摘要:基于STM32f10x系列库设计的定时器模块,利用systick实现定时功能。
例如main里StartTimer开启eTmrID_USART2对应的定时器,定时1000ms,在while循环不断CheckTimer检测eTmrID_USART2是否到达定时1000ms时间;如果定时到达,进入执行,如果在内部重新StartTimer,即可下次循环继续上述检测。
主函数调用
#define TRUE 1
int main(void)
{
SystemInit();
SystickInit(); /* 定时中断初始化 */
StartTimer(eTmrID_USART2, 1000); //串口模块 1000ms执行一次
while(1)
{
if( TRUE == CheckTimer( eTmrID_USART2)) //检查串口定时的时间到达与否
{
...
/*1s到了执行完程序之后如果需要继续定时,需要将对应的定时初始化*/
StartTimer(eTmrID_USART2, 1000); //串口模块 1000ms执行一次
}
}
}
头文件(Systick's Header File):drv_systick.h
#include <stdio.h>
#include <stdint.h>
#include "stm32f10x.h"
#ifndef __DRV_SYSTICK_H
#define __DRV_SYSTICK_H
/* 等待定时器超时期间,可以让CPU进入IDLE状态, 目前是空 */
#define CPU_IDLE()
/* 定时器结构体,成员变量必须是 volatile, 否则C编译器优化时可能有问题 */
typedef struct
{
volatile uint32_t count; /* 计数器 */
volatile uint8_t flag; /* 定时到达标志 */
}SOFT_TMR;
extern __IO uint32_t LocalTime; /* 10ms */
typedef enum
{
eTmrID_WorkLed = 1, /* dis文件 工作灯闪烁定时器 1*/
eTmrID_APP_LIFE, /* 系统生命信号定时器 2*/
eTmrID_Modbus, /* drv_modbus_master文件 modbus查询500ms等待 3*/
eTmrID_START, /* 启动信号计时 4*/
eTmrID_STOP, /* 关机计时 5*/
}eSysTick;
extern void DelayMS(uint32_t n);
extern void StartTimer(uint8_t _id, uint32_t _period);
extern uint8_t CheckTimer(uint8_t _id);
extern void delay_us(uint32_t nus);
extern void SystickInit(void);
void SysTick_ISR(void);
extern uint16_t testtime;
#endif
源文件(Systick's Source File)drv_systick.c
#include "drv_systick.h"
#include "drv_adc.h"
/* 在此定义若干个软件定时器全局变量
注意,必须增加volatile,因为这个变量在中断和主程序中同时
被访问,有可能造成编译器错误优化。DelayMS曾出过问题
*/
#define TMR_COUNT 30 /* 软件定时器的个数 ,各个寄存器在h文件里定义*/
SOFT_TMR g_Tmr[TMR_COUNT];
/*******************************************************************************
函数名:SoftTimerDec
输 入: 定时器变量指针,每隔1ms减1
输 出:
功能说明:
*/
static void SoftTimerDec ( SOFT_TMR *_tmr )
{
volatile uint8_t t = 1;
if ( _tmr->flag == 0 )
{
if ( _tmr->count > 0 )
{
if ( _tmr->count >= t ) _tmr->count -= t;
else _tmr->count = 0;
if ( _tmr->count == 0 )
{
_tmr->flag = 1;
}
}
}
}
/*******************************************************************************
函数名:SysTick_ISR
输 入:
输 出:
功能说明:SysTick中断服务程序,每隔1ms进入1次
*/
void SysTick_ISR ( void )
{
volatile uint8_t i;
static volatile u32 count;
count++;
for ( i = 0; i < TMR_COUNT; i++ )
{
SoftTimerDec ( &g_Tmr[i] );
}
testtime++;
}
/*******************************************************************************
函数名:DelayMS
输 入: 延迟长度,单位1 ms. 延迟精度为正负1ms
输 出:
功能说明:延时函数。占用软件定时器0
*/
void DelayMS ( uint32_t n )
{
/* 避免 n = 1 出现主程序死锁 */
if ( n == 1 )
{
n = 2;
}
g_Tmr[0].count = n;
g_Tmr[0].flag = 0;
/* while 循环体最好让CPU进入IDLE状态,已降低功耗 */
while ( 1 )
{
// CPU_IDLE();
if ( g_Tmr[0].flag == 1 )
{
break;
}
}
}
/*******************************************************************************
函数名:StartTimer
输 入: 定时器ID (0 - 3)
输 出:
功能说明:
*/
void StartTimer ( uint8_t _id, uint32_t _period )
{
if ( _id >= TMR_COUNT )
{
return;
}
g_Tmr[_id].count = _period;
g_Tmr[_id].flag = 0;
}
/*******************************************************************************
函数名:StartTimer
输 入: 定时器ID (0 - 3)
输 出: 返回 0 表示定时未到, 1表示定时到
功能说明:
*/
uint8_t CheckTimer ( uint8_t _id )
{
if ( _id >= TMR_COUNT )
{
return 0;
}
return g_Tmr[_id].flag;
}
/*******************************************************************************
函数名:delay_us
输 入: 定时时间
输 出: 无
功能说明:提供给IIC调用
*/
void delay_us ( uint32_t nus )
{
uint32_t i, j;
for ( i = 0; i < nus; i++ )
{
for ( j = 0; j < 200; j++ )
;
}
}
void SystickInit(void)
{
uint8_t i;
for(i=0;i<TMR_COUNT;i++)
{
g_Tmr[i].count = 0;
g_Tmr[i].flag = 0;
}
SysTick_Config(SystemCoreClock / 1000); //Systick倒计时一次耗时 1ms 然后中断
}
中断函数(Systick's Interrupt Function)void SysTick_Handler(void)
//Systick's Interrupt Function is located in 'stm32f10x_it.c'
void SysTick_Handler(void)
{
SysTick_ISR();
}