目录
前言
在之前直接操作I/O口的输出来控制LED实现流水灯的时候,让LED灯以一定的时间间隔来变化,比如0.5秒变化一个LED灯。但之前没有刻意地要求这个时间间隔很精确,所以采用了软件跑空循环来延时的方式,这样虽然很简单,但是精度会比较低。这次通过Systick定时器来实现精确定时,控制LED灯交替闪烁。
一、SysTick_Init()
SysTick定时器,又称系统滴答定时器,是24位自动重载定时器,与8051的带有自动重载定时方式有些类似,不过SysTick定时器是向下计数而且自带中断函数的。
初始化SysTick:
void SysTick_Init(void)
{
/* SystemFrequency / 1000 1ms中断一次
* SystemFrequency / 100000 10us中断一次
* SystemFrequency / 1000000 1us中断一次
*/
if (SysTick_Config(SystemCoreClock / 1000000))
{
/* Capture error */
while (1);
}
/* 关闭系统滴答定时器:初始化先不用开启,等需要延时时才开启定时器 */
SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
}
这段代码使用了 SysTick_Config
函数来配置 SysTick 定时器,使其每 1 微秒产生一次中断。SystemCoreClock
是系统时钟频率,SystemCoreClock / 1000000
意味着 SysTick 定时器每 72 个时钟周期计数一次,对于72MHz的频率,就是1us。
同时while(1)具有捕获异常的功能,如果SysTick函数返回非0值,说明函数内部陷入了死循环。
二、设置节拍程序
在定时器每产生一次中断时调用,让计数值递减。
void TimingDelay_Decrement(void)
{
if (TimingDelay != 0x00)
{
TimingDelay--;
}
}
这段程序是给SysTick 自带的中断函数 SysTick_Handler()调用的,而SysTick_Handler()函数在"stm32f10x_it.c"文件中,并且初始为空,我们需要往里面加入节拍程序。
三、加入延时函数
写一个微秒级延时的函数。
void Delay_us(__IO u32 nTime)
{
TimingDelay = nTime;
/* 使能滴答定时器 */
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
while(TimingDelay != 0);
/* 关闭系统滴答定时器 */
SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
}
毫秒级延时取1000倍。
#define Delay_ms(x) Delay_us(1000*x) //单位ms
主函数中调用毫秒延时:
int main(void)
{
/* 初始化LED灯 */
LED_Init();
/* 初始化系统滴答定时器 */
SysTick_Init();
/* 清零时间计数 */
timecount=0;
while (1)
{
/* 延时10ms */
Delay_ms(10);
/* 每10ms计数值增加1 */
timecount++;
/* 计数到50,延时时间为500ms */
if(timecount==50)
{
LED0_ON;
LED1_OFF;
}
/* 计数到100,延时时间为1s */
if(timecount==100)
{
LED0_OFF;
LED1_ON;
/* 清零时间计数 */
timecount=0;
}
}
}
最终通过SysTick定时器实现以0.5秒的间隔点灯。
SysTick定时器点灯