找回密码
 立即注册
查看: 38|回复: 7

stc8H8K64U RTC调试中遇到的奇怪问题

[复制链接]
  • 打卡等级:偶尔看看I
  • 打卡总天数:11
  • 最近打卡:2025-12-11 10:05:47

3

主题

29

回帖

215

积分

中级会员

积分
215
发表于 7 天前 | 显示全部楼层 |阅读模式
最近做项目需要用到RTC功能,于是使用stc芯片内置的RTC。参考了例程和说明书,发现还是有些问题解决不了,于是归纳一下,到此处看看有无大神可以教我。
项目使用stc8H8K64U芯片,需要使用定时器,串口,ADC,PWM和RTC。于是从官网下载了STC8H的函数资料包,在例程“多路ADC转换-串口2发送”的基础上逐步增加功能测试。用以实现定时器每秒输出2路ADC值和RTC时间。
在增加了RTC功能后发现


1、RTC校时后,时钟不启动

     起初使用串口指令方式单独修改一个参数(年,月,日,时,分,秒),一切正常可以。但是使用STCISP软件中的RTC对时功能后发现可以一次性把所有参数都修改,但是修改后秒数不变。后来发现人为发送RTCCFG |=0X01指令3-4次后才开始变化。
2、RTC中断不能开
     在不开启RTC中断时,程序还能运行,RTC勉强能用。但是开启中断后程序变得不可运行。
     开启秒中断。下载程序1秒后直接死机或不断重启。
     开启分钟中断。下载程序60秒后死机或重启。
我尝试过使用库函数和配置寄存器的方式来实现上述内容,但是效果都一样。
我尝试过使用RTC芯片PCF8563加芯片IIC总线来实现RTC功能,但是一开IIC后RTC功能正常了,ADC变得不可用,输出全零。
以下是部分程序

void main(void)
{
        u16 duty1,duty2;
        u8 i;
  init();
        while (1)
        {
                if(B_save)
                   {       
                     B_save=0;
                     EEPROM_write_n(EEPROM_ADD,&GlobalArray,length);      //写入EEPROM
                     B_beep_tweet=1;
                    }
                if(B_UART1_RXOK)
                {
                        B_UART1_RXOK=0;
                        UART_Processing();
                }
        //************STC-ISP RTC对时***************
                if((RX1_Buffer[0]==0xa0)&&(RX1_Buffer[1]==0xff)&&(RX1_Buffer[2]==0xbc)&&(RX1_Buffer[3]==0xff))
                {       
                        i=P_SW2;
                        P_SW2 |=0x80;
                        INIYEAR =        RX_Buffer[5];
                        INIMONTH=        RX_Buffer[6];
                        INIDAY  = RX_Buffer[7];
                        INIHOUR = RX_Buffer[9];
                        INIMIN  = RX_Buffer[10];
                        INISEC  = RX_Buffer[11];
                        RTCCFG                 |=0x01;
                        delay_ms(100);
                        RTCCFG                 |=0x01;
                        delay_ms(100);
                        P_SW2 =i;
                }
                if(B_adcOK)
                 {
                        B_adcOK=0;
                        _adc[0] = (1.0 / (1.0 / 298.15 + log((float)ADC_MedianAverage(0) / (4096.0-(float)ADC_MedianAverage(0))) / 3950) - 273.15)*10;
                        _adc[1] = (1.0 / (1.0 / 298.15 + log((float)ADC_MedianAverage(1) / (4096.0-(float)ADC_MedianAverage(1))) / 3950) - 273.15)*10;       
                 }                       
                 if(B_sec)
                {
                        B_sec=0;
                        LED=!LED;
                        switch (debug_show)
                        {
                                //*********显示加热通道1参数
                                case 0x03:
//                                                TX1_send_u8(GlobalArray[set_T1]);                                //设定温度1
                                                TX1_send_int(adc_d[0]);TX1_write2buff('v');TX1_write2buff(' ');
                                                TX1_send_int(Temper[0]);TX1_write2buff('C');TX1_write2buff(' ');
                                                TX1_write2buff('#');TX1_write2buff(GlobalArray[PID1_flag]+'0');TX1_write2buff(' ');                                                                               
                                                TX1_send_int(PID1.SetPosition);
                                                TX1_send_int(PID1.position);
                                                TX1_send_int(PID1.error);
                                                TX1_send_int(PID1.pwm_duty);       
                                                TX1_write2buff('%');
                                        break;
                                //*********显示加热通道2参数
                                case 0x04:
                                                TX1_send_u8(GlobalArray[set_T2]);                                //设定温度2
                                                TX1_send_int(Temper[1]);
                                        break;
                                default:break;
                        }
                        printf("Year=20%bd,Month=%bd,Day=%bd,Hour=%bd,Minute=%bd,Second=%bd\r\n",YEAR,MONTH,DAY,HOUR,MIN,SEC);       
                }
   
        }
}


