找回密码
 立即注册
查看: 19|回复: 5

关于STC8H8K64U RTC 打印时间不变的问题

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-09-18 08:43:19
已绑定手机

1

主题

3

回帖

35

积分

新手上路

积分
35
发表于 3 小时前 | 显示全部楼层 |阅读模式
#include "STC8H.h"
#include "stdio.h"
#include "intrins.h"

typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;

/****************************** 用户定义宏 ***********************************/
#define MAIN_Fosc     24000000L   //定义主时钟
#define PrintUart     1           //1:printf 使用 UART1; 2:printf 使用 UART2
#define Baudrate      115200L
#define TM            (65536 -(MAIN_Fosc/Baudrate/4))

/*************  本地变量声明    **************/
bit B_1s;

/******************** 串口打印函数 ********************/
void UartInit(void)
{
#if(PrintUart == 1)
    SCON = (SCON & 0x3f) | 0x40;
    AUXR |= 0x40;       //定时器时钟1T模式
    AUXR &= 0xFE;       //串口1选择定时器1为波特率发生器
    TL1  = TM;
    TH1  = TM>>8;
    TR1 = 1;            //定时器1开始计时
#else
    P_SW2 |= 1;         //UART2 switch to: 0: P1.0 P1.1,  1: P4.6 P4.7
    S2CON &= ~(1<<7);   //8位数据, 1位起始位, 1位停止位, 无校验
    T2L  = TM;
    T2H  = TM>>8;
    AUXR |= 0x14;       //定时器2时钟1T模式,开始计时
#endif
}

void UartPutc(unsigned char dat)
{
#if(PrintUart == 1)
    SBUF = dat;
    while(TI == 0);
    TI = 0;
#else
    S2BUF  = dat;
    while((S2CON & 2) == 0);
    S2CON &= ~2;    //Clear Tx flag
#endif
}

char putchar(char c)
{
    UartPutc(c);
    return c;
}

// RTC配置函数
void RTC_config(void)
{

    IRC32KCR = 0x80;            // 内部32K晶振受工作电压和环境温度影响极大,误差很大,不使用内部晶振
    while(!(IRC32KCR & 0x01));  // 等待时钟稳定
    RTCCFG = 0x02;                    // 选择内部 32K 作为时钟源

    // 设置初始时间:2025年09月17日 08时30分00秒
    INIYEAR = 0x25;     // BCD格式:25年
    INIMONTH = 0x09;    // BCD格式:09月
    INIDAY = 0x17;      // BCD格式:17日
    INIHOUR = 0x08;     // BCD格式:08时
    INIMIN = 0x30;      // BCD格式:30分
    INISEC = 0x00;      // BCD格式:00秒
    INISSEC = 0x00;     // S/128:0
    RTCCFG |= 0x01;   // 将 初始时间赋值到 RTC中


    RTCIF = 0x00;       //清中断标志
    RTCIEN = 0x88;      //使能秒中断
    RTCCR = 0x01;       //RTC使能

    while(RTCCFG & 0x01); //等待初始化完成



}

/******************** RTC中断函数 *********************/

void RTC_Isr(void) interrupt 13
{
    if(RTCIF & 0x08)    // 秒中断
    {
        RTCIF &= ~0x08; // 清除中断标志
        B_1s = 1;       // 设置1秒标志
//        printf("RTC Interrupt Triggered\n"); // 调试输出
    }
}


/**********************************************/
void main(void)
{
    P_SW2 |= 0x80;  //扩展寄存器(XFR)访问使能

    // 初始化串口
    UartInit();

    // 初始化RTC
    RTC_config();


    EA = 1;         //打开总中断


    while(1)
    {
        if(B_1s)
        {
            B_1s = 0;

            // 读取当前RTC时间
            RTCCFG |= 0x80;  // 触发RTC寄存器更新
            printf("20%02x-%02x-%02x %02x:%02x:%02x\r\n",
                  INIYEAR, INIMONTH, INIDAY, INIHOUR, INIMIN, INISEC);
            RTCCFG |= 0x80;  // 再次触发以防止读取错误
        }
    }
}




[08:31:10.341]接收←202509-1708-3000 00:00:00

