Stm32-SysTick详解

写在最前

​ 本文是个人学习Stm32时所做笔记,没有写过C51,但学校学过 微机原理 ,但没学好,实验套件是正点原子Stm32zet6精英板,参考资料为正点原子所提供,本文所涉及代码均使用固件库。本文供自己日后需要时复习所用,同时希望可以给有需要的小伙伴给予帮助。
本文使用滴答定时器实现精准延时。
才疏学浅还望不吝指正!

一、滴答定时器(SysTick)

​ Cortex‐M3处理器内部包含了一个简单的定时器。因为所有的CM3芯片都带有这个定时

器,软件在不同 CM3器件间的移植工作得以化简。该定时器的时钟源可以是内部时钟(FCLK,

CM3上的自由运行时钟),或者是外部时钟(CM3处理器上的STCLK信号),具体需要检视

芯片的器件手册来决定选择什么作为时钟源。

​ SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15)。SysTick定时器能产生中断,在中断向量表中有它一席之地。

​ 注:摘自Cortex-M3权威指南

​ 简言之,SysTick定时器可以选择不同的时钟源,可以产生中断,并且SysTick定时器是一个倒计数的计数器,每隔一个时钟周期计数值减一,计数至0后重新从计数初值处开始倒计数。

​ 例如:计数初值为100,经过一个时钟周期后,计数值减一,即99,98,97……1,0;计数至0后,又重新开始从100开始倒计数至0。

​ 可以借此做精准延时。

二、SysTick的组成

​ SysTick包含四个寄存器,都是24位的寄存器,分别是:

>SysTick控制及状态寄存器 -- 0xE000 E010
>
>SysTick重装载寄存器 -- 0xE000 E014
>
>SysTick当前值寄存器 -- 0xE000 E018
>
>SysTick校准值寄存器 -- 0xE000 E01C

​ 它们的功能如下:
Stm32-SysTick详解_第1张图片

​ 注:摘自Cortex-M3权威指南

三、SysTick实现精准延时

3.1 SysTick编程步骤

  1. 配置SysTick时钟源

    固件库函数:SysTick_CLKSourceConfig( );

    头文件:misc.h

    参数:

    ​ SysTick_CLKSource_HCLK_Div8 --> 系统时钟 HCLK的8分频

    ​ SysTick_CLKSource_HCLK --> 系统时钟 HCLK

  2. 配置SysTick的重装载值和清空计数值

    重装载值寄存器是一个24位的寄存器,在设置重装载值时,重装载值不能超过2^24 - 1

    (1)使用结构体SysTick_Type进行设置,该结构体在core_cm3.h中声明,声明如下:

    Stm32-SysTick详解_第2张图片

    (2)在core_cm3.h中,将 (SysTick_Type *) define 为SysTick,因此可以这样使用:

    ​ SysTick->CTRL |= 0x01; //使能SysTick定时器

    ​ 在设置重装载值时,重装载值不能超过2^24 - 1

  3. 开启SysTick定时器

    SysTick->CTRL |= 0x01; //使能SysTick定时器

3.2 延时初始化

​ 设置SysTick的时钟源,若系统时钟为72MHz,经过8分频后,SysTick的时钟为9MHz,也就是说每计数一次需要的时间为 T = 1/(9MHz),换算一下,即T = 1/9 us,换言之:延时 1 微妙,需要计数9次,因此微妙级别的倍频因子fac_us即等于9,为了可移植性,fas_us = (系统内核时钟频率) / 8000000,毫秒级别的倍频因子fac_ms = 1000*fac_ms即可。

void delay_init()
{
    /* 配置时钟源 --> 72MHz / 8 = 9MHz,
	*  滴答定时器每计数一次所需时间为 T = 1/(9MHz) s,即 1us = 10^(-6)s , 
	*  T = (1/9) * 10^(-6) s = 1/9 us , 即每计数一次的时间为1/9微秒
	*  换言之,系统时钟频率为72MHz时,1us需要计数9次
	*/
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
	/* fac_us 和 fac_ms 是定义的全局变量,是倍频因子*/
	fac_us = SystemCoreClock / 8000000;
	fac_ms = 1000 * fac_us;
}

3.3 微妙级延时实现

​ SysTick时钟频率为9MHz时,要延时10微秒,即传入的参数 us = 10,而计数一次需要的时间是1/9 微秒,因此计数初值需要设置为 10/(1/9);这里fac_us实际上是延时1微秒需要计数的次数,延时10微妙,需要计数10*fac_us次,即计数重装载值为10 * fac_us。

void delay_us(unsigned int us)
{
	unsigned int temp = 0;
	/*1us需要计数9次,计数初值为9*/
	/*设置重装载值*/
	SysTick->LOAD = fac_us * us;
	/*当前值寄存器清0,即清空计数器*/
	SysTick->VAL = 0x00;
	/*滴答定时器控制寄存器,使能滴答定时器*/
	SysTick->CTRL |= 0x01;
	
	do
	{
		/*获取控制寄存器的当前状态*/
		temp = SysTick->CTRL;
		
	}while((temp & 0x01) && !(temp & (0x01 << 16)));
	SysTick->CTRL &= 0x00;
	SysTick->VAL = 0x00;
}

3.4 毫秒级延时实现

​ 由于SysTick只提供了一个24位的倒计数寄存器,因此计数初值不能超过2^24-1,即 fas_ms * ms不能超过2^24 - 1。

void delay_ms(unsigned int ms)
{
	unsigned int temp = 0;
	/*设置重装载值*/
    if(fac_ms * ms <= ((0x01 << 24) - 1))
    {
        SysTick->LOAD = fac_ms * ms;
    }
    else
    {
        return ;
    }
	/*设置重装载值*/
	SysTick->VAL = 0x00;
	/*滴答定时器控制寄存器,使能滴答定时器*/
	SysTick->CTRL |= 0x01;
	
	do
	{
		/*获取控制寄存器的当前状态*/
		temp = SysTick->CTRL;
		
	}while((temp & 0x01) && !(temp & (0x01 << 16)));
	SysTick->CTRL &= 0x00;
	SysTick->VAL = 0x00;
}

你可能感兴趣的:(笔记,stm32,stm32,单片机,嵌入式硬件)