void        RTC_config(void)
{
//选择内部32k
//        IRC32KCR=0x80;
//        while(!(IRC32KCR & 0x01));
//        RTCCFG |= 0x02;
//选择外部32k
        X32KCR = 0xC0;
        while(!(X32KCR & 0x01));
        RTCCFG &=~0x02;
        INISSEC = 0;
        RTCCFG |= 0x01;                        //触发RTC寄存器初始化
        RTCIF = 0;                                        //清中断标志
        RTCIEN = 0x08;                        //秒中断使能
        RTCCR  = 0x01;                        //RTC使能
}

void init()
{
//**********GPIO初始化*******************
    P0M0 = 0x80; P0M1 = 0x60;         //P05,P06高阻P07推挽
    P1M0 = 0x00; P1M1 = 0xfb;
    P2M0 = 0x0f; P2M1 = 0x00;        
    P3M0 = 0x00; P3M1 = 0x00;
    P4M0 = 0x00; P4M1 = 0x00;
    P5M0 = 0x00; P5M1 = 0x00;                  
               
//**********读取EEPROM*******************  
    EEPROM_read_n(EEPROM_ADD,GlobalArray,length);       
//**********RTC初始化*******************               

//**********                ***************
        EAXSFR();                /* 扩展寄存器访问使能 */
                RTC_config();
//**********ADC初始化*******************
    ADC_config();
//**********Timer初始化*******************
    Timer_config();
//**********UART初始化*******************   
                UART_config();
                       
               

       

        EA = 1;
        printf("Infusion Heater Control\r\n");        //UART1发送一个字符串
    B_adcOK=0;
}


