STM32学习笔记——系统滴答定时出现的问题及解决方法
问题描述
首先来看一段野火单片机学习代码:
/***************************************************************************************
* 函 数: 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;
}
这是一段ms级延时,当我仿照火哥代码烧录进stm32中,想要实现led的亮灭时,出现以下问题:
-
当主程序代码为:led=0; SysTick_Delay_Ms(1000); led=1; SysTick_Delay_Ms(1000);时;发现led不会闪烁,而是一直处于亮的状态。
-
当主程序代码改为SysTick_Delay_Ms(1000);led=0;SysTick_Delay_Ms(1000); led=1; 时;发现led同样不闪烁,而是一直处于熄灭状态。
问题原因及解决方法
再来看一段core_m3.h 中的代码:
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set reload register */
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Cortex-M0 System Interrupts */
SysTick->VAL = 0; /* Load the SysTick Counter Value */
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
return (0); /* Function successful */
}
不难发现,当调用SysTick_Config()这一函数时,会帮你打开滴答定时中断。
- 这时就会出现问题,当用户未定义相应的中断时,系统会自己调用startup_stm32f10x_hd.s中系统自定义的中断,而中断里是while(1)。
- 当代码执行到延时函数时,似乎是定格在延时函数这里。
那如何解决呢?
- 关闭中断,即不调用SysTick_Config()这一函数;用户通过寄存器直接操作,代码如下(替换SysTick_Config(SystemCoreClock/1000)部分):
SysTick->LOAD = ((SystemCoreClock/1000) & SysTick_LOAD_RELOAD_Msk) - 1;
SysTick->VAL = 0;
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_ENABLE_Msk;
- 用户自己写一个空的中断函数
void SysTick_Handler(void)
{
//skip
}
-
注意点:如果用户在跟着火哥学习时,在工程下也添加了stm32f10x_it.c文件则不会出现本文中的问题,这就相当于第二种解决方法。
-
初学者在学习系统滴答定时器时,采用查询方式更易理解,而且此查询方式延时最多达到16777 ms