找回密码
 立即注册
查看: 1229|回复: 0

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

[复制链接]
  • TA的每日心情
    开心
    2024-1-4 08:56
  • 签到天数: 14 天

    [LV.3]偶尔看看II

    16

    主题

    711

    回帖

    2510

    积分

    超级版主

    积分
    2510
    发表于 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, 下载次数: 106

    回复 送花

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2024-4-19 14:50 , Processed in 0.067750 second(s), 31 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

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