[08:31:11.585]接收←202509-1708-3000 00:00:00

[08:31:12.840]接收←202509-1708-3000 00:00:00

[08:31:14.098]接收←202509-1708-3000 00:00:00

[08:31:15.346]接收←202509-1708-3000 00:00:00

[08:31:16.606]接收←202509-1708-3000 00:00:00

[08:31:17.850]接收←202509-1708-3000 00:00:00

[08:31:19.102]接收←202509-1708-3000 00:00:00

[08:31:20.360]接收←202509-1708-3000 00:00:00

请教前辈 我这个程序打印出来的时间不会变化 问题出在哪里呢?

回复

使用道具 举报 送花

3

主题

1968

回帖

784

积分

等待验证会员

积分
784
发表于 3 小时前 | 显示全部楼层
关于你提到的 STC8H8K64U 使用 RTC 模块时打印时间不变 的问题,这是一个在嵌入式开发中常见的问题。下面我将从几个角度进行专业分析,并提供排查建议与可能的解决方案。

一、问题描述回顾

你使用的是 STC8H8K64U 单片机,配置了 RTC(实时时钟)模块,并通过串口(UART)打印当前时间。然而,打印出来的时间始终不变,即 RTC 没有正常计时。

二、可能原因分析

1. RTC 模块未正确初始化
RTC 是一个独立的时钟模块,通常需要以下初始化步骤:
使能 RTC 电源
设置 RTC 时钟源(通常是 32.768kHz 晶振)
初始化时间寄存器(年、月、日、时、分、秒)
启动 RTC 模块

如果这些步骤未正确执行,RTC 将无法开始计时。

2. RTC 时钟源未启用或配置错误
STC8H 系列单片机的 RTC 模块通常依赖外部 32.768kHz 晶振作为时钟源。若该晶振未连接、损坏或未在代码中正确配置,RTC 将无法正常工作。

3. 中断未开启或中断服务未正确处理
RTC 通常通过中断方式通知系统时间更新。若未开启全局中断或 RTC 中断使能位未设置,或者中断服务函数未正确编写,可能导致时间无法更新。

4. 时间读取方式错误
RTC 的时间寄存器是只读的,读取时需注意:
是否需要先触发“读时间”命令
是否需要等待寄存器更新完成(BUSY 标志)
是否使用了正确的数据格式(BCD 或二进制)

5. 串口通信异常
虽然你提到时间打印不变,但也不能排除串口通信异常导致打印数据不变的可能性。例如波特率配置错误、发送缓冲区未刷新等。

三、推荐排查步骤

步骤 1:检查 RTC 初始化代码

请确保 RTC 初始化流程完整,包括:
  1. c
  2. RTCCLKSRC = 0x03;        // 设置 RTC 时钟源为外部 32.768kHz
  3. RTCCTRL |= 0x80;         // 启动 RTC 模块
  4. RTCCTRL |= 0x01;         // 允许 RTC 秒中断
复制代码

同时,初始化时间寄存器(如 RTCYEAR、RTCMONTH、RTCDAY、RTCHOUR、RTCMIN、RTCSEC)为当前时间。

步骤 2:检查中断配置

确保以下几点:
全局中断使能:EA = 1;
RTC 中断使能:RTCCTRL |= 0x01;
编写 RTC 中断服务函数,并在其中读取时间:
  1. c
  2. void RTCISR(void) interrupt 10 {
  3.     if (RTCINTFLAG & 0x01) {
  4.         // 读取当前时间
  5.         RTCINTFLAG |= 0x01; // 清除中断标志
  6.     }
  7. }
复制代码

步骤 3:检查时间读取逻辑

读取 RTC 时间寄存器时,应等待 BUSY 标志清零:
  1. c
  2. while (RTCSTAT & 0x80); // 等待 RTC 不忙
  3. year = RTCYEAR;
  4. month = RTCMONTH;
  5. day = RTCDAY;
  6. hour = RTCHOUR;
  7. min = RTCMIN;
  8. sec = RTCSEC;
复制代码

步骤 4:检查晶振连接
检查外部 32.768kHz 晶振是否连接正确
检查负载电容是否匹配(通常为 12.5pF)
若使用内部低功耗时钟,请确认是否支持 RTC 功能

