找回密码
 立即注册
查看: 2125|回复: 1

不停电下载保持RTC参数利用用户接口实现--STC32G系列

[复制链接]
  • 打卡等级:偶尔看看III
  • 打卡总天数:38
  • 最近打卡:2025-04-30 14:38:57

25

主题

977

回帖

3599

积分

超级版主

积分
3599
发表于 2023-2-1 12:51:31 | 显示全部楼层 |阅读模式
本帖最后由 zhp 于 2023-4-28 13:07 编辑

现有单片机系列的RTC模块,在单片机复位后RTC相关的特殊功能寄存器也会复位
本例程主要用于解决ISP下载后用户的RTC参数丢失的问题
解决思路:ISP下载前,先将RTC相关参数通过ISP下载软件的用户接口上传到PC保存,等待ISP下载完成后,下载软件再将保存的相关参数写入到FLASH的指定地址(范例中指定的地址为FE0000H)。ISP下载完成后会立即运行用户代码,用户程序在初始化RTC寄存器时,可从FLASH的指定地址中读取之前上传的RTC相关参数对RTC寄存器进行初始化,即可实现不停电下载保持RTC参数的目的。
  1. #include "stc32g.h"
  2. #include "intrins.h"
  3. #define FOSC        11059200UL
  4. #define BAUD        (65536 - FOSC/4/115200)
  5. typedef bit BOOL;
  6. typedef unsigned char BYTE;
  7. struct RTC_INIT
  8. {
  9.     BYTE bValidTag;         //数据有效标志(0x5a)
  10.     BYTE bIniYear;          //年(RTC初始化值)
  11.     BYTE bIniMonth;         //月
  12.     BYTE bIniDay;           //日
  13.     BYTE bIniHour;          //时
  14.     BYTE bIniMinute;        //分
  15.     BYTE bIniSecond;        //秒
  16.     BYTE bIniSSecond;       //次秒
  17.     BYTE bAlaHour;          //时(RTC闹钟设置值)
  18.     BYTE bAlaMinute;        //分
  19.     BYTE bAlaSecond;        //秒
  20.     BYTE bAlaSSecond;       //次秒
  21. };
  22. struct RTC_INIT ecode InitBlock _at_ 0xfe0000;
  23. void SysInit();
  24. void UartInit();
  25. void RTCInit();
  26. void SendUart(BYTE dat);
  27. void UnpackCmd(BYTE dat);
  28. void IapProgram(int addr, char dat);
  29. BOOL fUartBusy;
  30. BOOL fFetchRtc;
  31. BOOL fReset2Isp;
  32. BYTE bUartStage;
  33. BYTE bDump[7];
  34. void main()
  35. {
  36.     SysInit();                              //系统初始化
  37.     UartInit();
  38.     RTCInit();
  39.     EA = 1;
  40.     fUartBusy = 0;
  41.     fFetchRtc = 0;
  42.     fReset2Isp = 0;
  43.     bUartStage = 0;
  44.     while (1)
  45.     {
  46.         if (fFetchRtc)                      //获取RTC数据请求
  47.         {
  48.             fFetchRtc = 0;
  49.             RTCCR = 0;                      //上传当前的RTC值时,必须临时停止RTC,以免发生进位错误
  50.             bDump[0] = YEAR;                //快速将当前的RTC值缓存,以缩短RTC暂停的时间,减小误差
  51.             bDump[1] = MONTH;
  52.             bDump[2] = DAY;
  53.             bDump[3] = HOUR;
  54.             bDump[4] = MIN;
  55.             bDump[5] = SEC;
  56.             bDump[6] = SSEC;
  57.             RTCCR = 1;
  58.             
  59.             SendUart(0x5a);                 //上传12字节RTC参数
  60.             SendUart(bDump[0]);
  61.             SendUart(bDump[1]);
  62.             SendUart(bDump[2]);
  63.             SendUart(bDump[3]);
  64.             SendUart(bDump[4]);
  65.             SendUart(bDump[5]);
  66.             SendUart(bDump[6]);
  67.             SendUart(ALAHOUR);
  68.             SendUart(ALAMIN);
  69.             SendUart(ALASEC);
  70.             SendUart(ALASSEC);
  71.         }
  72.         if (fReset2Isp)                     //重启请求
  73.         {
  74.             fReset2Isp = 0;
  75.             IAP_CONTR = 0x60;               //软件触发复位到系统ISP区
  76.         }
  77.     }
  78. }
  79. void uart_isr() interrupt UART1_VECTOR
  80. {
  81.     BYTE dat;
  82.     if (TI)
  83.     {
  84.         TI = 0;
  85.         fUartBusy = 0;
  86.     }
  87.     if (RI)
  88.     {
  89.         RI = 0;
  90.         dat = SBUF;
  91.         switch (bUartStage++)               //解析串口命令
  92.         {
  93.         default:
  94.         case 0:
  95. L_Check1st:
  96.             if (dat == '@') bUartStage = 1;
  97.             else bUartStage = 0;
  98.             break;
  99.         case 1:
  100.             if (dat == 'F') bUartStage = 2;
  101.             else if (dat == 'R') bUartStage = 7;
  102.             else goto L_Check1st;
  103.             break;
  104.         case 2:
  105.             if (dat != 'E') goto L_Check1st;
  106.             break;
  107.         case 3:
  108.             if (dat != 'T') goto L_Check1st;
  109.             break;
  110.         case 4:
  111.             if (dat != 'C') goto L_Check1st;
  112.             break;
  113.         case 5:
  114.             if (dat != 'H') goto L_Check1st;
  115.             break;
  116.         case 6:
  117.             if (dat != '#') goto L_Check1st;
  118.             bUartStage = 0;
  119.             fFetchRtc = 1;                  //当前命令序列为获取RTC数据命令:"@FETCH#"
  120.             break;
  121.         case 7:
  122.             if (dat != 'E') goto L_Check1st;
  123.             break;
  124.         case 8:
  125.             if (dat != 'B') goto L_Check1st;
  126.             break;
  127.         case 9:
  128.         case 10:
  129.             if (dat != 'O') goto L_Check1st;
  130.             break;
  131.         case 11:
  132.             if (dat != 'T') goto L_Check1st;
  133.             break;
  134.         case 12:
  135.             if (dat != '#') goto L_Check1st;
  136.             bUartStage = 0;
  137.             fReset2Isp = 1;                 //当前命令序列为重启命令:"@REBOOT#"
  138.             break;
  139.         }
  140.     }
  141. }
  142. void rtc_isr() interrupt RTC_VECTOR         //RTC中断复位程序
  143. {
  144.     RTCIF = 0x00;                           //清RTC中断标志
  145.     P20 = !P20;                             //P2.0口每秒闪烁一次,测试用
  146. }
  147. void SysInit()
  148. {
  149.     WTST = 0;
  150.     CKCON = 0;
  151.     EAXFR = 1;
  152.     P0M0 = 0x00; P0M1 = 0x00;
  153.     P1M0 = 0x00; P1M1 = 0x00;
  154.     P2M0 = 0x00; P2M1 = 0x00;
  155.     P3M0 = 0x00; P3M1 = 0x00;
  156.     P4M0 = 0x00; P4M1 = 0x00;
  157.     P5M0 = 0x00; P5M1 = 0x00;
  158.     P6M0 = 0x00; P6M1 = 0x00;
  159.     P7M0 = 0x00; P7M1 = 0x00;
  160. }
  161. void UartInit()                             //串口初始化函数
  162. {
  163.     SCON = 0x50;
  164.     AUXR = 0x40;
  165.     TMOD = 0x00;
  166.     TL1 = BAUD;
  167.     TH1 = BAUD >> 8;
  168.     TR1 = 1;
  169.     ES = 1;
  170. }
  171. void RTCInit()                              //RTC初始化函数
  172. {
  173. //  IRC32KCR = 0x80;
  174. //  while (!(IRC32KCR & 0x01));
  175. //  RTCCFG |= 0x02;                         //选择内部32K为RTC时钟源
  176.     X32KCR = 0xc0;
  177.     while (!(X32KCR & 0x01));
  178.     RTCCFG &= ~0x02;                        //选择外部部32K为RTC时钟源
  179.     if (InitBlock.bValidTag == 0x5a)
  180.     {
  181.         INIYEAR  = InitBlock.bIniYear;      //如果初始化数据块有效,则使用数据块初始化RTC
  182.         INIMONTH = InitBlock.bIniMonth;
  183.         INIDAY   = InitBlock.bIniDay;
  184.         INIHOUR  = InitBlock.bIniHour;
  185.         INIMIN   = InitBlock.bIniMinute;
  186.         INISEC   = InitBlock.bIniSecond;
  187.         INISSEC  = InitBlock.bIniSSecond;
  188.         ALAHOUR  = InitBlock.bAlaHour;
  189.         ALAMIN   = InitBlock.bAlaMinute;
  190.         ALASEC   = InitBlock.bAlaSecond;
  191.         ALASSEC  = InitBlock.bAlaSSecond;
  192.         IapProgram(0x0000, 0x00);           //销毁初始化数据块,以免重复初始化
  193.     }
  194.     else
  195.     {
  196.         INIYEAR  = 23;                      //否则初始化RTC为默认值
  197.         INIMONTH = 1;
  198.         INIDAY   = 29;
  199.         INIHOUR  = 12;
  200.         INIMIN   = 0;
  201.         INISEC   = 0;
  202.         INISSEC  = 0;
  203.         ALAHOUR  = 0;
  204.         ALAMIN   = 0;
  205.         ALASEC   = 0;
  206.         ALASSEC  = 0;
  207.     }
  208.     RTCCFG |= 0x01;                         //写入RTC初始值
  209.     RTCCR = 0x01;                           //RTC开始运行
  210.     while (RTCCFG & 0x01);                  //等待RTC初始化完成
  211.     RTCIF = 0x00;
  212.     RTCIEN = 0x08;                          //使能RTC秒中断
  213. }
  214. void SendUart(BYTE dat)                     //串口发送函数
  215. {
  216.     while (fUartBusy);
  217.     SBUF = dat;
  218.     fUartBusy = 1;
  219. }
  220. void IapProgram(int addr, char dat)         //EEPROM编程函数
  221. {
  222.     IAP_CONTR = 0x80;
  223.     IAP_TPS = 12;
  224.     IAP_CMD = 2;
  225.     IAP_ADDRL = addr;
  226.     IAP_ADDRH = addr >> 8;
  227.     IAP_DATA = dat;
  228.     IAP_TRIG = 0x5a;
  229.     IAP_TRIG = 0xa5;
  230.     _nop_();
  231.     _nop_();
  232.     _nop_();
  233.     _nop_();
  234. }
