单片机使用同一硬件定时器实现多周期定时功能
一个复杂的单片机程序可能需要很多种周期不同的定时器,用于执行不同的任务,如传感器数据采集、显示设备刷新或者执行设备的驱动等。如果每种周期使用一个单片机的硬件定时器将很难实现全部的功能需求,本文记录一种简单的使用一个硬件定时器实现不同周期定时功能的方法。
各周期定时回调函数
根据需求设计各不同周期定时函数,可选择几个常用周期,需要按周期运行的程序单独编写回调函数并在对应函数中调用。
其它周期或超过1s的定时器用户程序在这些基础上自行实现,参考下文LED闪烁例程。
void Systick1ms(void){
// TODO: 在此处添加用户代码
}
void Systick10ms(void){
// TODO: 在此处添加用户代码
}
void Systick50ms(void){
// TODO: 在此处添加用户代码
}
void Systick100ms(void){
// TODO: 在此处添加用户代码
SystickCallbackLED();
}
void Systick200ms(void){
// TODO: 在此处添加用户代码
}
void Systick500ms(void){
// TODO: 在此处添加用户代码
}
void Systick1s(void){
// TODO: 在此处添加用户代码
}
硬件定时器配置
硬件定时器初始化,周期配置为1ms。
void SystickInit(void){
TIM_InitTypeDef timer;
timer.TIM_Mode = TIM_16BitAutoReload;
timer.TIM_ClkSource = TIM_CLOCK_1T;
timer.TIM_ClkOut = DISABLE;
timer.TIM_Value = (uint16)(65536UL - (MAIN_Fosc / 1000UL));
timer.TIM_Run = ENABLE;
Timer_Inilize(Timer0,&timer);
NVIC_Timer0_Init(ENABLE,Priority_3);
}
基础回调函数及调用
在基础回调函数中设置循环计数,按定时设定调用不同的周期定时函数。
void TimerCallbackSystick(void){
static uint16 i = 0;
if(++i > 1000){
i = 0;
Systick1ms();
Systick500ms();
Systick1s();
}
if(i % 10 == 0)
Systick10ms();
if(i % 50 == 0)
Systick10ms();
if(i % 100 == 0)
Systick10ms();
if(i % 200 == 0)
Systick10ms();
if(i == 500)
Systick500ms();
}
在硬件定时器中断服务程序中调用基础回调函数:
#include "STC8G_H_Timer.h"
#include "../systick.h"
//========================================================================
// 函数: Timer0_ISR_Handler
// 描述: Timer0中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2020-09-23
//========================================================================
void Timer0_ISR_Handler (void) interrupt TMR0_VECTOR //进中断时已经清除标志
{
TimerCallbackSystick();
}
例程及下载
以LED闪烁为例,要求LED闪烁时点亮200ms然后熄灭800ms/1800ms/4800ms,可以编写在100ms定时函数中调用的回调函数:
#include "led.h"
uint8 LEDMode;
uint8 LEDFlashCycle;
void LEDSetMode(uint8 mode){
LEDMode = mode;
switch(mode){
case(LED_MODE_OFF):
LED = FALSE;
break;
case(LED_MODE_ON):
LED = TRUE;
break;
case(LED_MODE_FLASH_1S):
LEDFlashCycle = 10;
break;
case(LED_MODE_FLASH_2S):
LEDFlashCycle = 20;
break;
case(LED_MODE_FLASH_5S):
LEDFlashCycle = 50;
break;
default:
break;
}
}
//在100ms定时函数中调用
void SystickCallbackLED(void){
static uint8 i = 0;
if(LEDMode & 0x02){
if(++i > 2)
LED = FALSE;
if(i > LEDFlashCycle){
i = 0;
LED = TRUE;
}
}
}
- 本文采用的单片机为STC8H系列,感兴趣的朋友可以参考测试,或去Gitee上下载例程。
- 下载地址:https://gitee.com/loganxiang/LgxDemo ,参考Systick.h/Systick.c。