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.6\EXAM\BLE\HAL\RTC.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.6\EXAM\BLE\HAL\SLEEP.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.6\EXAM\BLE\HAL\SLEEP.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跟上電默認一致就不配置了.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM