搜档网
当前位置:搜档网 › STM8教程-第八章 STM8S207时钟编程及其实例

STM8教程-第八章 STM8S207时钟编程及其实例

STM8教程-第八章 STM8S207时钟编程及其实例
STM8教程-第八章 STM8S207时钟编程及其实例

第八章STM8S207时钟编程及其实例

本章介绍STM8S207 的时钟编程。STM8S207 时钟控制器功能强大而灵活易用,允许程序运行中将主时钟从一个时钟源切换到另一个时钟源,而且同一个时钟源可以任意更改分频系数。

8.1 STM8 时钟控制简介

时钟控制器功能强大而且灵活易用。其目的在于使用户在获得最好性能的同时,亦能保证消耗的功率最低。

用户可独立地管理各个时钟源,并将它们分配到CPU 或各个外设。主时钟和CPU 时钟均带有预分频器。

具有安全可靠的无故障时钟切换机制,可在程序运行中将主时钟从一个时钟源切换到另一个时钟源。

抗电磁干扰时钟配置寄存器

为了避免由电磁干扰造成的对应用程序误写操作或系统挂起,大多数关键的时钟配置寄存器都有一个互补寄存器与之相对应。系统将会自动检测这些关键寄存器与其互补寄存器之间是否匹配。如果不匹配,则产生一个EMS 复位,从而使应用程序恢复到正常操作。详情请参见时钟寄存器描述。

1、主时钟源介绍

下面4种时钟源可用做主时钟

1、1-24MHz 高速外部晶振(HSE)

2、最大24MHz 高速外部时钟信号

3、16MHz 高速内部RC 振荡器(HSI)

4、128KHz 低速内部RC(LSI)

所以总的来说可以分为三种时钟源,HSE、HSI、LSI

2、时钟树,如下图所示

由上图可以发现,作为f_cpu 的时钟源可以来源于f_hse、f_hsi 经过HSIDIV分频后的时钟、f_lsi 这三个时钟源。而选择开关在CKM[7:0]中。由此事实上可以作为f_master 的时钟源频率有:

外部HSE 24MHz

内部高速HSI 16MHz、2 分频的8MHz、4 分频的4MHz、8 分频的2MHz(复位默认时钟源)

内部低速LSI 128KHz

上面得到的频率是f_master 的频率,然后f_master 还可以通过CPUDIV 来分频后提供f_cpu 的时钟,CPUDIV 可以为1、2、4、8、16、32、64、128 分频,最终得到是CPU 的时钟频率f_cpu。

3、时钟切换

时钟切换功能为用户提供了一种易用、快速、安全的从一个时钟源切换到另一个时钟源的途径。

(1)、系统启动

为使系统快速启动,复位后时钟控制器自动使用HSI 的8 分频(HSI/8)做为主时钟(2MHz)。其原因为HSI 的稳定时间短,而8 分频可保证系统在较差的VDD条件下安全启动。一旦主时钟源稳定,用户程序可将主时钟切换到另外的时钟源。

(2)、主时钟切换的过程

用户可选择下面两种方式切换时钟源:自动切换、手动切换自动切换使用户可使用最少的指令完成时钟源的切换。应用软件可继续其它操作而不用考虑切换事件所占的确切时间。具体方法在实例中讲解手动切换与自动切换不同,不能够立即切换,但它允许用户精确地控制切换事件发生的时间。具体方法在实例中讲解

8.2 时钟控制寄存器及设置

第六章的IO 口实验之所以能正常运行的原因是在于STM8S207 上电复位后有默认的时钟源,所以可以正常工作,但是为了更好使用和理解STM8S207 是有必要清楚掌握STM8S207 的时钟编程。

1、主时钟切换寄存器CLK_SWR

由上面的时钟树可知,CLK_SWR 对应的就是CKM[7:0],我也很好奇为什么不一致。

CLK_SWR 有特定的值才有效,是选择三个时钟源之一作为f_master 的时钟输入。

具体如下所示:

0xE1:HSI 为主时钟源(复位值)

0xD2:LSI 为主时钟源(仅当LSI_EN 选项位为1 时)

0xB4:HSE 为主时钟源

2、主时钟状态寄存器CLK_CMSR

对应着CLK_SWR,由硬件置位或清除。用以指示当前所选的主时钟源。如果该寄

存器中的值为无效值,则产生MCU 复位

0xE1:HSI 为主时钟源(复位值)

0xD2:LSI 为主时钟源(仅当LSI_EN 选项位为1 时)

0xB4:HSE 为主时钟源

3、时钟分频寄存器CLK_CKDIVR

这个寄存器对应了时钟树中的HSIDIV 以及CPUDIV,正如前面所说的HSIDIV可以

把内部高速RC 时钟源分频后才对f_master 提供时钟周期;CPUDIC 就是把

f_master 的时钟周期分频后再对f_cpu 提供时钟周期。具体分频倍数为:

HSIDIV[1:0]:高速内部时钟预分频器,由软件写入,用于指定HSI 分频因子。

00:fHSI = fHSI RC 输出

01:fHSI = fHSI RC 输出/2

10:fHSI = fHSI RC 输出/4

11:fHSI = fHSI RC 输出/8

CPUDIV[2:0]:CPU 时钟预分频器,由软件写入,用于指定CPU 时钟预分频因子。

000:fCPU = fMASTER

001:fCPU = fMASTER/2

010:fCPU = fMASTER/4

011:fCPU = fMASTER/8

100:fCPU = fMASTER/16

101:fCPU = fMASTER/32

110:fCPU = fMASTER/64

111:fCPU = fMASTER/128

4、切换控制寄存器CLK_SWCR

这个寄存器主要是查看时钟源的切换标志位,具体含义如下:

SWIF:时钟切换中断标志位由硬件置位或软件写0 清除。该位的含义取决于SWEN 位的状态。

手动切换模式下(SWEN=0):

0:目标时钟源未准备就绪

1:目标时钟源准备就绪

自动切换模式下(SWEN=0):

0:无时钟切换事件发生

1:有时钟切换事件发生

SWIEN:时钟切换中断使能由软件置位或清除

0:时钟切换中断禁用

1:时钟切换中断使能

SWEN:切换启动/停止由软件置位或清除。向该位写1 将切换主时钟至寄存器CLK_SWR 指定的时钟源。

0:禁止时钟切换的执行

1:使能时钟切换的执行

SWBSY:切换忙由硬件置位或清除。可由软件清除以复位时钟切换过程。

0:无时钟切换在进行。

1:时钟切换正在进行。

除上面上面主要涉及到的寄存器之外还有

内部时钟寄存器CLK_ICKR

外部时钟寄存器CLK_ECKR

外设时钟门控寄存器1 CLK_PCKENR1

外设时钟门控寄存器2 CLK_PCKENR2

时钟安全系统寄存器CLK_CSSR

可配置时钟输出寄存器CLK_CCOR

HIS 时钟修正寄存器CLK_HSITRIMR

SWIM 时钟控制寄存器CLK_SWIMCCR

这些寄存器在本章最后小节中才略为说明,时钟编程主要以前面3个寄存器有关。

例如CLK_SWR 是选择时钟源、CLK_SWCR 是时钟切换的控制寄存器,控制切换过程的设置而CLK_CKDIVR 是设置HIS 的分频系数和f_cpu 的分频系数

8.3 时钟编程基础应用

为了从不同角度理解时钟编程,这节分三个基础例程分别实现CPU 和内部高速时钟分频例程、自动切换时钟源例程以及手动切换时钟源例程。

8.3.1 CPU 分频以及HIS 分频例程

时钟编程本身并不需要外部设备,为了检验时钟分频的效果,在这里采用了一个LED 灯闪耀的效果来检验时钟的快慢,具体实现是相同的延时函数,在不同的时钟频率下跑的效果有很大差异,这样就达到了检查实验的效果。

如下图所示:在这里使用了LED1,也就是PD0 端口,对应的IO 口操作在前一章已经有过详细介绍。

本实验操作的寄存器只有一个,就是CLK_CKDIVR ,具体如下所示:

HSIDIV[1:0]:高速内部时钟预分频器,由软件写入,用于指定HSI 分频因子。

00:fHSI = fHSI RC 输出

01:fHSI = fHSI RC 输出/2

10:fHSI = fHSI RC 输出/4

11:fHSI = fHSI RC 输出/8(默认)

CPUDIV[2:0]:CPU 时钟预分频器,由软件写入,用于指定CPU 时钟预分频因子。000:fCPU = fMASTER

001:fCPU = fMASTER/2

010:fCPU = fMASTER/4

011:fCPU = fMASTER/8

100:fCPU = fMASTER/16

101:fCPU = fMASTER/32

110:fCPU = fMASTER/64

111:fCPU = fMASTER/128

程序代码如下:

/*

每一个时钟分频周期为闪耀灯5次

HSI CPU 1:1 16M

HSI CPU 1:4 4M

HSI CPU 2:4 2M

*/

#include "iostm8s207rb.h"

void delay_ms(int value);

int main( void )