void UART_Processing()
{
        if(RX_Buffer[0]==0xa0)
        {
                B_beep_tweet=1;
                switch(RX_Buffer[2])
                {     
                        case 0x00:
                                switch(RX_Buffer[3])
                                {
                                        case 0x00:
                                                        //手动初始化RTC   
                                                        if(RX_Buffer[4]==0x01)
                                                        {

                                                                RTCCR |= 0x01;
                                                        }
                                                break;                                                       
                                               
                                        case 0x01:
                                        //***************debug show*****************       
                                        debug_show=RX_Buffer[4];
                                        switch(RX_Buffer[4])
                                        {
                                                case 0x01:                //输出所有globalarray数据
//                                                                debug_show=RX_Buffer[4];
                                                                for(i=0;i<length;i++)
                                                                {
                                                                        TX1_write2buff(i/10+'0');
                                                                        TX1_write2buff(i%10+'0');
                                                                        TX1_write2buff(':');
                                                                        TX1_send_u8(GlobalArray[i]);
                                                                        delay_ms(2);
                                                                }
                                                        break;

                                        //********************设置RTC参数                *************************
                        case 0xb0:
                                switch(RX_Buffer[3])
                                {
                                       
                                        case 0x00:                                                //设置RTC-时
                                                        GlobalArray[Hour]                                                 = RX_Buffer[4];
                                                        //editRTC(0,RX_Buffer[4]);
                                                break;
                                        case 0x03:                                                //设置RTC-分
                                                        GlobalArray[Min]                                                  = RX_Buffer[4];
                                                        //editRTC(1,RX_Buffer[4]);
                                                break;
                                        case 0x06:                                                //设置RTC-秒
                                                        GlobalArray[Sec]                                                  = RX_Buffer[4];
                                                        //editRTC(2,RX_Buffer[4]);
                                                break;
                                        case 0x09:                                                //设置RTC-日
                                                        GlobalArray[Day]                                                  = RX_Buffer[4];
                                                        //editRTC(3,RX_Buffer[4]);
                                                break;
                                        case 0x0c:                                                //设置RTC-月
                                                        GlobalArray[Month]                                                = RX_Buffer[4];
                                                        //editRTC(4,RX_Buffer[4]);
                                                break;
                                        case 0x0f:                                                //设置RTC-年
                                                        GlobalArray[Year]                                                 = RX_Buffer[4];
                                                        //editRTC(5,RX_Buffer[4]);
                                                break;
                                        default:break;
                                }
                                editRTC();
                               
                                break;                                       
                        default:break;
                }
        }               
}

回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:584
  • 最近打卡:2025-12-17 09:47:29

33

主题

2775

回帖

6154

积分

论坛元老

积分
6154
发表于 7 天前 | 显示全部楼层
原理图,工程,最好都发上来。

RTC正确使用的话是没问题的。

1. 触发RTC寄存器的初始化之后需要等待RTC初始化的完成。
2.你给的代码不全,又没有提供相应的工程。这里可能有几个问题,开了中断没有中断服务函数;使用13号中断,没有写跳转代码;
参考例程并不是对技术参 考手册的补充,而是对技术参 考手册的解释。
技术参 考手册不应该需要参考例程作为补充,而是解释成了参考例程的样子
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:11
  • 最近打卡:2025-12-11 10:05:47

3

主题

29

回帖

215

积分

中级会员

积分
215
发表于 7 天前 | 显示全部楼层
_奶*** 发表于 2025-12-11 11:22
原理图,工程,最好都发上来。

RTC正确使用的话是没问题的。

触发RTC寄存器的初始化之后需要等待多长时间?100ms够吗
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:584
  • 最近打卡:2025-12-17 09:47:29

33

主题

2775

回帖

6154

积分

论坛元老

积分
6154
发表于 7 天前 | 显示全部楼层
al*** 发表于 2025-12-11 13:16
触发RTC寄存器的初始化之后需要等待多长时间?100ms够吗

有标志位啊,读标志位啊
参考例程并不是对技术参 考手册的补充,而是对技术参 考手册的解释。
技术参 考手册不应该需要参考例程作为补充,而是解释成了参考例程的样子
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:11
  • 最近打卡:2025-12-11 10:05:47

3

主题

29

回帖

215

积分

中级会员

积分
215
发表于 7 天前 | 显示全部楼层
按照这个思路,我修改了RTC初始化程序。在RTC使能后加了500ms延时。修改例程里面的RTC中断程序来测试,每秒中断时点亮/熄灭led。结果是烧写程序后重新启动,重启几次后不死机了,可以正常工作了。但是RTC中断没有动作。
void        RTC_config(void)
{
        u8 i;
        i=P_SW2;
        P_SW2 |=0x80;
//选择内部32k
//        IRC32KCR=0x80;
//        while(!(IRC32KCR & 0x01));
//        RTCCFG |= 0x02;
//选择外部32k
        X32KCR = 0xC0;
        while(!(X32KCR & 0x01));
        RTCCFG &=~0x02;
        INISSEC = 0;
        RTCCFG |= 0x01;                        //触发RTC寄存器初始化
        RTCIF = 0;                                        //清中断标志
        RTCIEN = 0x08;                        //秒中断使能
        RTCCR  = 0x01;                        //RTC使能
        delay_ms(500);
        P_SW2=i;
}

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_RTC1sec = 1;
                LED=!LED;
        }
}
截图202512111332585333.jpg
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:584
  • 最近打卡:2025-12-17 09:47:29

