| 
 
中级会员  
 
	积分218金钱218 注册时间2015-1-19在线时间28 小时 | 
 
| 虽然STM8s的内部时钟已经经过校准,但是如果在温度变化很大的场合使用需要精准时序的应用时,就需要用温漂较小的外部时钟,先介绍一下STM8S的时钟。 
 时钟源:
 STM8S的时钟源有三个,分别是:1~24MHz的外部晶振或者时钟RC时钟,上电后默认使用HSI/8最为时钟源。
 
 切换:
 切换手册上标注有两种,一个是自动切换,一个是手动切换,这个在一般应用中是没有差别的,自动切换就是CPU的负担小一些而已。看图吧:
 
   这里我们使用自动切换
 
 
 实现:
 自动切换实现起来有两种,第一种就是根据手册说明来操作寄存器,第二种就是使用官方库,这两种方式我都说一下:
 
 官方库:
 很简单,copy我的就行 [mw_shl_code=c,true]CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO,CLK_SOURCE_HSE,DISABLE, CLK_CURRENTCLOCKSTATE_ENABLE);[/mw_shl_code]
 原型如下:
 [mw_shl_code=c,true]/**
 * @brief  configures the Switch from one clock to another
 * @param   CLK_SwitchMode select the clock switch mode.
 * It can be set of the values of @ref CLK_SwitchMode_TypeDef
 * @param   CLK_NewClock choice of the future clock.
 * It can be set of the values of @ref CLK_Source_TypeDef
 * @param   NewState Enable or Disable the Clock Switch interrupt.
 * @param   CLK_CurrentClockState current clock to switch OFF or to keep ON.
 * It can be set of the values of @ref CLK_CurrentClockState_TypeDef
 * @note LSI selected as master clock source only if LSI_EN option bit is set.
 * @retval ErrorStatus this shows the clock switch status (ERROR/SUCCESS).
 */
 ErrorStatus CLK_ClockSwitchConfig(CLK_SwitchMode_TypeDef CLK_SwitchMode, CLK_Source_TypeDef CLK_NewClock, FunctionalState ITState, CLK_CurrentClockState_TypeDef CLK_CurrentClockState)
 {
 CLK_Source_TypeDef clock_master;
 uint16_t DownCounter = CLK_TIMEOUT;
 ErrorStatus Swif = ERROR;
 
 /* Check the parameters */
 assert_param(IS_CLK_SOURCE_OK(CLK_NewClock));
 assert_param(IS_CLK_SWITCHMODE_OK(CLK_SwitchMode));
 assert_param(IS_FUNCTIONALSTATE_OK(ITState));
 assert_param(IS_CLK_CURRENTCLOCKSTATE_OK(CLK_CurrentClockState));
 
 /* Current clock master saving */
 clock_master = (CLK_Source_TypeDef)CLK->CMSR;
 
 /* Automatic switch mode management */
 if (CLK_SwitchMode == CLK_SWITCHMODE_AUTO)
 {
 /* Enables Clock switch */
 CLK->SWCR |= CLK_SWCR_SWEN;
 
 /* Enables or Disables Switch interrupt */
 if (ITState != DISABLE)
 {
 CLK->SWCR |= CLK_SWCR_SWIEN;
 }
 else
 {
 CLK->SWCR &= (uint8_t)(~CLK_SWCR_SWIEN);
 }
 
 /* Selection of the target clock source */
 CLK->SWR = (uint8_t)CLK_NewClock;
 
 /* Wait until the target clock source is ready */
 while((((CLK->SWCR & CLK_SWCR_SWBSY) != 0 )&& (DownCounter != 0)))
 {
 DownCounter--;
 }
 
 if(DownCounter != 0)
 {
 Swif = SUCCESS;
 }
 else
 {
 Swif = ERROR;
 }
 }
 else /* CLK_SwitchMode == CLK_SWITCHMODE_MANUAL */
 {
 /* Enables or Disables Switch interrupt  if required  */
 if (ITState != DISABLE)
 {
 CLK->SWCR |= CLK_SWCR_SWIEN;
 }
 else
 {
 CLK->SWCR &= (uint8_t)(~CLK_SWCR_SWIEN);
 }
 
 /* Selection of the target clock source */
 CLK->SWR = (uint8_t)CLK_NewClock;
 
 /* Wait until the target clock source is ready */
 while((((CLK->SWCR & CLK_SWCR_SWIF) != 0 ) && (DownCounter != 0)))
 {
 DownCounter--;
 }
 
 if(DownCounter != 0)
 {
 /* Enables Clock switch */
 CLK->SWCR |= CLK_SWCR_SWEN;
 Swif = SUCCESS;
 }
 else
 {
 Swif = ERROR;
 }
 }
 if(Swif != ERROR)
 {
 /* Switch OFF current clock if required */
 if((CLK_CurrentClockState == CLK_CURRENTCLOCKSTATE_DISABLE) && ( clock_master == CLK_SOURCE_HSI))
 {
 CLK->ICKR &= (uint8_t)(~CLK_ICKR_HSIEN);
 }
 else if((CLK_CurrentClockState == CLK_CURRENTCLOCKSTATE_DISABLE) && ( clock_master == CLK_SOURCE_LSI))
 {
 CLK->ICKR &= (uint8_t)(~CLK_ICKR_LSIEN);
 }
 else if ((CLK_CurrentClockState == CLK_CURRENTCLOCKSTATE_DISABLE) && ( clock_master == CLK_SOURCE_HSE))
 {
 CLK->ECKR &= (uint8_t)(~CLK_ECKR_HSEEN);
 }
 }
 return(Swif);
 }[/mw_shl_code]
 
 其次是寄存器方式,如下:
 [mw_shl_code=c,true]void ChangeCLKtoHSE()
 {
 CLK->SWCR |= 0x02;  /*允许切换时钟*/
 CLK->SWR = 0xB4;    /*选择外部时钟*/
 while(!(CLK->SWCR&0x08));
 }[/mw_shl_code]
 
 | 
 |