步骤 5:检查串口打印逻辑
波特率是否正确设置(你代码中设置为 115200)
UART 是否正常工作(可尝试打印固定字符串测试)
是否在中断中频繁调用 printf 导致阻塞

四、示例代码参考(RTC 初始化与时间读取)

以下为一个简化的 RTC 初始化与读取时间的示例:
  1. c
  2. void RTCInit(void) {
  3.     RTCCLKSRC = 0x03;    // 使用外部 32.768kHz 晶振
  4.     RTCYEAR = 23;        // 设置年份(如 2023)
  5.     RTCMONTH = 10;       // 设置月份
  6.     RTCDAY = 15;         // 设置日期
  7.     RTCHOUR = 14;        // 设置小时
  8.     RTCMIN = 30;         // 设置分钟
  9.     RTCSEC = 0;          // 设置秒
  10.     RTCCTRL |= 0x80;     // 启动 RTC
  11.     RTCCTRL |= 0x01;     // 使能秒中断
  12. }
  13. void ReadRTCTime(void) {
  14.     while (RTCSTAT & 0x80); // 等待 RTC 不忙
  15.     year = RTCYEAR;
  16.     month = RTCMONTH;
  17.     day = RTCDAY;
  18.     hour = RTCHOUR;
  19.     min = RTCMIN;
  20.     sec = RTCSEC;
  21. }
复制代码

五、总结与建议

| 检查项 | 建议 |
|--------|------|
| RTC 初始化 | 确保设置时钟源、启动模块、设置初始时间 |
| 中断配置 | 开启全局中断、RTC中断使能、编写中断服务函数 |
| 时间读取 | 等待 BUSY 标志,正确读取寄存器 |
| 晶振 | 检查外部晶振连接与参数 |
| 串口通信 | 验证 UART 是否正常工作,避免干扰主流程 |

六、结语

RTC 模块是嵌入式系统中实现时间管理的重要组件,其配置和使用需要细致的硬件与软件配合。建议你在调试过程中逐步排查每个环节,尤其注意 RTC 的时钟源和中断处理逻辑。如仍有问题,欢迎提供完整代码片段,以便进一步分析。

祝你调试顺利!

[本文内容由国芯人工智能辅助生成,仅供参考]
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:132
  • 最近打卡:2025-09-18 08:31:07
已绑定手机

17

主题

492

回帖

1643

积分

金牌会员

积分
1643
发表于 3 小时前 | 显示全部楼层
%02bx
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:524
  • 最近打卡:2025-09-18 09:16:09

33

主题

2551

回帖

5563

积分

论坛元老

积分
5563
发表于 3 小时前 | 显示全部楼层
有木有一种可能,你读错寄存器了
截图202509180916058928.jpg
参考例程并不是对技术参 考手册的补充,而是对技术参 考手册的解释。
技术参 考手册不应该需要参考例程作为补充,而是解释成了参考例程的样子
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-09-18 08:43:19
已绑定手机

1

主题

3

回帖

35

积分

新手上路

积分
35
发表于 1 小时前 | 显示全部楼层
_奶*** 发表于 2025-9-18 09:16
有木有一种可能,你读错寄存器了

你讲的没错 // printf("Year=20%bd,Month=%bd,Day=%bd,Hour=%bd,Minute=%bd,Second=%bd\r\n",YEAR,MONTH,DAY,HOUR,MIN,SEC);

例程寄存器是YEAR ,头文件是RTCYEAR.
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-09-18 08:43:19
已绑定手机

1

主题

3

回帖

35

积分

新手上路

积分
35
发表于 1 小时前 | 显示全部楼层
SETRTC位置1时硬件会自动将寄存器INIYEAR,INIMONTH,INIDAY,INIHOUR,INIMIN,INISEC中的值复制到寄存器YEAR,MONTH,DAY,HOUR,MIN,SEC中。初始化完成后,硬件会自动将SETRTC位清0


我贴上读到的是初始值。 应该读YEAR等寄存器才对,各位还要注意 YEAR等寄存器头文件中是有RTC前缀,昨天调试直接用YEAR 总是编译错误。
回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-9-18 12:16 , Processed in 0.118437 second(s), 85 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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