33

主题

2775

回帖

6154

积分

论坛元老

积分
6154
发表于 7 天前 | 显示全部楼层
终于是看到你的中断服务函数了,看起来你是用了13号中断跳转RTC中断。那么你的工程里面加了对应的汇编代码了么
参考例程并不是对技术参 考手册的补充,而是对技术参 考手册的解释。
技术参 考手册不应该需要参考例程作为补充,而是解释成了参考例程的样子
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:11
  • 最近打卡:2025-12-11 10:05:47

3

主题

29

回帖

215

积分

中级会员

积分
215
发表于 7 天前 | 显示全部楼层
_奶*** 发表于 2025-12-11 14:06
终于是看到你的中断服务函数了,看起来你是用了13号中断跳转RTC中断。那么你的工程里面加了对应的汇编代码 ...

看到你的回复,我突然意识到是中断号错了。特意到stc8h.h文件里面去查了RTC的中断号,原来应该是36。将中断函数修改了一下。但是问题依旧
void RTC_ISR_Handler (void) interrupt RTC_VECTOR//RTC_VECTOR
{
        // TODO: 在此处添加用户代码
//        if(RTCIF & 0x80)    //闹钟中断
//        {
////                P01 = !P01;
//                RTCIF &= ~0x80;
//                B_Alarm = 1;
//        }

        if(RTCIF & 0x08)    //秒中断
        {
//                P00 = !P00;
                RTCIF &= ~0x08;
                B_RTC1sec = 1;
                LED=!LED;
        }
}

回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:647
  • 最近打卡:2025-12-18 07:29:35
已绑定手机

93

主题

6938

回帖

1万

积分

超级版主

积分
13022
发表于 7 天前 | 显示全部楼层
跑飞或死机可能是中断没有正确跳转,使用中断13跳转需要保证汇编程序正确,建议使用中断号扩展插件
注意RTC的时钟源是外部32768晶振,和CPU时钟是异步的
RTC程序供参考,使用ISP软件的RTC对时功能,命令头01 0B:

