中级会员
- 积分
- 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]
|
|