{

int i;

//配置PD0为输出

PD_DDR_DDR0 = 1;

PD_CR1_C10 = 1;

PD_CR2_C20 = 0;

PD_ODR_ODR0 = 1;

while(1)

{

//HSI CPU 1:1 16M

CLK_CKDIVR = 0x00;

for(i=0;i!=10;++i)

{

PD_ODR_ODR0 = ~PD_ODR_ODR0;

delay_ms(100);

}

delay_ms(100);

//HSI CPU 1:4 4M

CLK_CKDIVR_HSIDIV = 0;

CLK_CKDIVR_CPUDIV = 2;

for(i=0;i!=10;++i)

{

PD_ODR_ODR0 = ~PD_ODR_ODR0;

delay_ms(100);

}

delay_ms(100);

//HSI CPU 2:4 2M

CLK_CKDIVR_HSIDIV = 1;

CLK_CKDIVR_CPUDIV = 2;

for(i=0;i!=10;++i)

{

PD_ODR_ODR0 = ~PD_ODR_ODR0;

delay_ms(100);

}

delay_ms(100);

}

}

/*

********************************************

简单延时

********************************************

*/

void delay_ms(int value)

{

int i,j;

if(value < 1)

value = 1;

for(i=0;i!=value;++i)

for(j=0;j!=5000;++j);

}

8.3.2 自动切换时钟源

因为STM8S 单片机上电复位是采用了内部时钟源HIS,所以在这里实现的功能是切换外部时钟源。由于STM8S207 开发板使用的外部晶振是24M,在主频大于16M 以上时,需要更改选项字,这里降低实验的难易程度,决定在这里采用外部时钟然后通过CPUDIV 2 分频得到的f_cpu 主频为12M

自动切换时钟源的对应步骤:

1、设置切换控制寄存器(CLK_SWCR)中的位SWEN,使能切换机制。

2、向主时钟切换寄存器(CLK_SWR)写入一个8 位的值,用以选择目标时钟源。寄

存器CLK_SWCR 中的SWBSY 被硬件置位,目标源振荡器启动。原时钟源依然被用于驱动内核和外设。一旦目标时钟源稳定,寄存器CLK_SWR 中的值将被复制到主时钟状态寄存器(CLK_CMSR)中去。此时,SWBSY 位被清除,新时钟源替代旧时钟源。寄存器CLK_SWCR 中的标志位SWIF 被置位,如果SWIEN 为1,则会产生一个中断。硬件采用8.3.1 的电路图,也是通过LED 实现检测效果

详细代码如下:

#include "iostm8s207rb.h"

void delay_ms(int value);

int main( void )

int i;

//配置PD0为输出模式

PD_DDR_DDR0 = 1;

PD_CR1_C10 = 1; //推挽输出

PD_CR2_C20 = 0;

PD_ODR_ODR0 = 1; //LED1灭

while(1)

{

//自动切换方式

CLK_SWCR_SWIEN = 0; //禁止时钟切换中断

CLK_SWCR_SWEN = 1; //使能切换机制

CLK_SWR = 0xB4; //0XE1: HSI为主时钟源(复位值,内部16MHz)//0XD2: LSI为主时钟源(仅当LSI_EN选项为1时)

//0XB4:HSE为主时钟源(外部时钟)

CLK_CKDIVR = 1; //CPUDIV 2分频

//切换后的时钟为12M

delay_ms(100);

for(i=0;i!=10;++i)

{

PD_ODR_ODR0 = ~PD_ODR_ODR0;

delay_ms(100);

}

//自动切换方式

CLK_SWCR_SWIEN = 0; //禁止时钟切换中断

CLK_SWCR_SWEN = 1; //使能切换机制

CLK_SWR = 0xE1; //0XE1: HSI为主时钟源(复位值,内部16MHz)//0XD2: LSI为主时钟源(仅当LSI_EN选项为1时)

//0XB4:HSE为主时钟源(外部时钟)

//切换后的时钟时16M/2 = 8M

delay_ms(100);

for(i=0;i!=10;++i)

{

PD_ODR_ODR0 = ~PD_ODR_ODR0;

delay_ms(100);

}

}

}

/*

********************************************

简单延时程序

********************************************

*/

void delay_ms(int value)

int i,j;

if(value < 1)

value = 1;

for(i=0;i!=value;++i)

for(j=0;j!=5000;++j);

}

8.3.3 手动切换时钟源

手动切换与自动切换不同,不能够立即切换,但它允许用户精确地控制切换事件发生的时间。

具体操作步骤:

1、向主时钟切换寄存器(CLK_SWR)写入一个8 位的值,用以选择目标时钟源。寄

存器CLK_SWCR 中的SWBSY 被硬件置位,目标源振荡器启动。原时钟源依然被用于驱动内核和外设。

