STM32
登录
直播中
康桃花
7年用户
925经验值
私信
关注
[问答]
STM32系统定时器有哪几种延时方式呢
开启该帖子的消息推送
STM32
定时器
延时
什么是SYS
ti
ck系统定时器呢?
如何对SYSTick库函数进行配置呢?
回帖
(1)
陈小鸥
2021-11-23 10:25:46
SYSTick 简介
系统定时器,24bit,只能递减,存在于内核,嵌套在NVIC中,所有的Cortex-M内核的单片机都具有这个定时器。一般我们设置系统时钟 SYSCLK 等于 72M。当重装载数值寄存器的值递减到 0 的时候,系统定时器就产生一次中断,以此循环复。因为 SysTick 是属于 CM3内核的外设,所以所有基于 CM3 内核的单片机都具有这个系统定时器,使得软件在 CM3 单片机中可以很容易的移植。系统定时器一般用于操作系统,用于产生时基,维持操作系统的心跳。SysTick 在STM32的参考手册里面介绍的很简单,其详细介绍,请参阅《Cortex-M3 权威指南》。
Systick 寄存器
SysTick控制及状态寄存器
SysTick重装载数值寄存器
SysTick当前数值寄存器
Systick 定时时间计算
接下来就进行三种延时的讲解,普通的减数延时我就不进行赘述了,相信大家都会。而我要将的是单片机编程过程中经常用到延时函数,当然莫过于是毫秒 ms 级 延时和微秒 us 级延时
中断延时法
仿火哥延时,该方法非常适合于初学者
仿原子延时,直接操作寄存器。强烈推荐此方法!!!
首先跟大家讲解下SYSTick库函数的配置,只要理解了其中的原理。那么最后一种操作寄存器的方法就很容易上手。
// 这个 固件库函数 在 core_cm3.h中
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
// reload 寄存器为24bit,最大值为2^24
if (ticks 》 SysTick_LOAD_RELOAD_Msk) return (1);
// 配置 reload 寄存器的初始值
SysTick-》LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;
// 配置中断优先级为 1《《4-1 = 15,优先级为最低
NVIC_SetPriority (SysTick_IRQn, (1《《__NVIC_PRIO_BITS) - 1);
// 配置 counter 计数器的值
SysTick-》VAL = 0;
// 配置systick 的时钟为 72M
// 使能中断
// 使能systick
SysTick-》CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk;
return (0);
}
1. 中断延时法
/***************************************************************************************
* 函 数: void Interrupt_Delay_us(__IO u32 nTime)
* 功 能: 毫秒级延时
* 参 数: us传入微秒参数
* 返回值:无
* 备 注: LOAD为24位寄存器,nTime的最大传入值为 2的24次方(0xFFFFFF*72) / SYSCLK = 16777216 us
*****************************************************************************************/
void Interrupt_Delay_us(__IO u32 nTime)
{
//SYSTICK分频--10us的系统时钟中断
if (SysTick_Config(SystemCoreClock/100000))
{
while (1);
}
TimingDelay = nTime;
while(TimingDelay != 0);
SysTick-》CTRL=0x00; //关闭计数器
SysTick-》VAL =0X00; //清空计数器
}
/***************************************************************************************
* 函 数: void Interrupt_Delay_us(__IO u32 nTime)
* 功 能: 毫秒级延时
* 参 数: ms 传入微秒参数
* 返回值:无
* 备 注: LOAD为24位寄存器,nTime的最大传入值为 2的24次方(0xFFFFFF*72*1000) / SYSCLK = 16777 ms
*****************************************************************************************/
void Interrupt_Delay_us(__IO u32 nTime)
{
//SYSTICK分频--1ms的系统时钟中断
if (SysTick_Config(SystemCoreClock/1000))
{
while (1);
}
TimingDelay = nTime;
while(TimingDelay != 0);
SysTick-》CTRL=0x00; //关闭计数器
SysTick-》VAL =0X00; //清空计数器
}
//获取节拍程序
void TimingDelay_Decrement(void)
{
if (TimingDelay != 0x00)
{
TimingDelay--;
}
}
2. 仿火哥延时
/***************************************************************************************
* 函 数: SysTick_Delay_Us( __IO uint32_t us)
* 功 能: 毫秒级延时
* 参 数: us传入微秒参数
* 返回值:无
* 备 注: LOAD为24位寄存器,ms的最大传入值为 2的24次方(0xFFFFFF*72) / SYSCLK = 16777216 us
*****************************************************************************************/
void SysTick_Delay_Us( __IO uint32_t us)
{
uint32_t i;
SysTick_Config(SystemCoreClock/1000000);
for(i=0;i《us;i++)
{
// 当计数器的值减小到0的时候,CRTL寄存器的位16会置1
while( !((SysTick-》CTRL)&(1《《16)) );
}
// 关闭SysTick定时器
SysTick-》CTRL &=~SysTick_CTRL_ENABLE_Msk;
}
/***************************************************************************************
* 函 数: void SysTick_Delay_Ms( __IO uint32_t ms)
* 功 能: 毫秒级延时
* 参 数: ms 传入微秒参数
* 返回值:无
* 备 注: LOAD为24位寄存器,ms的最大传入值为 2的24次方(0xFFFFFF*72*1000) / SYSCLK = 16777 ms
*****************************************************************************************/
void SysTick_Delay_Ms( __IO uint32_t ms)
{
uint32_t i;
SysTick_Config(SystemCoreClock/1000);
for(i=0;i《ms;i++)
{
// 当计数器的值减小到0的时候,CRTL寄存器的位16会置1
// 当置1时,读取该位会清0
while( !((SysTick-》CTRL)&(1《《16)) );
}
// 关闭SysTick定时器
SysTick-》CTRL &=~ SysTick_CTRL_ENABLE_Msk;
}
3. 非中断方式,直接操作寄存器
uint8_t D_us=0; //微秒系数
uint16_t D_ms=0; //毫秒系数
/***************************************************************************************
* 函 数: void Delay_Init(void)
* 功 能: 延时函数初始化
* 参 数: 无
* 返回值:无
* 备 注: T(s) = 1/F(Hz) //赫兹时间转换公式
*****************************************************************************************/
void Delay_Init(void)
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
D_us = SystemCoreClock/1000000;// 1us
D_ms = (uint16_t)D_us * 1000;
}
/***************************************************************************************
* 函 数: void Delay_us(uint32_t nus)
* 功 能: 微秒级延时
* 参 数: nus 传入微秒参数
* 返回值:无
* 备 注: LOAD为24位寄存器,nus 的最大传入值为 2的24次方(0xFFFFFF*72) / SYSCLK = 16777216 us
*****************************************************************************************/
void Delay_us(uint32_t nus)
{
uint32_t temp;
SysTick-》CTRL = 0x00; //关闭SysTick定时器
SysTick-》LOAD = nus*72; //延时重装载值
SysTick-》VAL = 0x00; //清空计数器
SysTick-》CTRL |= 0x01 ; //启动SysTick定时器
do
{
temp=SysTick-》CTRL;
}while((temp&0x01)&&!(temp&(1《《16))); //等待延时结束
SysTick-》CTRL = 0x00; //关闭SysTick定时器
SysTick-》VAL = 0X00; //清空计数器
}
/***************************************************************************************
* 函 数: void Delay_ms(uint32_t nms)
* 功 能: 毫秒级延时
* 参 数: nms 传入微秒参数
* 返回值:无
* 备 注: LOAD为24位寄存器,nms 的最大传入值为 2的24次方(0xFFFFFF*72*1000) / SYSCLK = 16777 ms
*****************************************************************************************/
void Delay_ms(uint32_t nms)
{
uint32_t temp;
SysTick-》CTRL = 0x00; //关闭SysTick定时器
SysTick-》LOAD = nms*72000; //延时重装载值
SysTick-》VAL = 0x00; //清空计数器
SysTick-》CTRL |= 0x01 ; //启动SysTick定时器
do
{
temp=SysTick-》CTRL;
}while((temp&0x01)&&!(temp&(1《《16))); //等待延时结束
SysTick-》CTRL = 0x00; //关闭SysTick定时器
SysTick-》VAL = 0X00; //清空计数器
}
三种方式各有利弊,第一种方式采用采用中断方式延时,由于中断的存在,不利于在其他中断中调用此延时函数。第二种方式非常适合初学者使用,简单偏于理解。第三种方式直接操作寄存器,看起来比较繁琐,其实只要耐心去看几遍也就很容易理解了,个人感觉第三种比较好用。
SYSTick 简介
系统定时器,24bit,只能递减,存在于内核,嵌套在NVIC中,所有的Cortex-M内核的单片机都具有这个定时器。一般我们设置系统时钟 SYSCLK 等于 72M。当重装载数值寄存器的值递减到 0 的时候,系统定时器就产生一次中断,以此循环复。因为 SysTick 是属于 CM3内核的外设,所以所有基于 CM3 内核的单片机都具有这个系统定时器,使得软件在 CM3 单片机中可以很容易的移植。系统定时器一般用于操作系统,用于产生时基,维持操作系统的心跳。SysTick 在STM32的参考手册里面介绍的很简单,其详细介绍,请参阅《Cortex-M3 权威指南》。
Systick 寄存器
SysTick控制及状态寄存器
SysTick重装载数值寄存器
SysTick当前数值寄存器
Systick 定时时间计算
接下来就进行三种延时的讲解,普通的减数延时我就不进行赘述了,相信大家都会。而我要将的是单片机编程过程中经常用到延时函数,当然莫过于是毫秒 ms 级 延时和微秒 us 级延时
中断延时法
仿火哥延时,该方法非常适合于初学者
仿原子延时,直接操作寄存器。强烈推荐此方法!!!
首先跟大家讲解下SYSTick库函数的配置,只要理解了其中的原理。那么最后一种操作寄存器的方法就很容易上手。
// 这个 固件库函数 在 core_cm3.h中
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
// reload 寄存器为24bit,最大值为2^24
if (ticks 》 SysTick_LOAD_RELOAD_Msk) return (1);
// 配置 reload 寄存器的初始值
SysTick-》LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;
// 配置中断优先级为 1《《4-1 = 15,优先级为最低
NVIC_SetPriority (SysTick_IRQn, (1《《__NVIC_PRIO_BITS) - 1);
// 配置 counter 计数器的值
SysTick-》VAL = 0;
// 配置systick 的时钟为 72M
// 使能中断
// 使能systick
SysTick-》CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk;
return (0);
}
1. 中断延时法
/***************************************************************************************
* 函 数: void Interrupt_Delay_us(__IO u32 nTime)
* 功 能: 毫秒级延时
* 参 数: us传入微秒参数
* 返回值:无
* 备 注: LOAD为24位寄存器,nTime的最大传入值为 2的24次方(0xFFFFFF*72) / SYSCLK = 16777216 us
*****************************************************************************************/
void Interrupt_Delay_us(__IO u32 nTime)
{
//SYSTICK分频--10us的系统时钟中断
if (SysTick_Config(SystemCoreClock/100000))
{
while (1);
}
TimingDelay = nTime;
while(TimingDelay != 0);
SysTick-》CTRL=0x00; //关闭计数器
SysTick-》VAL =0X00; //清空计数器
}
/***************************************************************************************
* 函 数: void Interrupt_Delay_us(__IO u32 nTime)
* 功 能: 毫秒级延时
* 参 数: ms 传入微秒参数
* 返回值:无
* 备 注: LOAD为24位寄存器,nTime的最大传入值为 2的24次方(0xFFFFFF*72*1000) / SYSCLK = 16777 ms
*****************************************************************************************/
void Interrupt_Delay_us(__IO u32 nTime)
{
//SYSTICK分频--1ms的系统时钟中断
if (SysTick_Config(SystemCoreClock/1000))
{
while (1);
}
TimingDelay = nTime;
while(TimingDelay != 0);
SysTick-》CTRL=0x00; //关闭计数器
SysTick-》VAL =0X00; //清空计数器
}
//获取节拍程序
void TimingDelay_Decrement(void)
{
if (TimingDelay != 0x00)
{
TimingDelay--;
}
}
2. 仿火哥延时
/***************************************************************************************
* 函 数: SysTick_Delay_Us( __IO uint32_t us)
* 功 能: 毫秒级延时
* 参 数: us传入微秒参数
* 返回值:无
* 备 注: LOAD为24位寄存器,ms的最大传入值为 2的24次方(0xFFFFFF*72) / SYSCLK = 16777216 us
*****************************************************************************************/
void SysTick_Delay_Us( __IO uint32_t us)
{
uint32_t i;
SysTick_Config(SystemCoreClock/1000000);
for(i=0;i《us;i++)
{
// 当计数器的值减小到0的时候,CRTL寄存器的位16会置1
while( !((SysTick-》CTRL)&(1《《16)) );
}
// 关闭SysTick定时器
SysTick-》CTRL &=~SysTick_CTRL_ENABLE_Msk;
}
/***************************************************************************************
* 函 数: void SysTick_Delay_Ms( __IO uint32_t ms)
* 功 能: 毫秒级延时
* 参 数: ms 传入微秒参数
* 返回值:无
* 备 注: LOAD为24位寄存器,ms的最大传入值为 2的24次方(0xFFFFFF*72*1000) / SYSCLK = 16777 ms
*****************************************************************************************/
void SysTick_Delay_Ms( __IO uint32_t ms)
{
uint32_t i;
SysTick_Config(SystemCoreClock/1000);
for(i=0;i《ms;i++)
{
// 当计数器的值减小到0的时候,CRTL寄存器的位16会置1
// 当置1时,读取该位会清0
while( !((SysTick-》CTRL)&(1《《16)) );
}
// 关闭SysTick定时器
SysTick-》CTRL &=~ SysTick_CTRL_ENABLE_Msk;
}
3. 非中断方式,直接操作寄存器
uint8_t D_us=0; //微秒系数
uint16_t D_ms=0; //毫秒系数
/***************************************************************************************
* 函 数: void Delay_Init(void)
* 功 能: 延时函数初始化
* 参 数: 无
* 返回值:无
* 备 注: T(s) = 1/F(Hz) //赫兹时间转换公式
*****************************************************************************************/
void Delay_Init(void)
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
D_us = SystemCoreClock/1000000;// 1us
D_ms = (uint16_t)D_us * 1000;
}
/***************************************************************************************
* 函 数: void Delay_us(uint32_t nus)
* 功 能: 微秒级延时
* 参 数: nus 传入微秒参数
* 返回值:无
* 备 注: LOAD为24位寄存器,nus 的最大传入值为 2的24次方(0xFFFFFF*72) / SYSCLK = 16777216 us
*****************************************************************************************/
void Delay_us(uint32_t nus)
{
uint32_t temp;
SysTick-》CTRL = 0x00; //关闭SysTick定时器
SysTick-》LOAD = nus*72; //延时重装载值
SysTick-》VAL = 0x00; //清空计数器
SysTick-》CTRL |= 0x01 ; //启动SysTick定时器
do
{
temp=SysTick-》CTRL;
}while((temp&0x01)&&!(temp&(1《《16))); //等待延时结束
SysTick-》CTRL = 0x00; //关闭SysTick定时器
SysTick-》VAL = 0X00; //清空计数器
}
/***************************************************************************************
* 函 数: void Delay_ms(uint32_t nms)
* 功 能: 毫秒级延时
* 参 数: nms 传入微秒参数
* 返回值:无
* 备 注: LOAD为24位寄存器,nms 的最大传入值为 2的24次方(0xFFFFFF*72*1000) / SYSCLK = 16777 ms
*****************************************************************************************/
void Delay_ms(uint32_t nms)
{
uint32_t temp;
SysTick-》CTRL = 0x00; //关闭SysTick定时器
SysTick-》LOAD = nms*72000; //延时重装载值
SysTick-》VAL = 0x00; //清空计数器
SysTick-》CTRL |= 0x01 ; //启动SysTick定时器
do
{
temp=SysTick-》CTRL;
}while((temp&0x01)&&!(temp&(1《《16))); //等待延时结束
SysTick-》CTRL = 0x00; //关闭SysTick定时器
SysTick-》VAL = 0X00; //清空计数器
}
三种方式各有利弊,第一种方式采用采用中断方式延时,由于中断的存在,不利于在其他中断中调用此延时函数。第二种方式非常适合初学者使用,简单偏于理解。第三种方式直接操作寄存器,看起来比较繁琐,其实只要耐心去看几遍也就很容易理解了,个人感觉第三种比较好用。
举报
更多回帖
rotate(-90deg);
回复
相关问答
STM32
定时器
延时
请问一下
STM32
定时器
的脉冲计数
有
哪几种
方式
呢
2021-11-22
1751
STM32
定时器
与外部触发的同步
有
哪几种
模式
呢
2021-11-22
2020
STM32
F10ZET6通用
定时器
的计数模式
有
哪几种
2021-11-23
1472
stm32
定时器
有
哪几种
?
2021-11-23
1364
STM32
常见的
定时器
是
哪几种
?
2021-11-18
1559
根据继电器触点
延时方式
欠电流继电器分为
哪几种
2021-09-09
1362
定时器
的功能主要有
哪几种
方式
2021-08-12
2358
Keil C51单片机程序设计中的精确
延时方
法
有
哪几种
2021-11-02
2024
STM32
F4
定时器
的计数
器
模式
有
哪几种
呢
2021-11-23
2670
定时器
包括
哪几种
?其
有
何不同
2021-09-08
2916
发帖
登录/注册
20万+
工程师都在用,
免费
PCB检查工具
无需安装、支持浏览器和手机在线查看、实时共享
查看
点击登录
登录更多精彩功能!
首页
论坛版块
小组
免费开发板试用
ebook
直播
搜索
登录
×
20
完善资料,
赚取积分