在stm32中,系统滴答定时器可以实现精确的延时,但有时需要使用基本定时器实现精确延时,保证接下来采取的方法是全网最简单的方法。
使用的平台是野火mini开发板
第一步 配置tim6
#define BASIC_TIM6 TIM6
#define BASIC_TIM6_CLOCK_CMD RCC_APB1PeriphClockCmd
#define BASIC_TIM6_CLK RCC_APB1Periph_TIM6
#define BASIC_TIM6_IRQ TIM6_IRQn
#define BASIC_TIM6_IRQHandler TIM6_IRQHandler
这是定时器6的头文件的宏定义,为了在以后做移植更加方便
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitstructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE);
TIM_TimeBaseInitstructure.TIM_Period=1000;
TIM_TimeBaseInitstructure.TIM_Prescaler=71;
TIM_TimeBaseInit(BASIC_TIM6,&TIM_TimeBaseInitstructure);
TIM_ClearFlag(BASIC_TIM6,TIM_FLAG_Update);
/*设置时钟中断源为 计数更新中断*/
TIM_ITConfig(BASIC_TIM6,TIM_IT_Update,ENABLE);
//TIM_Cmd(BASIC_TIM6,ENABLE);
//注意这里我并没有使能定时器,这一部非常关键
关于TIM_Period,TIM_Prescaler这两个参数 的选择问题,参考野火电子的资料,写的非常详细,使用71,和1000,在接下来进入一次中断的时间就是1ms。
配置nvic
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = BASIC_TIM6_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
第二步 中断函数的书写
在配置中断函数之间 ,在主文件里面设置一个***全局变量***,
中断函数就是按照下面的方式写 其中的变量 time就是我们前面设置的全局变量。
void BASIC_TIM6_IRQHandler()
{
if(TIM_GetITStatus(BASIC_TIM6,TIM_IT_Update)!=RESET)
{
time--;
TIM_ClearITPendingBit(BASIC_TIM6,TIM_IT_Update);
}
}
编写延时函数
void base_time_delay_ms(u16 t)
{
time=t;
TIM_Cmd(BASIC_TIM6,ENABLE);
while(time!=0);
if(time==0)
{
time=t;
TIM_Cmd(BASIC_TIM6,DISABLE);
}
}
延时函数如上,进入函数将形参赋值给全局变量,然后打开定时器,等待变量在中断函数中一直减小到0,然后重新赋值,关闭定时器。
总结
base_time_delay_ms(50);
GPIO_SetBits(LED1_GPIO_PORT,LED1_GPIO_PIN);
base_time_delay_ms(50);
GPIO_ResetBits(LED1_GPIO_PORT,LED1_GPIO_PIN);
base_time_delay_ms(50);
在主函数里面调用延时函数,填入的参数就是延时的毫秒数。
即可实现基于定时器的精确延时。