2、用户软件需等待至目标时钟源稳定。寄存器CLK_SWCR 中的标志位SWIF用以

指示目标时钟源是否已稳定,如果SWIEN 为1,则会产生一个中断。

3、最后,由用户软件在所选的时间点,设置寄存器CLK_SWCR 中的位SWEN,执

行切换。在前两个例程的基础上,我们可以进行时钟编程的第三个例程了,具体的步骤如上所示,下面进行我们的软件编写。

/*

************************************************************

手动切换顺序

1、向CLK_SWR写入一个数据,选择目标时钟源

2、等待CLK_SWCR_SWIF = 1,时钟稳定

3、设置CLK_SWCR_SWEN = 1,开启时钟

************************************************************

*/

#include "iostm8s207rb.h"

void delay_ms(int value);

int main( void )

{

int i;

//配置LED1

PD_DDR_DDR0 = 1;

PD_CR1_C10 = 1; //推挽输出

PD_CR2_C20 = 0;

PD_ODR_ODR0 = 1; //LED1灭

CLK_SWCR_SWIEN = 0; //禁止中断

CLK_CKDIVR = 1; //CPUDIV设置为2分频

while(1)

{

//手动切换方式

CLK_SWR = 0xB4; //0XE1: HSI为主时钟源(复位值,内部16MHz)

//0XD2: LSI为主时钟源(仅当LSI_EN选项为1时)

//0XB4:HSE为主时钟源(外部时钟)

while(CLK_SWCR_SWIF == 0); //等待时钟稳定,输出时钟为12M

CLK_SWCR_SWEN = 1; //切换时钟

for(i=0;i!=10;++i)

{

PD_ODR_ODR0 = ~PD_ODR_ODR0;

delay_ms(100);

}

delay_ms(100);

//手动切换方式

CLK_SWR = 0xE1; //0XE1: HSI为主时钟源(复位值,内部16MHz)

//0XD2: LSI为主时钟源(仅当LSI_EN选项为1时)

//0XB4:HSE为主时钟源(外部时钟)

while(CLK_SWCR_SWIF == 0); //等待时钟稳定,输出时钟为8M

CLK_SWCR_SWEN = 1; //切换时钟

for(i=0;i!=10;++i)

{

PD_ODR_ODR0 = ~PD_ODR_ODR0;

delay_ms(100);

}

delay_ms(100);

}

}

/*

********************************************

简单延时程序

********************************************

*/

void delay_ms(int value)

{

int i,j;

if(value < 1)

value = 1;

for(i=0;i!=value;++i)

for(j=0;j!=5000;++j);

}

8.4 其它关于时钟编程寄存器

时钟编程的其它寄存器涉及到外设和时钟安全方面,在这里作为一点点补充。

1、内部时钟寄存器CLK_ICKR

内部寄存器主要负责HIS、LSI 的设置,对于这两个时钟源的状态以及开关作用。在低能耗运行程序中可以做到更低的能耗。详细功能如下:

REGAH:活跃停机模式(Active Halt)下电压调节器关闭。

==0,开;==1,关闭。

LSIRDY:LSI 时钟源就绪,硬件控制。

==0,未;==1,就绪态

LSIEN: LSI 的开关。

==0,关;==1,开

FHWU:从停机或活跃停机模式快速唤醒

==0,禁止;==1,使能

HSIRDY:HIS 准备就绪

==0,未;==1,就绪态

HSIEN:HIS 使能开关

==0,关;==1,开使能

2、外部时钟寄存器CLK_ECKR

对应于内部时钟寄存器,外部寄存器CLK_ECKR 也有同样的功能,如下所示:HSERDY:HSE 准备就绪

==0,未;==1,就绪

HSEEN:HSE 使能开关

==0,禁止;==1,使能

3、外设时钟门控制寄存器CLK_PCKENR1、CLK_PCKENR2

这两个寄存器是控制f_master 与片内外设的开关控制作用。当为0 时禁止

f_master 与外设连接,为1 是使能与外设连接。上电复位后是默认连接的,所以需要

关闭外设时钟以降低能耗时,可以适当禁止f_master 与外设之间的链接。

详细对应外设如下:

需要注意的是STM8S207 型号的芯片并没有片内寄存CAN 总线的。其它的寄存器不再说明,具体请见对应手册说明。

8.5 本章小结

本章的详细说明了STM8S207 的内部时钟关系,分别有三个时钟源以及内部高速时钟源的分频和CPU 的分频,而简单的例程分别对应着时钟分频、自动时钟切换以及手

动时钟切换三个方面,希望读者对STM8S207 的时钟编程有充分的了解以便实际的应用。

相关主题