赞
踩
本章参考资料:
系统定时器 SysTic:
SysTick—系统定时器有4 个寄存器,简要介绍如下:
SysTick 属于单片机内部的外设,不需要额外的硬件电路,剩下的只需一个LED 灯即可。
SysTick 属于内核的外设
用固件库编程的时候我们只需要调用库函数SysTick_Config() 即可
这样系统定时器就配置好了,一个库函数搞定
SysTick_Config() 库函数主要配置了SysTick 中的三个寄存器
1 __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) 2 { 3 // 不可能的重装载值,超出范围 4 if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { 5 return (1UL); 6 } 7 8 // 设置重装载寄存器 9 SysTick->LOAD = (uint32_t)(ticks - 1UL); 10 11 // 设置中断优先级 12 NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); 13 14 // 设置当前数值寄存器 15 SysTick->VAL = 0UL; 16 17 // 设置系统定时器的时钟源为AHBCLK=72M 18 // 使能系统定时器中断 19 // 使能定时器 20 SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | 21 SysTick_CTRL_TICKINT_Msk | 22 SysTick_CTRL_ENABLE_Msk; 23 return (0UL); 24 }
在SysTick_Config() 库函数还调用了固件库函数NVIC_SetPriority()
函数流程
__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
if ((int32_t)IRQn < 0) {
SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] =
(uint8_t)((priority << (8 - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
} else {
NVIC->IP[((uint32_t)(int32_t)IRQn)] =
(uint8_t)((priority << (8 - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
}
}
// 设置系统定时器中断优先级
NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL);
1 /** 2 * @brief 启动系统滴答定时器SysTick 3 * @param 无 4 * @retval 无 5 */ 6 void SysTick_Init(void) 7 { 8 /* SystemFrequency / 1000 1ms 中断一次 9 * SystemFrequency / 100000 10us 中断一次 10 * SystemFrequency / 1000000 1us 中断一次 11 */ 12 if (SysTick_Config(SystemCoreClock / 100000)) { 13 /* Capture error */ 14 while (1); 15 } 16 }
SysTick_Config(SystemCoreClock / 100000)
SysTick 定时时间的计算
当设置好中断时间TINT 后,可以设置一个变量t,用来记录进入中断的次数,变量t 乘以中断的时间TINT 可以计算出需要定时的时间
SysTick 定时函数
/**
* @brief us 延时程序,10us 为一个单位
* @param
* @arg nTime: Delay_us( 1 ) 则实现的延时为1 * 10us = 10us
* @retval 无
*/
void Delay_us(__IO u32 nTime)
{
TimingDelay = nTime;
while (TimingDelay != 0);
}
void SysTick_Handler(void)
{
TimingDelay_Decrement();
}
中断复位函数调用了另外一个函数TimingDelay_Decrement(),原型如下:
/**
* @brief 获取节拍程序
* @param 无
* @retval 无
* @attention 在SysTick 中断函数SysTick_Handler() 调用
*/
void TimingDelay_Decrement(void)
{
if (TimingDelay != 0x00) {
TimingDelay--;
}
}
主函数:
int main(void) { /* LED 端口初始化*/ LED_GPIO_Config(); /* 配置SysTick 为10us 中断一次, 时间到后触发定时中断, * 进入stm32fxx_it.c 文件的SysTick_Handler 处理,通过数中断次数计时 */ SysTick_Init(); while (1) { LED_ON; Delay_us(100000); // 10000 * 10us = 1000ms LED2_ON; Delay_us(100000); // 10000 * 10us = 1000ms LED3_ON; Delay_us(100000); // 10000 * 10us = 1000ms } }
微秒级延时:
1 void SysTick_Delay_Us( __IO uint32_t us)
2 {
3 uint32_t i;
4 SysTick_Config(SystemCoreClock/1000000);
5
6 for (i=0; i<us; i++) {
7 // 当计数器的值减小到0 的时候,CRTL 寄存器的位16 会置1
8 while ( !((SysTick->CTRL)&(1<<16)) );
9 }
10 // 关闭SysTick 定时器
11 SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk;
12 }
毫秒级延时:
1 void SysTick_Delay_Ms( __IO uint32_t ms)
2 {
3 uint32_t i;
4 SysTick_Config(SystemCoreClock/1000);
5
6 for (i=0; i<ms; i++) {
7 // 当计数器的值减小到0 的时候,CRTL 寄存器的位16 会置1
8 // 当置1 时,读取该位会清0
9 while ( !((SysTick->CTRL)&(1<<16)) );
10 }
11 // 关闭SysTick 定时器
12 SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk;
13 }
在这两个微秒和毫秒级别的延时函数中,我们还是调用了SysTick_Config 这个固件库函数
1 // 这个固件库函数在core_cm3.h 中 2 static __INLINE uint32_t SysTick_Config(uint32_t ticks) 3 { 4 // reload 寄存器为24bit,最大值为2^24 5 if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); 6 7 // 配置reload 寄存器的初始值 8 SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; 9 10 // 配置中断优先级为1<<4 -1 = 15,优先级为最低 11 NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); 12 13 // 配置counter 计数器的值 14 SysTick->VAL = 0; 15 16 // 配置systick 的时钟为72M 17 // 使能中断 18 // 使能systick 19 SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | 20 SysTick_CTRL_TICKINT_Msk | 21 SysTick_CTRL_ENABLE_Msk; 22 return (0); 23 }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。