×
嵌入式 > 技术百科 > 详情

STM8 时钟切换

发布时间:2020-12-18 发布时间:
|

HSE、HSI、LSI 都可以作为系统主时钟源,STM8 单片机复位以后默认 HSI 的 8 分频作为系统主时钟,其原因是 HSI 稳定时间短,而其 8 分频又可以保证系统在较差的 VDD 条件下安全启动。在系统运行的过程中可以切换系统的主时钟源。系统时钟源的切换有 2 种方式:自动切换、手动切换。


自动切换可以使用最少的指令来完成主时钟源的切换,用户程序可以处理其他事物而不用关心确切的切换时间;手动切换在硬件准备好之后不立即切换,允许用户精确的控制切换发生的时间。


自动切换的步骤为:

1.设置切换控制寄存器 CLK_SWCR 中的 SWEN 位,使能时钟切换。


2.设置主时钟切换寄存器 CLK_SWR,选择目标时钟源。切换控制寄存器中的切换忙标志位 SWBSY被硬件置位,目标时钟源启动,原时钟源依旧驱动内核和外设。一旦目标时钟源稳定,主时钟切换寄存器 CLK_SWR 中的值将被复制到主时钟状态寄存器 CLK_CMSR 中。此时,SWBSY 位被硬件清零,目标时钟源替代原时钟源,CLK_SWCR 寄存器中的时钟切换中断标志位 SWIF 被硬件置位,如此时钟切换中断被使能,则会产生中断。


手动切换的步骤为:

1.设置主时钟切换寄存器 CLK_SWR,选择目标时钟源。SWBSY 位会被硬件置位,目标时钟源启动,原时钟源依然驱动内核和外设。


2.用户程序通过读取 CLK_SWCR 寄存器的 SWIF 位来等待目标时钟源准备就绪,SWIF 为 1 时代表目标时钟源准备就绪。如果时钟切换被使能,SWIF 被硬件置位时将触发中断。


3.如果目标时钟源准备就绪,则用户程序在预期的时间点将 CLK_SWCR 寄存器的 SWEN 位置位来进行时钟切换。


通过判断 SWIF 位可以判断时钟切换是否完成,通过读取 CLK_CMSR 寄存器可以得知当前的系统主时钟源。切换完成之后要写 SWIF 位为 0 你来清零此标志。


不管是自动切换还是手动切换,如果原时钟源在切换后仍然被其他模块使用,则原时钟源不会被自动关闭,需要通过配置内部时钟寄存器 CLK_ICKR 或外部时钟寄存器 CLK_ECKR 来关闭。


如果时钟切换没有成功,可以通过软件清零 SWBSY 位来复位当前切换,使 CLK_SWR 恢复原时钟源。


使用寄存器来切换时钟


自动切换和手动切换的流程图对比如图所示。


下面我们通过实例来掌握 STM8S 时钟切换的操作。本章节的实例设想开发板的 LED 分别在系统主时钟为 HSI/8、HSI、HSE/16、LSI 的时候各闪烁 5 次,系统主时钟的切换分别采用自动切换和手动切换,通过实验现象即可判断系统时钟切换是否成功。

void main( void )

