SysTick系统定时器

在前面的CLKSOURCE寄存器位也明确指明SysTick的时钟源为HCLK和HCLK / 8可选,然而在时钟树上却并没有体现时钟源可选这个关键信息,可见这是数据手册的漏洞,功能实现以寄存器的说明为主而非时钟树:SysTick的时钟源并非限定在HCLK / 8

将SysTick的时钟源设置为72MHZ,那么计数器减1间隔的时间为: (1 / 72MHz)s

SysTick系统定时器的重装载寄存器数值

使用标准外设库编程的时候我们只需要调用SysTick_Config(uint32_t ticks)函数即可 ,形参ticks用来设置重装载寄存器的值,最大不可超过2的24次方,当重装载寄存器的值递减到0的时候产生中断,然后重装载寄存器的值又重新装载往下递减计数,以此循环。
设置ticks的值等价于设置计时时间,中间有一个简单的换算过程:SysTick每递减1需要(1/72MHZ)s,那么定时1s则将ticks取值为72000000,定时1ms则ticks取值为72000,定时10us则ticks取值为720,定时1us则ticks取值为72,总归:

SysTick时钟源 / 1000   =>  定时1ms
SysTick时钟源 / 100000 =>  定时10us
SysTick时钟源 / 1000000    =>  定时1us

视频中:

时钟源为72HZ说明1us中有72个脉冲。若想延迟10us,则systick就要设置为72*10=720

 

阐述了以上知识点,下来就是编程练习了:利用SysTick系统定时器,实现精准延时,这个在实际工程项目中十分常用。
硬件平台正点原子MiniSTM32,实现的功能是精准延时让板载的两个LED灯闪烁。编程的要点是调用SysTick_Config()函数设置计数器的重装载值。
新建文件main.c和systick_test.h分别用于实现主体功能和函数声明:

systick_test.h
#ifndef __SYSTICK_TEST_H__
#define __SYSTICK_TEST_H__

#include "stm32f10x_conf.h"

void Led_CfgInit(void);
void SysTick_Delay_Us(__IO uint32_t us);
void SysTick_Delay_Ms(__IO uint32_t ms);

#endif /* __SYSTICK_TEST_H__ */

main.c
#define ALL_LED_ON  GPIO_ResetBits(GPIOA,GPIO_Pin_8);\
                    GPIO_ResetBits(GPIOD,GPIO_Pin_2)

#define ALL_LED_OFF GPIO_SetBits(GPIOA,GPIO_Pin_8);\
                    GPIO_SetBits(GPIOD,GPIO_Pin_2)

//PA8-->LED0,PD2-->LED1
void Led_CfgInit(void)
{
    GPIO_InitTypeDef GPIO_InitTypeStu;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOD, ENABLE);

    GPIO_InitTypeStu.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitTypeStu.GPIO_Pin = GPIO_Pin_8;
    GPIO_InitTypeStu.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitTypeStu);
    GPIO_SetBits(GPIOA,GPIO_Pin_8);         

    GPIO_InitTypeStu.GPIO_Pin = GPIO_Pin_2;
    GPIO_Init(GPIOD, &GPIO_InitTypeStu);
    GPIO_SetBits(GPIOD,GPIO_Pin_2);         
}

//配置SysTick的计数器计数的时间是1us,每间隔1us,CTRL的BIT[16]由0刷新为1
void SysTick_Delay_Us(__IO uint32_t us)
{
    uint32_t i;

    SysTick_Config(72);

    for (i = 0; i < us; i++)
    {
        while (!((SysTick->CTRL >> 16) & 0x01));
    }
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
}

//配置SysTick的计数器计数的时间是1ms,每间隔1us,CTRL的BIT[16]由0刷新为1
void SysTick_Delay_Ms(__IO uint32_t ms)
{
    uint32_t i;

    SysTick_Config(72000);

    for (i = 0; i < ms; i++)
    {
        //while (!(SysTick->CTRL & (1 << 16)));
        while (!((SysTick->CTRL >> 16) & 0x01));
    }
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
}

int main(void)
{
    SysTick_Delay_Us(10);
    Led_CfgInit();

    while (1)
    {
        ALL_LED_ON;

        SysTick_Delay_Ms(1000);

        ALL_LED_OFF;

        SysTick_Delay_Ms(5000);
    }
}

SysTick_Delay_Ms()和SysTick_Delay_Us()分别实现n个1Ms定时和n个1Us定时的功能。
以SysTick_Delay_Ms()为例,其中的SysTick_Config(72000)定义了每间隔1ms触发一次SysTick中断,当然,同时CTRL的BIT[16]会由0变为1,随后计数器又会从重装载器中取出72000开始递减,此时TRL的BIT[16]会由1变为0,如此循环。基于这个特点,这里采用轮询CTRL的BIT[16]的方法以达到延时的目的,这里中断处理函数未使用。

下来采用中断处理函数的方法:

--------------------- 本文来自 bright261 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/qq_29344757/article/details/75090137?utm_source=copy

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值