通过上次学习我们实现了利用SysTick延时一段时间的Delay函数,并利用该函数实现了LED间隔1秒闪烁功能,实现Delay函数时其实是程序在不间断的查询计数标志位COUNTFLAG,这样处理器就无法干别的工作, 例如让2颗LED以不同的频率闪烁,利用Delay函数就无法实现。
针对这个问题我们可以利用SysTick异常中断请求来实现,在SysTick 异常中断服务函数中对进入中断的次数进行累加,由于进入中断的时间是可以精确控制的(例如每间隔1毫秒进入一次SysTic异常中断),这样通过中断次数我们得到了精确的时间控制。具体实现方法如下:
配置SysTick相关参数:
SysTick_Config(SystemCoreClock/1000); //配置为1ms定时,开启SysTick中断,时钟源为AHB,计数使能
定义system_tick 来记录进入中断的次数或时间,定义tick_start来记录每次切换LED状态的时刻,首先让我们来实现1颗LED 以1秒的间隔闪烁。
static uint32_t system_tick;
static uint32_t tick_start;
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //配置时钟RCC
GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO初始化结构体
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //定义GPIO模式为推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1; //定义引脚
GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz; //定义速度
GPIO_Init(GPIOA,&GPIO_InitStructure); //GPIOA初始化
SysTick_Config(SystemCoreClock/1000); //配置SysTick相关参数
while(1)
{
if(system_tick-tick_start>1000) //判断自上次LED切换状态后时间是否超过1秒
{
tick_start=system_tick; //每次超过1秒后更新tick_start的值
GPIO_WriteBit(GPIOA,GPIO_Pin_1,!(GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_1)));
//翻转输出电平
}
}
}
//SysTick中断服务函数,需要先在stm32f10x_it.c文件中将void SysTick_Handler(void)函数注释掉避免重复定义
void SysTick_Handler(void)
{
system_tick++; //每间隔1毫秒system_tick加1
}
要让第2颗LED以1.5秒间隔闪烁的话,只需再次定义一个变量记录第二个LED切换状态的时刻即可
程序如下:
static uint32_t system_tick;
static uint32_t tick_start; //LED1状态切换间隔时间计时
static uint32_t tick_start2; //LED2状态切换间隔时间计时
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //配置时钟RCC
GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO初始化结构体
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //定义GPIO模式为推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1; //定义引脚
GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz; //定义速度
GPIO_Init(GPIOA,&GPIO_InitStructure); //GPIOA初始化
SysTick_Config(SystemCoreClock/1000); //配置SysTick相关参数
while(1)
{
if(system_tick-tick_start>1000) //判断自上次LED切换状态后时间是否超过1秒
{
tick_start=system_tick; //每次超过1秒后更新tick_start的值
GPIO_WriteBit(GPIOA,GPIO_Pin_1,!(GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_1)));
//翻转输出电平
}
if(system_tick-tick_start2>1500) //LED2以间隔1.5秒的时间闪烁
{
tick_start2=system_tick;
GPIO_WriteBit(GPIOA,GPIO_Pin_0,!(GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_0)));
}
}
}
//SysTick中断服务函数,需要先在stm32f10x_it.c文件中将void SysTick_Handler(void)函数注释掉避免重复定义
void SysTick_Handler(void)
{
system_tick++; //每间隔1毫秒system_tick加1
}