{

unsigned char i;

InitLED();

//HSI 做主时钟源

//复位后默认主时钟为 16M/8=2M

for(i=0;i<5;i++)

{

PC_ODR=(0<<3);//PC_ODR 第 3 位清零,输出低电平

PE_ODR&=0xFE; //PE_ODR 第 0 位清零,输出低电平

PD_ODR&=0xF7;//PD_ODR 第 3 位清零,输出低电平

Delay(50000); //延时

PC_ODR=(1<<3);//PC_ODR 第 3 位置位,输出高电平

PE_ODR|=0x01; //PE_ODR 第 0 位置位,输出高电平

PD_ODR|=0x08;//PD_ODR 第 3 位清零,输出低电平

Delay(50000); //延时

}

CLK_CKDIVR=0x00;//HSI 不分频,主时钟 16M

for(i=0;i<5;i++)

{

PC_ODR=(0<<3);//PC_ODR 第 3 位清零,输出低电平

PE_ODR&=0xFE; //PE_ODR 第 0 位清零,输出低电平

PD_ODR&=0xF7;//PD_ODR 第 3 位清零,输出低电平

Delay(50000); //延时

PC_ODR=(1<<3);//PC_ODR 第 3 位置位,输出高电平

PE_ODR|=0x01; //PE_ODR 第 0 位置位,输出高电平

PD_ODR|=0x08;//PD_ODR 第 3 位清零,输出低电平

Delay(50000); //延时

}

//HSE 做主时钟源,自动时钟切换

CLK_SWCR|=0x02;//时钟切换启动,SWEN=1

CLK_SWR=0xB4; //选择目标时钟源,0xB4=HSE

while((CLK_SWCR&0x08)==0);//等待切换时间发生,此时 SWIF=1

CLK_SWCR&=0xF7;//清除切换标志

if(CLK_CMSR==0xB4)//判断主时钟源是否为 HSE

{

CLK_CKDIVR=0x04; //CPU 时钟频率为主时钟源 16 分频

for(i=0;i<5;i++)

{

PC_ODR=(0<<3);//PC_ODR 第 3 位清零,输出低电平

PE_ODR&=0xFE; //PE_ODR 第 0 位清零,输出低电平

PD_ODR&=0xF7;//PD_ODR 第 3 位清零,输出低电平

Delay(50000); //延时

PC_ODR=(1<<3);//PC_ODR 第 3 位置位,输出高电平

PE_ODR|=0x01; //PE_ODR 第 0 位置位,输出高电平

PD_ODR|=0x08;//PD_ODR 第 3 位清零,输出低电平

Delay(50000); //延时

}

}

//LSI 做主时钟源,手动时钟切换,请先在选项字节中使能 LSI

CLK_SWR=0xD2;//选择目标时钟源,0xD2=LSI

while((CLK_SWCR&0x08)==0);//等待目标时钟源准备就绪,此时 SWIF=1

CLK_SWCR&=0xF7;//清除切换标志

CLK_SWCR|=0x02;//进行切换

if(CLK_CMSR==0xD2)

{

for(i=0;i<5;i++)

{

PC_ODR=(0<<3);//PC_ODR 第 3 位清零,输出低电平

PE_ODR&=0xFE; //PE_ODR 第 0 位清零,输出低电平

PD_ODR&=0xF7;//PD_ODR 第 3 位清零,输出低电平

Delay(300); //延时

PC_ODR=(1<<3);//PC_ODR 第 3 位置位,输出高电平

PE_ODR|=0x01; //PE_ODR 第 0 位置位,输出高电平

PD_ODR|=0x08;//PD_ODR 第 3 位清零,输出低电平

Delay(300); //延时

}

}

while(1)

{

}

}

void InitLED(void)

{

PC_DDR|=0x08;//设置 PC3 为输出模式

PC_CR1|=0x08;//设置 PC3 为推挽输出

PC_CR2|=0x00;//设置 PC3 为 10MHz 快速输出

PE_DDR|=0x01;//设置 PE0 为输出模式

PE_CR1|=0x01;//设置 PE0 为推挽输出

PE_CR2|=0x00;//设置 PE0 为 10MHz 快速输出

PD_DDR|=0x08;//设置 PD3 为输出模式

PD_CR1|=0x08;//设置 PD3 为推挽输出

PD_CR2|=0x00;//设置 PD3 为 10MHz 快速输出

}


  InitLED();函数为 LED 初始化函数,与前面章节的代码相同。


  首先 HSI 做系统主时钟。系统复位后默认 HSI/8=2M 为系统主时钟;接着,通过修改 CLK_CKDIVR寄存器,使 HSI 不分频作为系统主时钟。


  系统主时钟由 HSI 切换至 HSE 是通过自动切换方式实现的。首先置位 SWEN 位以启动时钟切换;然后设置 CLK_SWR 寄存器以选择目标时钟源为 HSE;通过读取 SWIF 位的值来判断系统时钟切换是否完成,如果 SWIF 为 1 则表示转换完成;转换完成之后要通过软件来写入 0 来清标志位 SWIF。


  系统主时钟由 HSE 切换至 LSI 是通过手动切换的方式实现的。在编写程序之前需要先修改选项字节OPTION BYTE 以使能 LSI;程序中先设置 CLK_SWR 寄存器以选择目标时钟源为 LSI;通过读取 SWIF的值等待至 LSI 就绪之后清除 SWIF 位,接着置位 SWEN 位启动转换。


  可以通过读取 CLK_CMSR 寄存器查看当前系统时钟源是否为预设的目标时钟源。


  实验现象为 LED 以 4 种不同的频率闪烁,与预期的实验效果相符。




『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
ADI 高精度低功耗精密放大器