aboutsummaryrefslogtreecommitdiff
path: root/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_clk.c
diff options
context:
space:
mode:
Diffstat (limited to 'CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_clk.c')
-rw-r--r--CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_clk.c477
1 files changed, 477 insertions, 0 deletions
diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_clk.c b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_clk.c
new file mode 100644
index 0000000..a1d345f
--- /dev/null
+++ b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_clk.c
@@ -0,0 +1,477 @@
+/********************************** (C) COPYRIGHT *******************************
+ * File Name : CH58x_clk.c
+ * Author : WCH
+ * Version : V1.2
+ * Date : 2021/11/17
+ * Description
+ *********************************************************************************
+ * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
+ * Attention: This software (modified or not) and binary are used for
+ * microcontroller manufactured by Nanjing Qinheng Microelectronics.
+ *******************************************************************************/
+
+#include "CH58x_common.h"
+
+/*********************************************************************
+ * @fn LClk32K_Select
+ *
+ * @brief 32K 低频时钟来源
+ *
+ * @param hc - 选择32K使用内部还是外部
+ *
+ * @return none
+ */
+void LClk32K_Select(LClk32KTypeDef hc)
+{
+ uint8_t cfg = R8_CK32K_CONFIG;
+
+ if(hc == Clk32K_LSI)
+ {
+ cfg &= ~RB_CLK_OSC32K_XT;
+ }
+ else
+ {
+ cfg |= RB_CLK_OSC32K_XT;
+ }
+
+ sys_safe_access_enable();
+ R8_CK32K_CONFIG = cfg;
+ sys_safe_access_disable();
+}
+
+/*********************************************************************
+ * @fn HSECFG_Current
+ *
+ * @brief HSE晶体 偏置电流配置
+ *
+ * @param c - 75%,100%,125%,150%
+ *
+ * @return none
+ */
+void HSECFG_Current(HSECurrentTypeDef c)
+{
+ uint8_t x32M_c;
+
+ x32M_c = R8_XT32M_TUNE;
+ x32M_c = (x32M_c & 0xfc) | (c & 0x03);
+
+ sys_safe_access_enable();
+ R8_XT32M_TUNE = x32M_c;
+ sys_safe_access_disable();
+}
+
+/*********************************************************************
+ * @fn HSECFG_Capacitance
+ *
+ * @brief HSE晶体 负载电容配置
+ *
+ * @param c - refer to HSECapTypeDef
+ *
+ * @return none
+ */
+void HSECFG_Capacitance(HSECapTypeDef c)
+{
+ uint8_t x32M_c;
+
+ x32M_c = R8_XT32M_TUNE;
+ x32M_c = (x32M_c & 0x8f) | (c << 4);
+
+ sys_safe_access_enable();
+ R8_XT32M_TUNE = x32M_c;
+ sys_safe_access_disable();
+}
+
+/*********************************************************************
+ * @fn LSECFG_Current
+ *
+ * @brief LSE晶体 偏置电流配置
+ *
+ * @param c - 70%,100%,140%,200%
+ *
+ * @return none
+ */
+void LSECFG_Current(LSECurrentTypeDef c)
+{
+ uint8_t x32K_c;
+
+ x32K_c = R8_XT32K_TUNE;
+ x32K_c = (x32K_c & 0xfc) | (c & 0x03);
+
+ sys_safe_access_enable();
+ R8_XT32K_TUNE = x32K_c;
+ sys_safe_access_disable();
+}
+
+/*********************************************************************
+ * @fn LSECFG_Capacitance
+ *
+ * @brief LSE晶体 负载电容配置
+ *
+ * @param c - refer to LSECapTypeDef
+ *
+ * @return none
+ */
+void LSECFG_Capacitance(LSECapTypeDef c)
+{
+ uint8_t x32K_c;
+
+ x32K_c = R8_XT32K_TUNE;
+ x32K_c = (x32K_c & 0x0f) | (c << 4);
+
+ sys_safe_access_enable();
+ R8_XT32K_TUNE = x32K_c;
+ sys_safe_access_disable();
+}
+
+/*********************************************************************
+ * @fn Calibration_LSI
+ *
+ * @brief 校准内部32K时钟
+ *
+ * @param cali_Lv - 校准等级选择 Level_32 - 用时 1.2ms 1000ppm (32M 主频) 1100ppm (60M 主频)
+ * Level_64 - 用时 2.2ms 800ppm (32M 主频) 1000ppm (60M 主频)
+ * Level_128 - 用时 4.2ms 600ppm (32M 主频) 800ppm (60M 主频)
+ *
+ * @return none
+ */
+void Calibration_LSI(Cali_LevelTypeDef cali_Lv)
+{
+ UINT32 i;
+ INT32 cnt_offset;
+ UINT8 retry = 0;
+ INT32 freq_sys;
+
+ freq_sys = GetSysClock();
+
+ sys_safe_access_enable();
+ R8_CK32K_CONFIG |= RB_CLK_OSC32K_FILT;
+ R8_CK32K_CONFIG &= ~RB_CLK_OSC32K_FILT;
+ sys_safe_access_enable();
+ R8_XT32K_TUNE &= ~3;
+ R8_XT32K_TUNE |= 1;
+
+ // 粗调
+ sys_safe_access_enable();
+ R8_OSC_CAL_CTRL &= ~RB_OSC_CNT_TOTAL;
+ R8_OSC_CAL_CTRL |= 1;
+ sys_safe_access_enable();
+ R8_OSC_CAL_CTRL |= RB_OSC_CNT_EN;
+ R16_OSC_CAL_CNT |= RB_OSC_CAL_OV_CLR;
+ while( (R8_OSC_CAL_CTRL &RB_OSC_CNT_EN) == 0 )
+ {
+ sys_safe_access_enable();
+ R8_OSC_CAL_CTRL |= RB_OSC_CNT_EN;
+ }
+ while(1)
+ {
+ while(!(R8_OSC_CAL_CTRL & RB_OSC_CNT_HALT));
+ i = R16_OSC_CAL_CNT; // 用于丢弃
+ while(R8_OSC_CAL_CTRL & RB_OSC_CNT_HALT);
+ R16_OSC_CAL_CNT |= RB_OSC_CAL_OV_CLR;
+ while(!(R8_OSC_CAL_CTRL & RB_OSC_CNT_HALT));
+ i = R16_OSC_CAL_CNT; // 实时校准后采样值
+ cnt_offset = (i & 0x3FFF) + R8_OSC_CAL_OV_CNT * 0x3FFF - 2000 * (freq_sys / 1000) / CAB_LSIFQ;
+ if(((cnt_offset > -37 * (freq_sys / 1000) / CAB_LSIFQ) && (cnt_offset < 37 * (freq_sys / 1000) / CAB_LSIFQ)) || retry > 2)
+ {
+ if(retry)
+ break;
+ }
+ retry++;
+ cnt_offset = (cnt_offset > 0) ? (((cnt_offset * 2) / (74 * (freq_sys/1000) / 60000)) + 1) / 2 : (((cnt_offset * 2) / (74 * (freq_sys/1000) / 60000 )) - 1) / 2;
+ sys_safe_access_enable();
+ R16_INT32K_TUNE += cnt_offset;
+ }
+
+ // 细调
+ // 配置细调参数后,丢弃2次捕获值(软件行为)上判断已有一次,这里只留一次
+ while(!(R8_OSC_CAL_CTRL & RB_OSC_CNT_HALT));
+ i = R16_OSC_CAL_CNT; // 用于丢弃
+ R16_OSC_CAL_CNT |= RB_OSC_CAL_OV_CLR;
+ sys_safe_access_enable();
+ R8_OSC_CAL_CTRL &= ~RB_OSC_CNT_TOTAL;
+ R8_OSC_CAL_CTRL |= cali_Lv;
+ while( (R8_OSC_CAL_CTRL&0x07) != cali_Lv )
+ {
+ sys_safe_access_enable();
+ R8_OSC_CAL_CTRL |= cali_Lv;
+ }
+ while(R8_OSC_CAL_CTRL & RB_OSC_CNT_HALT);
+ while(!(R8_OSC_CAL_CTRL & RB_OSC_CNT_HALT));
+ i = R16_OSC_CAL_CNT; // 实时校准后采样值
+
+ cnt_offset = (i & 0x3FFF) + R8_OSC_CAL_OV_CNT * 0x3FFF - 4000 * (1 << cali_Lv) * (freq_sys / 1000000) / 256 * 1000/(CAB_LSIFQ/256) ;
+ cnt_offset = (cnt_offset > 0) ? ((((cnt_offset * 2*(100 )) / (1366 * ((1 << cali_Lv)/8) * (freq_sys/1000) / 60000)) + 1) / 2)<<5 : ((((cnt_offset * 2*(100)) / (1366 * ((1 << cali_Lv)/8) * (freq_sys/1000) / 60000)) - 1) / 2)<<5;
+ sys_safe_access_enable();
+ R16_INT32K_TUNE += cnt_offset;
+ R8_OSC_CAL_CTRL &= ~RB_OSC_CNT_EN;
+}
+
+/*********************************************************************
+ * @fn RTCInitTime
+ *
+ * @brief RTC时钟初始化当前时间
+ *
+ * @param y - 配置年,MAX_Y = BEGYEAR + 44
+ * @param mon - 配置月,MAX_MON = 12
+ * @param d - 配置日,MAX_D = 31
+ * @param h - 配置小时,MAX_H = 23
+ * @param m - 配置分钟,MAX_M = 59
+ * @param s - 配置秒,MAX_S = 59
+ *
+ * @return none
+ */
+void RTC_InitTime(uint16_t y, uint16_t mon, uint16_t d, uint16_t h, uint16_t m, uint16_t s)
+{
+ uint32_t t;
+ uint16_t year, month, day, sec2, t32k;
+ volatile uint8_t clk_pin;
+
+ year = y;
+ month = mon;
+ day = 0;
+ while(year > BEGYEAR)
+ {
+ day += YearLength(year - 1);
+ year--;
+ }
+ while(month > 1)
+ {
+ day += monthLength(IsLeapYear(y), month - 2);
+ month--;
+ }
+
+ day += d - 1;
+ sec2 = (h % 24) * 1800 + m * 30 + s / 2;
+ t32k = (s & 1) ? (0x8000) : (0);
+ t = sec2;
+ t = t << 16 | t32k;
+
+ do
+ {
+ clk_pin = (R8_CK32K_CONFIG & RB_32K_CLK_PIN);
+ } while(clk_pin != (R8_CK32K_CONFIG & RB_32K_CLK_PIN));
+ if(!clk_pin)
+ {
+ while(!clk_pin)
+ {
+ do
+ {
+ clk_pin = (R8_CK32K_CONFIG & RB_32K_CLK_PIN);
+ } while(clk_pin != (R8_CK32K_CONFIG & RB_32K_CLK_PIN));
+ }
+ }
+
+ sys_safe_access_enable();
+ R32_RTC_TRIG = day;
+ R8_RTC_MODE_CTRL |= RB_RTC_LOAD_HI;
+ while((R32_RTC_TRIG & 0x3FFF) != (R32_RTC_CNT_DAY & 0x3FFF));
+ sys_safe_access_enable();
+ R32_RTC_TRIG = t;
+ R8_RTC_MODE_CTRL |= RB_RTC_LOAD_LO;
+ sys_safe_access_disable();
+}
+
+/*********************************************************************
+ * @fn RTC_GetTime
+ *
+ * @brief 获取当前时间
+ *
+ * @param py - 获取到的年,MAX_Y = BEGYEAR + 44
+ * @param pmon - 获取到的月,MAX_MON = 12
+ * @param pd - 获取到的日,MAX_D = 31
+ * @param ph - 获取到的小时,MAX_H = 23
+ * @param pm - 获取到的分钟,MAX_M = 59
+ * @param ps - 获取到的秒,MAX_S = 59
+ *
+ * @return none
+ */
+void RTC_GetTime(uint16_t *py, uint16_t *pmon, uint16_t *pd, uint16_t *ph, uint16_t *pm, uint16_t *ps)
+{
+ uint32_t t;
+ uint16_t day, sec2, t32k;
+
+ day = R32_RTC_CNT_DAY & 0x3FFF;
+ sec2 = R16_RTC_CNT_2S;
+ t32k = R16_RTC_CNT_32K;
+
+ t = sec2 * 2 + ((t32k < 0x8000) ? 0 : 1);
+
+ *py = BEGYEAR;
+ while(day >= YearLength(*py))
+ {
+ day -= YearLength(*py);
+ (*py)++;
+ }
+
+ *pmon = 0;
+ while(day >= monthLength(IsLeapYear(*py), *pmon))
+ {
+ day -= monthLength(IsLeapYear(*py), *pmon);
+ (*pmon)++;
+ }
+ (*pmon)++;
+ *pd = day + 1;
+ *ph = t / 3600;
+ *pm = t % 3600 / 60;
+ *ps = t % 60;
+}
+
+/*********************************************************************
+ * @fn RTC_SetCycle32k
+ *
+ * @brief 基于LSE/LSI时钟,配置当前RTC 周期数
+ *
+ * @param cyc - 配置周期计数初值,MAX_CYC = 0xA8BFFFFF = 2831155199
+ *
+ * @return none
+ */
+void RTC_SetCycle32k(uint32_t cyc)
+{
+ volatile uint8_t clk_pin;
+
+ do
+ {
+ clk_pin = (R8_CK32K_CONFIG & RB_32K_CLK_PIN);
+ } while((clk_pin != (R8_CK32K_CONFIG & RB_32K_CLK_PIN)) || (!clk_pin));
+
+ sys_safe_access_enable();
+ R32_RTC_TRIG = cyc;
+ R8_RTC_MODE_CTRL |= RB_RTC_LOAD_LO;
+ sys_safe_access_disable();
+}
+
+/*********************************************************************
+ * @fn RTC_GetCycle32k
+ *
+ * @brief 基于LSE/LSI时钟,获取当前RTC 周期数
+ *
+ * @param none
+ *
+ * @return 当前周期数,MAX_CYC = 0xA8BFFFFF = 2831155199
+ */
+uint32_t RTC_GetCycle32k(void)
+{
+ volatile uint32_t i;
+
+ do
+ {
+ i = R32_RTC_CNT_32K;
+ } while(i != R32_RTC_CNT_32K);
+
+ return (i);
+}
+
+/*********************************************************************
+ * @fn RTC_TMRFunCfg
+ *
+ * @brief RTC定时模式配置(注意定时基准固定为32768Hz)
+ *
+ * @param t - refer to RTC_TMRCycTypeDef
+ *
+ * @return none
+ */
+void RTC_TMRFunCfg(RTC_TMRCycTypeDef t)
+{
+ sys_safe_access_enable();
+ R8_RTC_MODE_CTRL &= ~(RB_RTC_TMR_EN | RB_RTC_TMR_MODE);
+ sys_safe_access_enable();
+ R8_RTC_MODE_CTRL |= RB_RTC_TMR_EN | (t);
+ sys_safe_access_disable();
+}
+
+/*********************************************************************
+ * @fn RTC_TRIGFunCfg
+ *
+ * @brief RTC时间触发模式配置
+ *
+ * @param cyc - 相对当前时间的触发间隔时间,基于LSE/LSI时钟周期数
+ *
+ * @return none
+ */
+void RTC_TRIGFunCfg(uint32_t cyc)
+{
+ uint32_t t;
+
+ t = RTC_GetCycle32k() + cyc;
+ if(t > 0xA8C00000)
+ {
+ t -= 0xA8C00000;
+ }
+
+ sys_safe_access_enable();
+ R32_RTC_TRIG = t;
+ R8_RTC_MODE_CTRL |= RB_RTC_TRIG_EN;
+ sys_safe_access_disable();
+}
+
+/*********************************************************************
+ * @fn RTC_ModeFunDisable
+ *
+ * @brief RTC 模式功能关闭
+ *
+ * @param m - 需要关闭的当前模式
+ *
+ * @return none
+ */
+void RTC_ModeFunDisable(RTC_MODETypeDef m)
+{
+ uint8_t i = 0;
+
+ if(m == RTC_TRIG_MODE)
+ {
+ i |= RB_RTC_TRIG_EN;
+ }
+ else if(m == RTC_TMR_MODE)
+ {
+ i |= RB_RTC_TMR_EN;
+ }
+
+ sys_safe_access_enable();
+ R8_RTC_MODE_CTRL &= ~(i);
+ sys_safe_access_disable();
+}
+
+/*********************************************************************
+ * @fn RTC_GetITFlag
+ *
+ * @brief 获取RTC中断标志
+ *
+ * @param f - refer to RTC_EVENTTypeDef
+ *
+ * @return 中断标志状态
+ */
+uint8_t RTC_GetITFlag(RTC_EVENTTypeDef f)
+{
+ if(f == RTC_TRIG_EVENT)
+ {
+ return (R8_RTC_FLAG_CTRL & RB_RTC_TRIG_FLAG);
+ }
+ else
+ {
+ return (R8_RTC_FLAG_CTRL & RB_RTC_TMR_FLAG);
+ }
+}
+
+/*********************************************************************
+ * @fn RTC_ClearITFlag
+ *
+ * @brief 清除RTC中断标志
+ *
+ * @param f - refer to RTC_EVENTTypeDef
+ *
+ * @return none
+ */
+void RTC_ClearITFlag(RTC_EVENTTypeDef f)
+{
+ switch(f)
+ {
+ case RTC_TRIG_EVENT:
+ R8_RTC_FLAG_CTRL = RB_RTC_TRIG_CLR;
+ break;
+ case RTC_TMR_EVENT:
+ R8_RTC_FLAG_CTRL = RB_RTC_TMR_CLR;
+ break;
+ default:
+ break;
+ }
+}