CH592_Makefile_Template/sdk/StdPeriphDriver/CH59x_clk.c
2023-12-21 22:44:09 +07:00

579 lines
15 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/********************************** (C) COPYRIGHT *******************************
* File Name : CH59x_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 "CH59x_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 LClk32K_Cfg
*
* @brief 32K 低频时钟电源配置
*
* @param hc - 选择内部32K还是外部32K
* @param s - 是否打开电源
*
* @return none
*/
void LClk32K_Cfg(LClk32KTypeDef hc, FunctionalState s)
{
uint8_t cfg = R8_CK32K_CONFIG;
if(hc == Clk32K_LSI)
{
if(s == DISABLE)
{
cfg &= ~RB_CLK_INT32K_PON;
}
else
{
cfg |= RB_CLK_INT32K_PON;
}
}
else
{
if(s == DISABLE)
{
cfg &= ~RB_CLK_XT32K_PON;
}
else
{
cfg |= RB_CLK_XT32K_PON;
}
}
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 2.4ms 1000ppm (32M 主频) 1100ppm (60M 主频)
* Level_64 4.4ms 800ppm (32M 主频) 1000ppm (60M 主频)
* Level_128 8.4ms 600ppm (32M 主频) 800ppm (60M 主频)
*
* @return none
*/
void Calibration_LSI(Cali_LevelTypeDef cali_Lv)
{
UINT32 i;
INT32 cnt_offset;
UINT8 retry = 0;
INT32 freq_sys;
UINT32 cnt_32k = 0;
freq_sys = GetSysClock();
sys_safe_access_enable();
R8_CK32K_CONFIG &= ~RB_CLK_OSC32K_FILT;
R8_CK32K_CONFIG |= RB_CLK_OSC32K_FILT;
sys_safe_access_disable();
sys_safe_access_enable();
R8_XT32K_TUNE &= ~3;
R8_XT32K_TUNE |= 1;
sys_safe_access_disable();
// 粗调
sys_safe_access_enable();
R8_OSC_CAL_CTRL &= ~RB_OSC_CNT_TOTAL;
R8_OSC_CAL_CTRL |= 1;
sys_safe_access_disable();
while(1)
{
sys_safe_access_enable();
R8_OSC_CAL_CTRL |= RB_OSC_CNT_EN;
R16_OSC_CAL_CNT |= RB_OSC_CAL_OV_CLR;
R16_OSC_CAL_CNT |= RB_OSC_CAL_IF;
sys_safe_access_disable();
while( (R8_OSC_CAL_CTRL & RB_OSC_CNT_EN) == 0 )
{
sys_safe_access_enable();
R8_OSC_CAL_CTRL |= RB_OSC_CNT_EN;
sys_safe_access_disable();
}
while(!(R8_OSC_CAL_CTRL & RB_OSC_CNT_HALT)); // 用于丢弃
sys_safe_access_enable();
R8_OSC_CAL_CTRL &= ~RB_OSC_CNT_EN;
R8_OSC_CAL_CTRL |= RB_OSC_CNT_EN;
R16_OSC_CAL_CNT |= RB_OSC_CAL_OV_CLR;
R16_OSC_CAL_CNT |= RB_OSC_CAL_IF;
sys_safe_access_disable();
while( (R8_OSC_CAL_CTRL & RB_OSC_CNT_EN) == 0 )
{
sys_safe_access_enable();
R8_OSC_CAL_CTRL |= RB_OSC_CNT_EN;
sys_safe_access_disable();
}
while(R8_OSC_CAL_CTRL & RB_OSC_CNT_HALT);
cnt_32k = RTC_GetCycle32k();
while(RTC_GetCycle32k() == cnt_32k);
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;
sys_safe_access_disable();
}
// 细调
// 配置细调参数后丢弃2次捕获值软件行为上判断已有一次这里只留一次
sys_safe_access_enable();
R8_OSC_CAL_CTRL &= ~RB_OSC_CNT_TOTAL;
R8_OSC_CAL_CTRL |= cali_Lv;
sys_safe_access_disable();
while( (R8_OSC_CAL_CTRL & RB_OSC_CNT_TOTAL) != cali_Lv )
{
sys_safe_access_enable();
R8_OSC_CAL_CTRL |= cali_Lv;
sys_safe_access_disable();
}
sys_safe_access_enable();
R8_OSC_CAL_CTRL &= ~RB_OSC_CNT_EN;
R8_OSC_CAL_CTRL |= RB_OSC_CNT_EN;
R16_OSC_CAL_CNT |= RB_OSC_CAL_OV_CLR;
R16_OSC_CAL_CNT |= RB_OSC_CAL_IF;
sys_safe_access_disable();
while( (R8_OSC_CAL_CTRL & RB_OSC_CNT_EN) == 0 )
{
sys_safe_access_enable();
R8_OSC_CAL_CTRL |= RB_OSC_CNT_EN;
sys_safe_access_disable();
}
while(!(R8_OSC_CAL_CTRL & RB_OSC_CNT_HALT)); // 用于丢弃
sys_safe_access_enable();
R8_OSC_CAL_CTRL &= ~RB_OSC_CNT_EN;
R8_OSC_CAL_CTRL |= RB_OSC_CNT_EN;
R16_OSC_CAL_CNT |= RB_OSC_CAL_OV_CLR;
R16_OSC_CAL_CNT |= RB_OSC_CAL_IF;
sys_safe_access_disable();
while( (R8_OSC_CAL_CTRL & RB_OSC_CNT_EN) == 0 )
{
sys_safe_access_enable();
R8_OSC_CAL_CTRL |= RB_OSC_CNT_EN;
sys_safe_access_disable();
}
while(R8_OSC_CAL_CTRL & RB_OSC_CNT_HALT);
cnt_32k = RTC_GetCycle32k();
while(RTC_GetCycle32k() == cnt_32k);
R16_OSC_CAL_CNT |= RB_OSC_CAL_OV_CLR;
while(!(R8_OSC_CAL_CTRL & RB_OSC_CNT_HALT));
sys_safe_access_enable();
R8_OSC_CAL_CTRL &= ~RB_OSC_CNT_EN;
sys_safe_access_disable();
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;
sys_safe_access_disable();
}
/*********************************************************************
* @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;
sys_safe_access_disable();
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_disable();
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 > RTC_MAX_COUNT)
{
t -= RTC_MAX_COUNT;
}
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;
}
}