1 延时函数的作用
延时函数就是让程序在某个位置暂停执行一段指定的时间,然后再继续运行后面的代码,比如在每一个点灯大师入门时都需要经历的流水灯实验,或是等待外设初始化、时序匹配和按键消抖都离不开延时函数。
2 编程思路
目标:本篇文章主要实现延时的初始化、微秒和毫秒级别延时的函数设计;
2.1 初始化
1确定配置哪一个时钟信号为延时函数提供基准。
2确定每微秒需要的时钟周期。
2.2 微秒延时
1 对传入的参数进行校验
2 条件判断避免溢出24寄存器最大值
3 写入(设置)计数器初始值
4 启动硬件递减计数,并等待计数完成
5 失能计数器并清空寄存器
2.3 毫秒延时
调用微秒延时实现毫秒延时
3 代码示例
cpp
/*delay.h文件*/
#ifndef __DELAY_H
#define __DELAY_H
#include "stm32f10x.h"
void Delay_Init(void);
void DelayUs(uint32_t US);
void DelayMs(uint32_t MS);
#endif
cpp
/*delay.c文件*/
#include "delay.h"
static uint32_t CountUs = 0; //1us需要的SysTick周期数
/**
* @brief 延时初始化
*/
void Delay_Init(void)
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //HCLK/8作为SysTick时钟(硬件)
uint32_t SysCLK_MHz = SystemCoreClock / 1000000; // 72MHz / 1 000 000 = 72
CountUs = SysCLK_MHz / 8; // 72 / 8 = 9(每微秒9个周期 每毫秒9000个周期 每秒9000 000个周期)
}
/**
* @brief 微秒延时
* @param us延时微秒数
*/
void DelayUs(uint32_t US)
{
if(US == 0) return;
uint32_t load_val = US * CountUs - 1;
if(load_val > 0x00FFFFFF) load_val = 0x00FFFFFF; //防止溢出24位LOAD寄存器的最大值
SysTick->LOAD = load_val; //将计算好的值写入LOAD寄存器
SysTick->VAL = 0;
SysTick->CTRL = 0x01; //使能 无中断 HCLK/8
while(!(SysTick->CTRL & (1 << 16))); //CTRL的第16位是COUNTFLAG,当计数器从1→0时,硬件自动置1。
SysTick->CTRL = 0x00;
SysTick->VAL = 0;
}
/**
* @brief 毫秒延时
* @param ms延时毫秒数
*/
void DelayMs(uint32_t MS)
{
while(MS--)
{
DelayUs(1000); // 复用微秒延时
}
}
注:本篇文章以STM32F10系列编写。
注:以上内容仅个人理解,不具备唯一性和绝对正确性,仅供参考。