• ch579/578/577/573/571/57x 内部 RTC 使用


    本文目的

    本文将记录如何在沁恒的ble soc上使用rtc 以及注意事项
    对于用到BLE功能,不建议直接对RTC直接操作,而是使用wch提供的"系统" TMOS的API,这里有个使用总结: https://www.cnblogs.com/iot-fan/p/13460082.html

    适用芯片

    • CH579/CH578/CH577
    • CH573/CH571

    差异部分

    差异部分 CH579/578/577 CH573/571
    上电默认启动
    触发值设置

    说明

    • 直至目前,WCH的CH57*系列芯片都是只提供了一个RTC外设
    • CH57*系列的RTC外设不支持独立供电
    • 该RTC只有一个触发(CC)中断,和一个定时中断
    • 该RTC的时钟源不支持预分频,即为固定1s=32768当用的是32.768的外部时钟时候
    • 该RTC的CNT最大值不是对齐到2的N次方-1 ,而是以1s=37268 记一天的值即0xA8C00000

    使用

    实际上在wch 提供的ble 工程里,有比较充分的rtc的使用方式
    如下是一个CH573 ble sdk 里面的提供的代码(在CH573EVT_1.6EXAMBLEHALRTC.c)

    void HAL_TimeInit( void )
    {
    #if( CLK_OSC32K )                                               //使用内部的32K RC作为RTC的时钟,由于rc振荡器是误差比较大,所以wch提供了校准函数,并且根据需求是校准到32Khz 还是32.768khz
        R8_SAFE_ACCESS_SIG = 0x57;
        R8_SAFE_ACCESS_SIG = 0xa8;
        R8_CK32K_CONFIG &= ~(RB_CLK_OSC32K_XT|RB_CLK_XT32K_PON);
        R8_CK32K_CONFIG |= RB_CLK_INT32K_PON;
        Lib_Calibration_LSI();                                      // 32K rc的校准,如果不需要高精度(比如一些非ble应用),可以注释掉这个代码,可以省去一些RAM和flash空间
    #else
        R8_SAFE_ACCESS_SIG = 0x57;
        R8_SAFE_ACCESS_SIG = 0xa8;
        R8_CK32K_CONFIG |= RB_CLK_OSC32K_XT | RB_CLK_INT32K_PON | RB_CLK_XT32K_PON;
        R8_SAFE_ACCESS_SIG = 0;
    #endif
        RTC_InitTime( 2020, 1, 1, 0, 0, 0 );                        //RTC时钟初始化当前时间,这里实际上年月日时分秒的计算都是软件实现,如果不需要,可以注释掉.同样可以省区一些RAM和flash资源
        TMOS_TimerInit( 0 );                                        //tmos的时间初始化,当我么没有用到tmos时候,这里注释掉即可
    }
    
    //这里传入的是RTC的值
    //WCH 的rtc这里的设计比较奇葩,rtc 的cnt最大是一天的,所以这里的设置触发值最大是32768*3600*24 = 0xA8C00000,
    //所以time 在传入前,需要做 if( time > 0xA8C00000 ) time -= 0xA8C00000; (出处:CH573EVT_1.6EXAMBLEHALSLEEP.c 中的CH57X_LowPower 函数)
    void RTC_SetTignTime( u32 time )
    {
        R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1;
        R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2;
        R32_RTC_TRIG = time;
        RTCTigFlag = 0;
    }
    
    __attribute__((interrupt("WCH-Interrupt-fast")))                // wch的硬件压栈
    __attribute__((section(".highcode")))                           // 需要放到RAM里面
    void RTC_IRQHandler( void )
    {
        R8_RTC_FLAG_CTRL = ( RB_RTC_TMR_CLR | RB_RTC_TRIG_CLR );    //这里的清理中断标志位是两个都清理,实际上这样写是推荐的,在早期的一些bootloader里面某些rtc 功能打开了,可能导致这里没有清理中断标志位而卡住
        RTCTigFlag = 1;
    }
    
    

    其中还有个唤醒配置(在CH573EVT_1.6EXAMBLEHALSLEEP.c):

    void HAL_SleepInit( void )
    {
    #if (defined (HAL_SLEEP)) && (HAL_SLEEP == TRUE)               // 蓝牙工程里面的 开启休眠的宏,由于wch 的ble只有在休眠时候,才会用到RTC的中断,所以这里有个开启宏
        R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1;
        R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2;
        R8_SLP_WAKE_CTRL |= RB_SLP_RTC_WAKE;                       // RTC唤醒
        R8_RTC_MODE_CTRL |= RB_RTC_TRIG_EN;                        // 触发模式
        R8_SAFE_ACCESS_SIG = 0;                                    //
        PFIC_EnableIRQ( RTC_IRQn );
    #endif
    }
    

    注意事项

    • 获取当前的RTC的CNT一定要使用wch提供的函数RTC_GetCycle32k(),不要直接读寄存器,寄存器R32_RTC_CNT_32K其实是两个16bit的寄存器,在变化时候存在不同步的变化的情况,如果直接读寄存器,有几率得到一个奇怪的值;
    • 如果用的是内部RC作为RTC的时钟,外部的32.768K 的晶体使能功能一定要关掉(尤其是CH579,默认是开启的);
    • RTC的寄存器是复位保持的,所以一个好的习惯是在初始化时候保证用到的位都写一遍,而不是某些bit跟上电默认一致就不配置了.
  • 相关阅读:
    前端
    前端
    数据库
    代码块
    装饰器
    函数 初识函数
    相识python --------文件操作
    相识python --------str字符串 int整形 bool布尔值 tu元祖 set()集合 dict 字典的数据补充
    【openstack报错】【因更新包而致】IncompatibleObjectVersion: Version 1.9 of Instance is not supported
    开博第一篇
  • 原文地址:https://www.cnblogs.com/iot-fan/p/15211335.html
Copyright © 2020-2023  润新知