/********************************** (C) COPYRIGHT ******************************* * File Name : CH57x_clk.c * Author : WCH * Version : V1.0 * Date : 2018/12/15 * Description *******************************************************************************/ #include "CH57x_common.h" /******************************************************************************* * Function Name : SystemInit * Description : 系统时钟默认初始化 * Input : None * Return : None *******************************************************************************/ void SystemInit(void) { R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; R16_CLK_SYS_CFG = (2<<6)|0x08; // 32M -> Fsys *((PUINT16V)0x40001048) |= 4; R8_SAFE_ACCESS_SIG = 0; mDelayuS(10); /* 开启电压监控 */ PowerMonitor( ENABLE ); } /******************************************************************************* * Function Name : SetSysClock * Description : 重设系统运行时钟 * Input : sc: 系统时钟源选择 refer to SYS_CLKTypeDef * Return : None *******************************************************************************/ void SetSysClock( SYS_CLKTypeDef sc) { switch( sc ) { case CLK_SOURCE_LSI: R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; R8_CK32K_CONFIG &= ~RB_CLK_OSC32K_XT; R16_CLK_SYS_CFG = (3<<6)|0x08; break; case CLK_SOURCE_LSE: R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; R8_CK32K_CONFIG |= RB_CLK_OSC32K_XT; R16_CLK_SYS_CFG = (3<<6)|0x08; break; case CLK_SOURCE_HSE_32MHz: R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; R16_CLK_SYS_CFG = RB_CLK_OSC32M_XT|(2<<6)|0x08; break; case CLK_SOURCE_HSE_16MHz: R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; R16_CLK_SYS_CFG = RB_CLK_OSC32M_XT|(0<<6)|0x02; break; case CLK_SOURCE_HSE_8MHz: R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; R16_CLK_SYS_CFG = RB_CLK_OSC32M_XT|(0<<6)|0x04; break; case CLK_SOURCE_HSI_32MHz: R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; R16_CLK_SYS_CFG = (2<<6)|0x08; break; case CLK_SOURCE_HSI_16MHz: R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; R16_CLK_SYS_CFG = (0<<6)|0x02; break; case CLK_SOURCE_HSI_8MHz: R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; R16_CLK_SYS_CFG = (0<<6)|0x04; break; case CLK_SOURCE_PLL_40MHz: R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; R16_CLK_SYS_CFG = RB_CLK_OSC32M_XT|(1<<6)|12; break; case CLK_SOURCE_PLL_32MHz: R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; R16_CLK_SYS_CFG = RB_CLK_OSC32M_XT|(1<<6)|15; break; case CLK_SOURCE_PLL_24MHz: R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; R16_CLK_SYS_CFG = RB_CLK_OSC32M_XT|(1<<6)|20; break; case CLK_SOURCE_PLL_20MHz: R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; R16_CLK_SYS_CFG = RB_CLK_OSC32M_XT|(1<<6)|24; break; case CLK_SOURCE_PLL_16MHz: R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; R16_CLK_SYS_CFG = RB_CLK_OSC32M_XT|(1<<6)|30; break; default : break; } R8_SAFE_ACCESS_SIG = 0; } /******************************************************************************* * Function Name : GetSysClock * Description : 获取当前系统时钟 * Input : None * Return : Hz *******************************************************************************/ UINT32 GetSysClock( void ) { UINT16 rev; rev = R16_CLK_SYS_CFG & 0xff; if( (rev & RB_CLK_SYS_MOD) == (2<<6) ){ // 32M做主频 return (32000000); } else if( (rev & RB_CLK_SYS_MOD) == (1<<6) ){ // PLL进行分频 return (480000000/(rev&0x1f)); } else if( (rev & RB_CLK_SYS_MOD) == (0<<6) ){ // 32M进行分频 return (32000000/(rev&0x1f)); } else { // 32K做主频 return (32000); } } /******************************************************************************* * Function Name : HClk32M_Select * Description : 32M 高频时钟来源 * Input : hc: Clk32M_HSI - 选择内部32M Clk32M_HSE - 选择外部32M * Return : None *******************************************************************************/ void HClk32M_Select( HClk32MTypeDef hc) { R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; if( hc == Clk32M_HSI) R16_CLK_SYS_CFG &= ~RB_CLK_OSC32M_XT; else R16_CLK_SYS_CFG |= RB_CLK_OSC32M_XT; R8_SAFE_ACCESS_SIG = 0; } /******************************************************************************* * Function Name : LClk32K_Select * Description : 32K 低频时钟来源 * Input : hc: Clk32K_LSI - 选择内部32K Clk32K_LSE - 选择外部32K * Return : None *******************************************************************************/ void LClk32K_Select( LClk32KTypeDef hc) { R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; if( hc == Clk32K_LSI) R8_CK32K_CONFIG &= ~RB_CLK_OSC32K_XT; else R8_CK32K_CONFIG |= RB_CLK_OSC32K_XT; R8_SAFE_ACCESS_SIG = 0; } /******************************************************************************* * Function Name : HSECFG_Current * Description : HSE晶体 偏置电流配置 * Input : c: 75%,100%,125%,150% * Return : None *******************************************************************************/ void HSECFG_Current( HSECurrentTypeDef c ) { UINT8 x32M_c; x32M_c = R8_XT32M_TUNE; x32M_c = (x32M_c&0xfc)|(c&0x03); R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; R8_XT32M_TUNE = x32M_c; R8_SAFE_ACCESS_SIG = 0; } /******************************************************************************* * Function Name : HSECFG_Capacitance * Description : HSE晶体 负载电容配置 * Input : c: refer to HSECapTypeDef * Return : None *******************************************************************************/ void HSECFG_Capacitance( HSECapTypeDef c ) { UINT8 x32M_c; x32M_c = R8_XT32M_TUNE; x32M_c = (x32M_c&0x8f)|(c<<4); R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; R8_XT32M_TUNE = x32M_c; R8_SAFE_ACCESS_SIG = 0; } /******************************************************************************* * Function Name : LSECFG_Current * Description : LSE晶体 偏置电流配置 * Input : c: 70%,100%,140%,200% * Return : None *******************************************************************************/ void LSECFG_Current( LSECurrentTypeDef c ) { UINT8 x32K_c; x32K_c = R8_XT32K_TUNE; x32K_c = (x32K_c&0xfc)|(c&0x03); R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; R8_XT32K_TUNE = x32K_c; R8_SAFE_ACCESS_SIG = 0; } /******************************************************************************* * Function Name : LSECFG_Capacitance * Description : LSE晶体 负载电容配置 * Input : c: refer to LSECapTypeDef * Return : None *******************************************************************************/ void LSECFG_Capacitance( LSECapTypeDef c ) { UINT8 x32K_c; x32K_c = R8_XT32K_TUNE; x32K_c = (x32K_c&0x0f)|(c<<4); R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; R8_XT32K_TUNE = x32K_c; R8_SAFE_ACCESS_SIG = 0; } /******************************************************************************* * Function Name : Calibration_LSI * Description : 校准内部32K时钟 * Input : None * Return : 误差:千分之(单位) *******************************************************************************/ // 0-26030Hz 1023-44220Hz UINT16 Calibration_LSI( void ) { UINT16 rev, basev; UINT32 calv; UINT16 i; UINT16 loc, loc_t; signed short CNT_STEP_K; signed short diff_1, diff_2, diffc; UINT8 k=0; /* 根据当前时钟获取标称值和斜率(T-step) */ rev = R16_CLK_SYS_CFG & 0xff; // CNT_STEP_K=Fsys*5*(1/26030 - 1/44220)/1023; if( (rev & RB_CLK_SYS_MOD) == (2<<6) ){ // 32M做主频 calv = ((5*32000000+(CAB_LSIFQ>>1))/CAB_LSIFQ); CNT_STEP_K = -3; } else if( (rev & RB_CLK_SYS_MOD) == (1<<6) ){ // PLL进行分频 calv = (((UINT32)5*480000000/(rev&0x1f)+(CAB_LSIFQ>>1))/CAB_LSIFQ); CNT_STEP_K =( -37-((rev&0x1f)-1))/(rev&0x1f); } else if( (rev & RB_CLK_SYS_MOD) == (0<<6) ){ // 32M进行分频 calv = ((5*32000000/(rev&0x1f)+(CAB_LSIFQ>>1))/CAB_LSIFQ); CNT_STEP_K = ( -3-((rev&0x1f)-1))/(rev&0x1f); } else { // 32K做主频 calv = (5); CNT_STEP_K = 0; } /* 校准 */ basev = ( calv &0xfff ); // 获取校准标称值 // loc = 1023*(f-26030)/f/((44220-26030)/44220) 经验曲线 loc = R16_INT32K_TUNE; diff_2 = 0; diffc = 0; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; R8_OSC_CAL_CTRL = RB_OSC_CNT_EN; do { R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; R16_INT32K_TUNE = loc; R8_SAFE_ACCESS_SIG = 0; /* 读取当前值 */ while(!(R8_OSC_CAL_CTRL&RB_OSC_CNT_HALT)); i = R16_OSC_CAL_CNT; // 用于丢弃 while(R8_OSC_CAL_CTRL&RB_OSC_CNT_HALT); while(!(R8_OSC_CAL_CTRL&RB_OSC_CNT_HALT)); i = R16_OSC_CAL_CNT; // 实时校准后采样值 k++; diff_1 = i-basev; if( diff_1 == 0 ){ return 0; // 校准正好 } else if((diff_1*diff_2)<0){ // 处于两点之间 if((diffc == 1) || (diffc == -1) || (diffc == 0)) { // 都变成正数 if( diff_2<0 ) diff_2 = ~(diff_2-1); else diff_1 = ~(diff_1-1); if(diff_1>diff_2){ R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; R16_INT32K_TUNE = loc_t; R8_SAFE_ACCESS_SIG = 0; return (diff_2*1000/basev); // 返回误差值,千分之 } else return(diff_1*1000/basev); } } // 保存上一次值 diff_2 = diff_1; loc_t = loc; diffc = diff_1/CNT_STEP_K; loc = loc - diffc; if( loc == loc_t ) { if( diff_1 > 0 ) loc = loc+1; // 当前频率偏小 else loc = loc-1; // 当前频率偏大 } }while( k<20 ); return(0xff); } /******************************************************************************* * Function Name : RTCInitTime * Description : RTC时钟初始化当前时间 * Input : y: 配置时间 - 年 MAX_Y = BEGYEAR + 44 mon: 配置时间 - 月 MAX_MON = 12 d: 配置时间 - 日 MAX_D = 31 h: 配置时间 - 小时 MAX_H = 23 m: 配置时间 - 分钟 MAX_M = 59 s: 配置时间 - 秒 MAX_S = 59 * Return : None *******************************************************************************/ void RTC_InitTime( UINT16 y, UINT16 mon, UINT16 d, UINT16 h, UINT16 m, UINT16 s ) { UINT32 t; UINT16 year, month, day, sec2, t32k; UINT8V 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)) || (!clk_pin) ); R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; R32_RTC_TRIG = day; R8_RTC_MODE_CTRL |= RB_RTC_LOAD_HI; R32_RTC_TRIG = t; R8_RTC_MODE_CTRL |= RB_RTC_LOAD_LO; R8_SAFE_ACCESS_SIG = 0; } /******************************************************************************* * Function Name : RTC_GetTime * Description : 获取当前时间 * Input : y: 获取到的时间 - 年 MAX_Y = BEGYEAR + 44 mon: 获取到的时间 - 月 MAX_MON = 12 d: 获取到的时间 - 日 MAX_D = 31 ph: 获取到的时间 - 小时 MAX_H = 23 pm: 获取到的时间 - 分钟 MAX_M = 59 ps: 获取到的时间 - 秒 MAX_S = 59 * Return : None *******************************************************************************/ void RTC_GetTime( PUINT16 py, PUINT16 pmon, PUINT16 pd, PUINT16 ph, PUINT16 pm, PUINT16 ps ) { UINT32 t; UINT16 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; } /******************************************************************************* * Function Name : RTC_SetCycle32k * Description : 基于LSE/LSI时钟,配置当前RTC 周期数 * Input : cyc: 配置周期计数初值 - cycle MAX_CYC = 0xA8BFFFFF = 2831155199 * Return : None *******************************************************************************/ void RTC_SetCycle32k( UINT32 cyc ) { UINT8V clk_pin; do{ clk_pin = (R8_CK32K_CONFIG&RB_32K_CLK_PIN); }while( (clk_pin != (R8_CK32K_CONFIG&RB_32K_CLK_PIN)) || (!clk_pin) ); R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; R32_RTC_TRIG = cyc; R8_RTC_MODE_CTRL |= RB_RTC_LOAD_LO; R8_SAFE_ACCESS_SIG = 0; } /******************************************************************************* * Function Name : RTC_GetCycle32k * Description : 基于LSE/LSI时钟,获取当前RTC 周期数 * Input : None * Return : 返回当前周期数,MAX_CYC = 0xA8BFFFFF = 2831155199 *******************************************************************************/ UINT32 RTC_GetCycle32k( void ) { UINT32 i; do{ i = R32_RTC_CNT_32K; }while( i != R32_RTC_CNT_32K ); return (i); } /******************************************************************************* * Function Name : RTC_TMRFunCfg * Description : RTC定时模式配置 * Input : t: refer to RTC_TMRCycTypeDef * Return : None *******************************************************************************/ void RTC_TMRFunCfg( RTC_TMRCycTypeDef t ) { R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; R8_RTC_MODE_CTRL &= ~(RB_RTC_TMR_EN|RB_RTC_TMR_MODE); R8_RTC_MODE_CTRL |= RB_RTC_TMR_EN | (t); R8_SAFE_ACCESS_SIG = 0; } /******************************************************************************* * Function Name : RTC_TRIGFunCfg * Description : RTC时间触发模式配置 * Input : cyc: 相对当前时间的触发间隔时间,基于LSE/LSI时钟周期数 * Return : None *******************************************************************************/ void RTC_TRIGFunCfg( UINT32 cyc ) { UINT32 t; t = RTC_GetCycle32k() + cyc; if( t>0xA8C00000) t -= 0xA8C00000; if( t&0xFFFF ) t = t+0x10000; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; R32_RTC_TRIG = t; R8_RTC_MODE_CTRL |= RB_RTC_TRIG_EN; R8_SAFE_ACCESS_SIG = 0; } /******************************************************************************* * Function Name : RTC_ModeFunDisable * Description : RTC 模式功能关闭 * Input : m: 需要关闭的当前模式 * Return : None *******************************************************************************/ void RTC_ModeFunDisable( RTC_MODETypeDef m ) { UINT8 i=0; if( m == RTC_TRIG_MODE ) i |= RB_RTC_TRIG_EN; else if( m == RTC_TMR_MODE ) i |= RB_RTC_TMR_EN; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1; R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2; R8_RTC_MODE_CTRL &= ~(i); R8_SAFE_ACCESS_SIG = 0; } /******************************************************************************* * Function Name : RTC_GetITFlag * Description : 获取RTC中断标志 * Input : f: refer to RTC_EVENTTypeDef * Return : 中断标志状态: 0 - 未发生事件 (!0) - 发生事件 *******************************************************************************/ UINT8 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 ); } /******************************************************************************* * Function Name : RTC_ClearITFlag * Description : 清除RTC中断标志 * Input : 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; } }