复制代码

ISP下载软件中“用户接口”的设置如下:(注意,首次下载不能使能用户接口)
STC32G系列 —— 利用用户接口实现不停电下载保持RTC参数-6.png

STC32G系列-RTC-高级应用.rar

12.07 KB, 下载次数: 184

回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:460
  • 最近打卡:2025-04-30 07:45:21

21

主题

168

回帖

1465

积分

金牌会员

积分
1465
发表于 2025-2-22 12:01:52 | 显示全部楼层
版主好,我的RTC读取、显示程序正常,就是每次停电或下载程序,RTC的值又被复位了(初始值)。看到这个帖子知道是解决这个问题的,但是程序下载能够顺利运行,P20指示灯也能正常闪烁。但我不知道怎么用到自己程序里,在下载或停电时保持当前时间。我的操作步骤是这样的:
第一,把STC32G系列-RTC-高级应用程序下载到单片机中。
第二,按上图设置用户接口。
第三,下载我自己的RTC程序到单片机。结果显示在“与用户接口通讯”界面,很快就弹出“通讯连接超时”
知道自己没有理解程序的操作步骤,该如何使用,还请版主赐教!另外,它和“RTC对时”(程序下载正常运行了,并能打印输出,但不知道如何对时)功能有什么区别?
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-1 19:23 , Processed in 0.151582 second(s), 58 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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