RTC使用外部晶振的问题 | 已解决
求大佬帮助!在使用芯片STC8H1K08T作为主控的情况下,使用外部32.768K的晶振无法启动RTC,一直卡在while (!(X32KCR & 0x01) && timeout--) 的循环部分无法启动成功,选用的晶振匹配电容试过:20pf,15pf,12pf。三个均不行程序功能是先初始化RTC,然后使用STCISP获取实时时间写入RTC中(目前启动RTC晶振出现问题所以后面的功能还未实现)下面是代码:
#include "STC8H.h"
#include "stdio.h"
#include "intrins.h"
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;
#define MAIN_Fosc 22118400L //定义主时钟(精确计算115200波特率)
//#define UART1_BUF_LENGTH 128
#defineP1_MODE_IO_PU(Pin) P1M1 &= ~(Pin), P1M0 &= ~(Pin);
#defineP3_MODE_IO_PU(Pin) P3M1 &= ~(Pin), P3M0 &= ~(Pin);
#defineP1_MODE_IN_HIZ(Pin) P1M1 |= (Pin), P1M0 &= ~(Pin);
/*************本地变量声明 **************/
u8TX1_Cnt; //发送计数
u8RX1_Cnt; //接收计数
bit B_TX1_Busy; //发送忙标志
//u8RX1_Buffer; //接收缓冲
char code *STCRTC= "@STCRTC#"; //= "@STCRTC#";命令头
char indexrtc=0; //当前的命令头索引
char length =0; //长度
char rtctime ; //rtc时间数据
bitRec_OK = 0; //rtc时间获取完成标志
bit B_1S;
bit B_Alarm;
/****************RTC初始化函数 *****************/
void RTC_config(void)
{
u16 timeout = 10000;
X32KCR = 0xc0; // 启动外部32K晶振
while (!(X32KCR & 0x01) && timeout--)
_nop_();
if(!(X32KCR & 0x01)) {
printf("X32K Fail! Status: %02x\n", X32KCR);
}
RTCCFG &= ~0x02; // 选择外部32K时钟源
INIYEAR = 24; // 初始化时间
INIMONTH = 12;
INIDAY = 31;
INIHOUR = 23;
INIMIN = 59;
INISEC = 50;
INISSEC = 0;
RTCCFG |= 0x01;// 触发初始化
timeout = 10000;
while((RTCCFG & 0x01) && timeout--)
_nop_();
if(RTCCFG & 0x01) {
printf("RTC Init Timeout!\n");
}
RTCIF = 0; // 清中断标志
RTCIEN = 0x08; // 使能秒中断
RTCCR = 0x01; // 使能RTC
printf("RTC Init Done. Status: %02x\n", RTCCR);
}
char putchar(char dat)
{
B_TX1_Busy = 1; //标志发送忙
SBUF = dat; //发一个字节
while(B_TX1_Busy); //等待发送完成
return dat;
}
void Uart1_Init(void) //115200bps@24.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x01; //串口1选择定时器2为波特率发生器
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0xCC; //设置定时初始值
T2H = 0xFF; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
ES = 1; //使能串口1中断
}
void main(void)
{
EAXSFR();
EA = 1;
P1_MODE_IO_PU(0x80 | 0x40);//P16、P17用于外部晶振
P3_MODE_IO_PU(0x00 | 0x01);//P30、P31用于串口
Uart1_Init();
RTC_config();
// EA = 1;
while(1)
{
if(B_1S)
{
B_1S = 0;
printf("Year=20%bd ", YEAR);
printf("Month=%bd ", MONTH);
printf("Day=%bd ", DAY);
printf("Hour=%bd ", HOUR);
printf("Minute=%bd ", MIN);
printf("Second=%bd ", SEC);
printf("\r\n");
}
}
}
void UART1_int (void) interrupt 4
{
u8 dat;
if(RI)
{
RI = 0;
dat = SBUF;
// RX1_Buffer = SBUF;
// if(++RX1_Cnt >= UART1_BUF_LENGTH) RX1_Cnt = 0;
//-------------------------------串口RTC对时 -------------------------------
if( length>0 )
{
rtctime=dat;
length++;
if( length>=12 )
{
length = 0;
Rec_OK = 1;
indexrtc=0;
}
}
if (dat == STCRTC[ indexrtc])
{
indexrtc++;
if(STCRTC == '\0')
{
length = 1; //开启接收
indexrtc=0;
}
}
else
{
indexrtc = 0;
if (dat ==STCRTC[ indexrtc])
indexrtc++;
}
}
if(TI)
{
TI = 0;
B_TX1_Busy = 0;
}
}
void RTC_ISR_Handler (void) interrupt 13//RTC_VECTOR
{
// TODO: 在此处添加用户代码
if(RTCIF & 0x80) //闹钟中断
{
P01 = !P01;
RTCIF &= ~0x80;
B_Alarm = 1;
}
if(RTCIF & 0x08) //秒中断
{
P00 = !P00;
RTCIF &= ~0x08;
B_1S = 1;
}
}
求大佬解答{:baoquan:} 直接烧录8H实验箱例程包例子到芯片里试试:50-内部RTC时钟程序
下载时, 选择时钟 24MHz,串口大于RTC时钟信息。
实验箱例程包下载地址:https://www.stcai.com/syx
如果还是不起振的话,先排查板子有没有虚焊或者短路,没有的话换个晶振试试。 乘风飞扬 发表于 2025-8-6 14:41
直接烧录8H实验箱例程包例子到芯片里试试:50-内部RTC时钟程序
下载时, 选择时钟 24MHz,串口大于RTC时钟信 ...
我直接使用的试验箱的程序,还是不起振,打算换个晶振再试一试。{:xiaoku:} 晶振IO设置为高阻 DebugLab 发表于 2025-8-6 15:11
晶振IO设置为高阻
还是不行,无法起振。目前程序:#include "STC8H.h"
#include "stdio.h"
#include "intrins.h"
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;
#define MAIN_Fosc 22118400L //定义主时钟(精确计算115200波特率)
//#define UART1_BUF_LENGTH 128
#defineP1_MODE_IO_PU(Pin) P1M1 &= ~(Pin), P1M0 &= ~(Pin);
#defineP3_MODE_IO_PU(Pin) P3M1 &= ~(Pin), P3M0 &= ~(Pin);
#defineP1_MODE_IN_HIZ(Pin) P1M1 |= (Pin), P1M0 &= ~(Pin);
/*************本地变量声明 **************/
u8TX1_Cnt; //发送计数
u8RX1_Cnt; //接收计数
bit B_TX1_Busy; //发送忙标志
//u8RX1_Buffer; //接收缓冲
char code *STCRTC= "@STCRTC#"; //= "@STCRTC#";命令头
char indexrtc=0; //当前的命令头索引
char length =0; //长度
char rtctime ; //rtc时间数据
bitRec_OK = 0; //rtc时间获取完成标志
bit B_1S;
bit B_Alarm;
///****************RTC初始化函数 *****************/
//void RTC_config(void)
//{
//u16 timeout = 10000;
//
////X32KCR = 0xc0; // 启动外部32K晶振
////
////while (!(X32KCR & 0x01) && timeout--)
//// _nop_();
////
////if(!(X32KCR & 0x01)) {
//// printf("X32K Fail! Status: %02x\n", X32KCR);
////}
// INIYEAR = 24; // 初始化时间
//INIMONTH = 12;
//INIDAY = 31;
//INIHOUR = 23;
//INIMIN = 59;
//INISEC = 50;
//INISSEC = 0;
//
// IRC32KCR = 0x80; //启动内部32K晶振.
// while (!(IRC32KCR & 1) && timeout--)//等待时钟稳定
// _nop_();
//if(!(IRC32KCR & 0x01)) {
// printf("IRC32K Fail! Status: %02x\n", IRC32KCR);
//}
//RTCCFG = 0x03; //选择内部32K时钟源,触发RTC寄存器初始化
//
// RTCIF = 0; // 清中断标志
//
//RTCCR = 0x01; // 使能RTC
//
//timeout = 10000;
//while((RTCCFG & 0x01) && timeout--)
// _nop_();
//
//if(RTCCFG & 0x01) {
// printf("RTC Init Timeout!\n");
//}
//
//printf("RTC Init Done. Status: %02x\n", RTCCR);
//
//RTCIEN = 0x08; // 使能秒中断
//}
/****************RTC初始化函数 *****************/
void RTC_config(void)
{
u16 timeout = 10000;
X32KCR = 0xc0; // 启动外部32K晶振
while (!(X32KCR & 0x01) && timeout--)
_nop_();
if(!(X32KCR & 0x01)) {
printf("X32K Fail! Status: %02x\n", X32KCR);
}
RTCCFG &= ~0x02; // 选择外部32K时钟源
INIYEAR = 24; // 初始化时间
INIMONTH = 12;
INIDAY = 31;
INIHOUR = 23;
INIMIN = 59;
INISEC = 50;
INISSEC = 0;
RTCCFG |= 0x01;// 触发初始化
timeout = 10000;
while((RTCCFG & 0x01) && timeout--)
_nop_();
if(RTCCFG & 0x01) {
printf("RTC Init Timeout!\n");
}
RTCIF = 0; // 清中断标志
RTCIEN = 0x08; // 使能秒中断
RTCCR = 0x01; // 使能RTC
printf("RTC Init Done. Status: %02x\n", RTCCR);
}
char putchar(char dat)
{
B_TX1_Busy = 1; //标志发送忙
SBUF = dat; //发一个字节
while(B_TX1_Busy); //等待发送完成
return dat;
}
void Uart1_Init(void) //115200bps@24.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x01; //串口1选择定时器2为波特率发生器
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0xCC; //设置定时初始值
T2H = 0xFF; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
ES = 1; //使能串口1中断
}
void main(void)
{
EAXSFR();
EA = 1;
P1_MODE_IN_HIZ(0x80 | 0x40);//P16、P17用于外部晶振
P3_MODE_IO_PU(0x00 | 0x01);//P30、P31用于串口
Uart1_Init();
RTC_config();
// EA = 1;
while(1)
{
if(B_1S)
{
B_1S = 0;
printf("Year=20%bd ", YEAR);
printf("Month=%bd ", MONTH);
printf("Day=%bd ", DAY);
printf("Hour=%bd ", HOUR);
printf("Minute=%bd ", MIN);
printf("Second=%bd ", SEC);
printf("\r\n");
}
if(Rec_OK == 1)
{
// // 禁用RTC以安全更新参数
// RTCCR = 0x00; //RTC关闭
// YEAR = rtctime; //Y:2021 //单片机内部rtc时钟初始化的办法
// MONTH = rtctime; //M:12
// DAY = rtctime; //D:31
// HOUR = rtctime; //H:23
// MIN =rtctime; //M:59
// SEC = rtctime; //S:50
// SSEC = rtctime; //S/128:0
// RTCCR = 0x01; //RTC使能
Rec_OK = 0;
printf("%02d%02dyear %dmon %dday\t",(int)rtctime,(int)rtctime,(int)rtctime,(int)rtctime);
printf("%d:%d:%d.%d\t",(int)rtctime,(int)rtctime,(int)rtctime,(int)((u16)(rtctime*256)|(u8)rtctime));
printf("%d\r\n",(int)rtctime);
}
}
}
void UART1_int (void) interrupt 4
{
u8 dat;
if(RI)
{
RI = 0;
dat = SBUF;
// RX1_Buffer = SBUF;
// if(++RX1_Cnt >= UART1_BUF_LENGTH) RX1_Cnt = 0;
//-------------------------------串口RTC对时 -------------------------------
if( length>0 )
{
rtctime=dat;
length++;
if( length>=12 )
{
length = 0;
Rec_OK = 1;
indexrtc=0;
}
}
if (dat == STCRTC[ indexrtc])
{
indexrtc++;
if(STCRTC == '\0')
{
length = 1; //开启接收
indexrtc=0;
}
}
else
{
indexrtc = 0;
if (dat ==STCRTC[ indexrtc])
indexrtc++;
}
}
if(TI)
{
TI = 0;
B_TX1_Busy = 0;
}
}
void RTC_ISR_Handler (void) interrupt 13//RTC_VECTOR
{
// TODO: 在此处添加用户代码
if(RTCIF & 0x80) //闹钟中断
{
P01 = !P01;
RTCIF &= ~0x80;
B_Alarm = 1;
}
if(RTCIF & 0x08) //秒中断
{
P00 = !P00;
RTCIF &= ~0x08;
B_1S = 1;
}
}
目前使用的晶振为晶振链接 ccczzh 发表于 2025-8-6 15:29
还是不行,无法起振。目前程序:
测试正常的程序:
基于以下串口程序:
https://www.stcaimcu.com/thread-16321-1-1.html
串口对时,命令头01 0B
#include <AI8H.H>
#include <intrins.h>
#include <absacc.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <math.h>
#define FOSC 24000000UL //主时钟
#define BAUD 9600UL //波特率
#define TMRF 200UL //定时器频率
#define BRT (0x10000-(FOSC/BAUD+2)/4) //波特率发生器值
#define TMR (0x10000-FOSC/TMRF/12) //定时器值
#define T_Buf_Len 64 //Uart1发送缓存长度
#define R_Buf_Len 64 //Uart1接收缓存长度
unsigned char RP; //Uart1接收指针
unsigned char TP; //Uart1发送指针
unsigned char Uart_R_Len; //Uart1接收长度
unsigned char Uart_T_Len; //Uart1发送长度
unsigned char xdata R_Buf; //Uart1接收缓存
unsigned char xdata T_Buf; //Uart1发送缓存
bit RTC_1s_Flag;
void Delay_ms(unsigned char ms)
{
unsigned int i;
do
{
i=FOSC/10000;
while(--i); //10T per loop
}
while(--ms);
}
void UART_Send(unsigned int x)
{
while(Uart_T_Len);
TP=0;
Uart_T_Len=x;
TI=1;
}
void Uart_Printf(unsigned char *v,...)
{
va_list ap;
va_start(ap,v);
while(Uart_T_Len);
UART_Send(vsprintf(T_Buf,v,ap));
va_end(ap);
}
void Init(void)
{
P_SW2|=EAXFR;
P0M1=0x00; P0M0=0x00; //设置IO模式
P1M1=0xC0; P1M0=0x00; //设置IO模式
P2M1=0x00; P2M0=0x00; //设置IO模式
P3M1=0x00; P3M0=0x00; //设置IO模式
P4M1=0x00; P4M0=0x00; //设置IO模式
P5M1=0x00; P5M0=0x00; //设置IO模式
P6M1=0x00; P6M0=0x00; //设置IO模式
P7M1=0x00; P7M0=0x00; //设置IO模式
X32KCR=0x80; //启动外部32.768KHz晶振
while(!(X32KCR&0x01)); //等待外部32.768KHz晶振稳定
RTCCFG=0x00; //RTC选择外部32.768KHz时钟源
AUXR=0x05; //设置定时器0时钟为12T模式,设置定时器2为1T模式,设置定时器2为波特率发生器
TMOD=0x01; //设置定时器0为16位不自动重装载模式
TH0=TMR>>8; //设置定时器0初始值
TL0=TMR; //设置定时器0初始值
TF0=0; //清除TF0中断标志位
ET0=1; //启用定时器0中断
SCON=0x50; //设置UART1模式为8位数据可变波特率
T2H=BRT>>8; //设置UART1波特率
T2L=BRT; //设置UART1波特率
AUXR|=T2R; //打开定时器2
ES=1; //启用UART1中断
INIYEAR =25; //初始化年
INIMONTH =1; //初始化月
INIDAY =1; //初始化日
INIHOUR =0; //初始化时
INIMIN =0; //初始化分
INISEC =0; //初始化秒
INISSEC =0; //初始化1/128秒
INIWEEK =3; //初始化星期
RTCCFG|=0x01; //初始化RTC
RTCIF=0x00; //清除RTC中断标志
RTCIEN=0x08; //启用RTC秒中断
RTCCR=0x01; //打开RTC
EA=1; //启用总中断
}
void main(void)
{
Init();
while(1)
{
if(RTC_1s_Flag)
{
RTC_1s_Flag=0;
Uart_Printf("\r\n\r\n20%02bu/%02bu/%02bu 星期%bu %02bu:%02bu:%02bu\r\n",RTCYEAR,RTCMONTH,RTCDAY,RTCWEEK,RTCHOUR,RTCMIN,RTCSEC);
}
Delay_ms(250);
Delay_ms(250);
}
}
void Uart_Start(void)
{
TH0=TMR>>8;
TL0=TMR;
TR0=1;
}
void Uart_Stop(void)
{
TR0=0;
TH0=TMR>>8;
TL0=TMR;
RP=0;
memset(R_Buf,0x00,sizeof R_Buf);
}
void TMR0_Isr(void) interrupt TMR0_VECTOR
{
Uart_Stop();
}
void UART1_Isr(void) interrupt UART1_VECTOR
{
if(RI)
{
RI=0;
Uart_Start();
R_Buf=SBUF;
if(RP==0)
{
if(R_Buf==0x01)
{
}
else
{
Uart_Stop();
}
}
else if(RP==1)
{
if(R_Buf==0x0B)
{
Uart_R_Len=R_Buf+2;
}
else
{
Uart_Stop();
}
}
else if(RP==Uart_R_Len-1)
{
INIYEAR= R_Buf; //初始化年
INIMONTH= R_Buf; //初始化月
INIDAY= R_Buf; //初始化日
INIHOUR= R_Buf; //初始化时
INIMIN= R_Buf; //初始化分
INISEC= R_Buf; //初始化秒
INISSEC= 0; //初始化1/128秒
INIWEEK= R_Buf; //初始化星期
RTCCFG|=0x01; //初始化RTC
Uart_Stop();
}
else if(RP==R_Buf_Len-1)
{
Uart_Stop();
}
if(TR0)
{
RP++;
}
}
if(TI)
{
TI=0;
if(TP==Uart_T_Len)
{
TP=0;
Uart_T_Len=0;
}
if(Uart_T_Len!=0)
{
SBUF=(T_Buf);
TP++;
}
}
}
void RTC_Isr(void) interrupt RTC_VECTOR
{
// if(RTCIF&0x80) //闹钟中断
// {
// RTCIF&=~0x80;
// }
// if(RTCIF&0x40) //日中断
// {
// RTCIF&=~0x40;
// }
// if(RTCIF&0x20) //时中断
// {
// RTCIF&=~0x20;
// }
// if(RTCIF&0x10) //分中断
// {
// RTCIF&=~0x10;
// }
if(RTCIF&0x08) //秒中断
{
RTCIF&=~0x08;
RTC_1s_Flag=1;
}
// if(RTCIF&0x04) //1/2秒中断
// {
// RTCIF&=~0x04;
// }
// if(RTCIF&0x02) //1/8秒中断
// {
// RTCIF&=~0x02;
// }
// if(RTCIF&0x01) //1/32秒中断
// {
// RTCIF&=~0x01;
// }
}
DebugLab 发表于 2025-8-6 16:27
测试正常的程序:
基于以下串口程序:
https://www.stcaimcu.com/thread-16321-1-1.html
我测试还是不行,应该是我硬件选型和设计的问题,晶振有推荐的吗? ccczzh 发表于 2025-8-6 16:50
我测试还是不行,应该是我硬件选型和设计的问题,晶振有推荐的吗?
2*6mm直插:X206032768KGB2SC
3215贴片:XKXGI-SUA-32.768K
1610贴片:X161032768KGD2SI
页:
[1]
2