截图202512111635154487.jpg

  1. #include <AI8H.H>
  2. #include <intrins.h>
  3. #include <absacc.h>
  4. #include <string.h>
  5. #include <stdarg.h>
  6. #include <stdio.h>
  7. #include <math.h>
  8. //#define                TR                                P33
  9. #define                FOSC                        24000000UL                                        //主时钟
  10. #define                BAUD                        9600UL                                                //波特率
  11. #define                TMRF                        200UL                                                //定时器频率
  12. #define                BRT                                (0x10000-(FOSC/BAUD+2)/4)        //波特率发生器值
  13. #define                TMR                                (0x10000-FOSC/TMRF/12)                //定时器值
  14. #define                T_Buf_Len                64                                                        //Uart1发送缓存长度
  15. #define                R_Buf_Len                64                                                        //Uart1接收缓存长度
  16. #define                Master_Addr                0x00                                                //Uart主机地址
  17. #define                Slave_Addr                0x01                                                //Uart从机地址
  18. #define                Broad_Addr                0xFF                                                //Uart广播地址
  19. //#define                R                                0                                                        //485接收
  20. //#define                T                                1                                                        //485发送
  21. unsigned char                RP;                                        //Uart1接收指针
  22. unsigned char                TP;                                        //Uart1发送指针
  23. unsigned char                Uart_R_Len;                        //Uart1接收长度
  24. unsigned char                Uart_T_Len;                        //Uart1发送长度
  25. unsigned char xdata        R_Buf[R_Buf_Len];        //Uart1接收缓存
  26. unsigned char xdata        T_Buf[T_Buf_Len];        //Uart1发送缓存
  27. bit RTC_1s_Flag;
  28. void Delay_ms(unsigned char ms)
  29. {
  30.         unsigned int i;
  31.         do
  32.         {
  33.                 i=FOSC/10000;
  34.                 while(--i);        //10T per loop
  35.         }
  36.         while(--ms);
  37. }
  38. void UART_Send(unsigned int x)
  39. {
  40.         while(Uart_T_Len);
  41.         TP=0;
  42.         Uart_T_Len=x;
  43.         TI=1;
  44. }
  45. void Uart_Printf(unsigned char *v,...)
  46. {
  47.         va_list ap;
  48.         va_start(ap,v);
  49.         while(Uart_T_Len);
  50.         UART_Send(vsprintf(T_Buf,v,ap));
  51.         va_end(ap);
  52. }
  53. //void UART_Return(unsigned char temp)
  54. //{
  55. //        memcpy(T_Buf,R_Buf,temp);
  56. //        UART_Send(temp);
  57. //}
  58. void Init(void)
  59. {
  60.         P_SW2|=EAXFR;
  61.         
  62.         P0M1=0x00;        P0M0=0x00;        //设置IO模式
  63.         P1M1=0xC0;        P1M0=0x00;        //设置IO模式
  64.         P2M1=0x00;        P2M0=0x00;        //设置IO模式
  65.         P3M1=0x00;        P3M0=0x00;        //设置IO模式
  66.         P4M1=0x00;        P4M0=0x00;        //设置IO模式
  67.         P5M1=0x00;        P5M0=0x00;        //设置IO模式
  68.         P6M1=0x00;        P6M0=0x00;        //设置IO模式
  69.         P7M1=0x00;        P7M0=0x00;        //设置IO模式
  70.         
  71.         X32KCR=0x80;                        //启动外部32.768KHz晶振
  72.         while(!(X32KCR&0x01));        //等待外部32.768KHz晶振稳定
  73.         RTCCFG=0x00;                        //RTC选择外部32.768KHz时钟源
  74.         
  75.         AUXR=0x05;                //设置定时器0时钟为12T模式,设置定时器2为1T模式,设置定时器2为波特率发生器
  76.         TMOD=0x01;                //设置定时器0为16位不自动重装载模式
  77.         TH0=TMR>>8;                //设置定时器0初始值
  78.         TL0=TMR;                //设置定时器0初始值
  79.         TF0=0;                        //清除TF0中断标志位
  80.         ET0=1;                        //启用定时器0中断
  81.         
  82.         SCON=0x50;                //设置UART1模式为8位数据可变波特率
  83.         T2H=BRT>>8;                //设置UART1波特率
  84.         T2L=BRT;                //设置UART1波特率
  85.         AUXR|=T2R;                //打开定时器2
  86.         ES=1;                        //启用UART1中断
  87.         
  88.         INIYEAR                =25;        //初始化年
  89.         INIMONTH        =1;                //初始化月
  90.         INIDAY                =1;                //初始化日
  91.         INIHOUR                =0;                //初始化时
  92.         INIMIN                =0;                //初始化分
  93.         INISEC                =0;                //初始化秒
  94.         INISSEC                =0;                //初始化1/128秒
  95.         INIWEEK                =3;                //初始化星期
  96.         
  97.         RTCCFG|=0x01;                //初始化RTC
  98.         
  99.         RTCIF=0x00;                //清除RTC中断标志
  100.         RTCIEN=0x08;        //启用RTC秒中断
  101.         RTCCR=0x01;                //打开RTC
  102.         
  103.         EA=1;                        //启用总中断
  104. }
  105. void main(void)
  106. {
  107.         Init();
  108.         while(1)
  109.         {
  110.                 if(RTC_1s_Flag)
  111.                 {
  112.                         RTC_1s_Flag=0;
  113.                         Uart_Printf("\r\n\r\n20%02bu/%02bu/%02bu 星期%bu %02bu:%02bu:%02bu\r\n",YEAR,MONTH,DAY,WEEK,HOUR,MIN,SEC);
  114.                 }
  115.         }
  116. }
  117. void Uart_Start(void)
  118. {
  119.         TH0=TMR>>8;
  120.         TL0=TMR;
  121.         TR0=1;
  122. }
  123. void Uart_Stop(void)
  124. {
  125.         TR0=0;
  126.         TH0=TMR>>8;
  127.         TL0=TMR;
  128.         RP=0;
  129.         memset(R_Buf,0x00,sizeof R_Buf);
  130. }
  131. void TMR0_Isr(void) interrupt TMR0_VECTOR
  132. {
  133. //        UART_Return(RP);
  134.         Uart_Stop();
  135. }
  136. void UART1_Isr(void) interrupt UART1_VECTOR
  137. {
  138.         if(RI)
  139.         {
  140.                 RI=0;
  141.                 Uart_Start();
  142.                 R_Buf[RP]=SBUF;
  143.                 if(RP==0)
  144.                 {
  145.                         if(R_Buf[0]==Slave_Addr||R_Buf[0]==Broad_Addr)
  146.                         {
  147.                                 
  148.                         }
  149.                         else
  150.                         {
  151.                                 Uart_Stop();
  152.                         }
  153.                 }
  154.                 else if(RP==1)
  155.                 {
  156.                         if(R_Buf[1]==0x0B)
  157.                         {
  158.                                 Uart_R_Len=R_Buf[1]+2;
  159.                         }
  160.                         else
  161.                         {
  162.                                 Uart_Stop();
  163.                         }
  164.                 }
  165.                 else if(RP==Uart_R_Len-1)
  166.                 {
  167.                         INIYEAR=        R_Buf[3];        //初始化年
  168.                         INIMONTH=        R_Buf[4];        //初始化月
  169.                         INIDAY=                R_Buf[5];        //初始化日
  170.                         INIHOUR=        R_Buf[7];        //初始化时
  171.                         INIMIN=                R_Buf[8];        //初始化分
  172.                         INISEC=                R_Buf[9];        //初始化秒
  173.                         INISSEC=        0;                        //初始化1/128秒
  174.                         INIWEEK=        R_Buf[6];        //初始化星期
  175.                         RTCCFG|=0x01;                        //初始化RTC
  176.                         Uart_Stop();
  177.                 }
  178.                 else if(RP==R_Buf_Len-1)
  179.                 {
  180.                         Uart_Stop();
  181.                 }
  182.                 if(TR0)
  183.                 {
  184.                         RP++;
  185.                 }
  186.         }
  187.         if(TI)
  188.         {
  189.                 TI=0;
  190.                 if(TP==Uart_T_Len)
  191.                 {
  192. //                        TR=R;
  193.                         TP=0;
  194.                         Uart_T_Len=0;
  195.                 }
  196.                 if(Uart_T_Len!=0)
  197.                 {
  198. //                        TR=T;
  199.                         SBUF=(T_Buf[TP]);
  200.                         TP++;
  201.                 }
  202.         }
  203. }
  204. void RTC_Isr(void) interrupt RTC_VECTOR
  205. {
  206. //        if(RTCIF&0x80)        //闹钟中断
  207. //        {
  208. //                RTCIF&=~0x80;
  209. //        }
  210. //        if(RTCIF&0x40)        //日中断
  211. //        {
  212. //                RTCIF&=~0x40;
  213. //        }
  214. //        if(RTCIF&0x20)        //时中断
  215. //        {
  216. //                RTCIF&=~0x20;
  217. //        }
  218. //        if(RTCIF&0x10)        //分中断
  219. //        {
  220. //                RTCIF&=~0x10;
  221. //        }
  222.         if(RTCIF&0x08)        //秒中断
  223.         {
  224.                 RTCIF&=~0x08;
  225.                 RTC_1s_Flag=1;
  226.         }
  227. //        if(RTCIF&0x04)        //1/2秒中断
  228. //        {
  229. //                RTCIF&=~0x04;
  230. //        }
  231. //        if(RTCIF&0x02)        //1/8秒中断
  232. //        {
  233. //                RTCIF&=~0x02;
  234. //        }
  235. //        if(RTCIF&0x01)        //1/32秒中断
  236. //        {
  237. //                RTCIF&=~0x01;
  238. //        }
  239. }
复制代码


回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-12-18 10:25 , Processed in 0.128148 second(s), 82 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表