STM32定时器比较多,使用起来也比较混乱。
windows下做过编程的人一定对SetTimer有印象,不过该定时器也不那么好用,因为id要自己维护,并且保证不跟程序中的其他id冲突。
手头上的项目要用到定时器,又不想每次都跑到寄存器里详细设定参数,所以就写了个类似SetTimer的定时器。
注:请在STM32F407上使用该定时器,其他内核需要修改,如M3内核是没有32位定时器的
使用方法:
u8 SetTimer(u32 unTime, u32 unCount, TIMERFUN pHandler,u32 ucPara)
使用SetTimer去向系统申请一个定时器,如果成功,返回定时器ID,失败返回0.为了使定时器ID更有意义,这里设定返回值为定时器编号
这里根据计时时间自动分配定时器。比如你需要一个比较长时间的定时,那么SetTimer会给你分配一个32位定时器(M4内核)
参数:
unTime:计时时间(ms,如需ns请自行修改或者使用delay)
unCount :计时器运行次数,0为无限运行,非零的话,运行unCount次后,该定时器关闭。
pHandler:定时器定时后执行的函数,该处如果不需要执行,可填0(什么都不需要做,干嘛要开启定时器?),当然这里可以自己定义函数指针类型(比如传2个参数或者变参:呃,变参太变态)
ucPara:函数参数
/*关闭定时器
tmrId:定时器ID
*/
void KillTimer(TIMER tmrId);
例如:
[mw_shl_code=c,true] //每隔0.5s反转4bit灯
tmrIrb = SetTimer(500, 0, IndRvsBit, 4);
printf("IndRvsBit Timer Id: %d
",tmrIrb);
if(0 != tmrIrb)
{
ucCnt = SetTimer(10 * 1000, 1, KillBlink, tmrIrb); //10s后关闭位4反转
printf("KillBlink Timer Id: %d
",ucCnt);
}[/mw_shl_code]
[mw_shl_code=c,true][/mw_shl_code]
[mw_shl_code=c,true][/mw_shl_code]
[mw_shl_code=c,true][/mw_shl_code]
[mw_shl_code=c,true][/mw_shl_code]
[mw_shl_code=c,true][/mw_shl_code]
[mw_shl_code=c,true][/mw_shl_code]
这里要提前定义好参数里的函数指针
[mw_shl_code=c,true]void KillBlink(u8 ucOpt)
{
// RTC_ShutWakeUp();
KillTimer(ucOpt);
printf("KillBlink(%d)
", ucOpt);
}
void AdPickTime(u8 ucOpt)
{
PushCmd(0xF2,0);
}
void IndRvsBit(u8 ucOpt)
{
SubBoardIndSingle(4, acCurInd[4] ^ (1 << ucOpt));
}[/mw_shl_code]
header:
[mw_shl_code=c,true]#ifndef __TIMER_H
#define __TIMER_H
#include "board.h"
#include "zkekglobe.h"
//////////////////////////////////////////////////////////////////////////////////
//All rights reserved
//////////////////////////////////////////////////////////////////////////////////
/*使能基本计时器
ucTimerIdx:计时器编号 范围:2~5 9~14
unCount 自动重装值。
uwPsc 计数器分频 2-65535 计时时间 = unCount * uwPsc / 84M(168M if ucTimerIdx in{9, 10, 11})
pHandler 计数完成后执行函数
ucPara 执行函数的参数
返回值:
0:成功
1:ucOpt unRunningFreqency unCount参数错误
2:定时器编号参数错误
3:定时器已经被占用
4:16位定时器传入的计数参数超阈值*/
u8 TimerEnable(u8 ucTimerIdx, u32 unCount, u16 uwPsc,TIMERFUN pHandler,u8 ucPara);
/*
获取空闲计时器
unTime:要计时的时间
返回值:timerId or 0:failed
*/
u8 GetAFreeTimer(u32 unTime);
/*设置定时器,最大计时2147483647ms(24.8天),最小1ms,其中unTime值不能超过该值
unTime: 计时时间,单位ms
unCount: 0:连续计时;其它:计时次数,到达次数后计时器停止工作
pHandler 计数完成后执行函数
ucPara 执行函数的参数
返回值: TimerID or 0:失败
*/
u8 SetTimer(u32 unTime, u32 unCount, TIMERFUN pHandler,u32 ucPara);
/*关闭定时器
tmrId:定时器ID
*/
void KillTimer(TIMER tmrId);
/*停止基本计时器 使能位置0,停止其时钟
ucTimerIdx:计时器编号 范围:2~5
ucOpt 可选参数 保留不用
*/
void TimerStop(u8 ucTimerIdx,u8 ucOpt);
#endif
[/mw_shl_code]
c:
[mw_shl_code=c,true]#include "timer.h"
//////////////////////////////////////////////////////////////////////////////////
////All rights reserved
//////////////////////////////////////////////////////////////////////////////////
TIMERFUN Timer2Fun = 0;
TIMERFUN Timer3Fun = 0;
TIMERFUN Timer4Fun = 0;
TIMERFUN Timer5Fun = 0;
TIMERFUN Timer9Fun = 0;
TIMERFUN Timer10Fun = 0;
TIMERFUN Timer11Fun = 0;
TIMERFUN Timer12Fun = 0;
TIMERFUN Timer13Fun = 0;
TIMERFUN Timer14Fun = 0;
u8 ucTimer2Para = 0;
u8 ucTimer3Para = 0;
u8 ucTimer4Para = 0;
u8 ucTimer5Para = 0;
u8 ucTimer9Para = 0;
u8 ucTimer10Para = 0;
u8 ucTimer11Para = 0;
u8 ucTimer12Para = 0;
u8 ucTimer13Para = 0;
u8 ucTimer14Para = 0;
u8 ucTmr2Efct = 0;
u8 ucTmr3Efct = 0;
u8 ucTmr4Efct = 0;
u8 ucTmr5Efct = 0;
u8 ucTmr9Efct = 0;
u8 ucTmr10Efct = 0;
u8 ucTmr11Efct = 0;
u8 ucTmr12Efct = 0;
u8 ucTmr13Efct = 0;
u8 ucTmr14Efct = 0;
u8 acTimerId[10] = { 0 };
u8 acTmrOrder[10] = {9, 10, 11, 3, 4, 12, 13, 14, 2, 5}; //定时器按定时时间长短查找顺序
u32 anTimingCnt[10] = { 0 };
u8 GetAFreeTimer(u32 unTime)
{
u8 ucTmrSearchWith = 0;
u8 ucTimerIndex = 0;
//find an idle timer
if(unTime < 16384)//小于16.383s
{
ucTmrSearchWith = 1;
}
else if(unTime > 16383 && unTime < 32768)
{
ucTmrSearchWith = 3;
}
else if(unTime > 32767 && unTime < 2147483647)
{
ucTmrSearchWith = 8;
}
for(; ucTmrSearchWith < 10; ucTmrSearchWith++)
{
if(0 == acTimerId[ucTmrSearchWith])
{
ucTimerIndex = acTmrOrder[ucTmrSearchWith];
}
}
return ucTimerIndex;
}
/*设置定时器,最大计时2147483647ms(24.8天),最小1ms,其中unTime值不能超过该值
unTime: 计时时间,单位ms
unCount: 0:连续计时;其它:计时次数,到达次数后计时器停止工作
pHandler 计数完成后执行函数
ucPara 执行函数的参数
返回值:TimerID or 0:失败
*/
u8 SetTimer(u32 unTime, u32 unCount, TIMERFUN pHandler,u32 ucPara)
{
u8 ucTimerIndex = 0;
u8 ucRslt = 0;
u8 ucTmrSearchWith = 0;
u32 unTimeUse = 0;
//find an idle timer
if(unTime < 16384)//小于16.383s
{
ucTmrSearchWith = 0;
}
else if(unTime > 16383 && unTime < 32768)
{
ucTmrSearchWith = 3;
}
else if(unTime > 32767 && unTime < 2147483647)
{
ucTmrSearchWith = 8;
}
else
{
return 0;
}
for(; ucTmrSearchWith < 10; ucTmrSearchWith++)
{
if(0 == acTimerId[ucTmrSearchWith])
{
ucTimerIndex = acTmrOrder[ucTmrSearchWith];
acTimerId[ucTmrSearchWith] = ucTimerIndex;
ucRslt = ucTimerIndex;
anTimingCnt[ucTmrSearchWith] = unCount;
unTimeUse = unTime;
if(ucTmrSearchWith < 3)
{
unTimeUse *= 2;
}
if( 0 != TimerEnable(ucTimerIndex, unTimeUse * 2, 42000, pHandler, ucPara))
{
acTimerId[ucTmrSearchWith] = 0;
ucRslt = 0;
continue;
}
break;
}
}
return ucRslt;
}
/*关闭定时器
tmrId:定时器ID
*/
void KillTimer(TIMER tmrId)
{
TimerStop(tmrId,0);
switch(tmrId)
{
case 2:
acTimerId[8] = 0;
break;
case 3:
acTimerId[3] = 0;
break;
case 4:
acTimerId[4] = 0;
break;
case 5:
acTimerId[9] = 0;
break;
case 9:
acTimerId[0] = 0;
break;
case 10:
acTimerId[1] = 0;
break;
case 11:
acTimerId[2] = 0;
break;
case 12:
acTimerId[5] = 0;
break;
case 13:
acTimerId[6] = 0;
break;
case 14:
acTimerId[7] = 0;
break;
default:
break;
}
}
//定时器2中断服务程序
void TIM2_IRQHandler(void)
{
if(TIM2->SR&0X0001)//溢出中断
{
if(ucTmr2Efct)
{
if(Timer2Fun)
{
(*Timer2Fun)(ucTimer2Para);
}
if(anTimingCnt[8] > 1) //判断计时次数
{
anTimingCnt[8]--;
}
else if(1 == anTimingCnt[8]) //计时次数完成
{
KillTimer(2);
}
}
else
{
ucTmr2Efct = 1;
}
}
TIM2->SR&=~(1<<0);//清除中断标志位
}
//定时器3中断服务程序
void TIM3_IRQHandler(void)
{
if(TIM3->SR&0X0001)//溢出中断
{
if(1 == ucTmr3Efct)
{
if(Timer3Fun)
{
(*Timer3Fun)(ucTimer3Para);
}
if(anTimingCnt[3] > 1) //判断计时次数
{
anTimingCnt[3] --;
}
else if(1 == anTimingCnt[3]) //计时次数完成
{
KillTimer(3);
}
}
else
{
ucTmr3Efct = 1;
}
}
TIM3->SR&=~(1<<0);//清除中断标志位
}
//定时器4中断服务程序
void TIM4_IRQHandler(void)
{
if(TIM4->SR&0X0001)//溢出中断
{
if(1 == ucTmr4Efct)
{
if(Timer4Fun)
{
(*Timer4Fun)(ucTimer4Para);
}
if(anTimingCnt[4] > 1) //判断计时次数
{
anTimingCnt[4] --;
}
else if(1 == anTimingCnt[4]) //计时次数完成
{
KillTimer(4);
}
}
else
{
ucTmr4Efct = 1;
}
}
TIM4->SR&=~(1<<0);//清除中断标志位
}
//定时器5中断服务程序
void TIM5_IRQHandler(void)
{
if(TIM5->SR&0X0001)//溢出中断
{
if(1 == ucTmr5Efct)
{
if(Timer5Fun)
{
(*Timer5Fun)(ucTimer5Para);
}
if(anTimingCnt[9] > 1) //判断计时次数
{
anTimingCnt[9] --;
}
else if(1 == anTimingCnt[9]) //计时次数完成
{
KillTimer(5);
}
}
else
{
ucTmr5Efct = 1;
}
}
TIM5->SR&=~(1<<0);//清除中断标志位
}
//定时器9中断服务程序
void TIM1_BRK_TIM9_IRQHandler(void)
{
if(TIM9->SR&0X0001)//溢出中断
{
if(1 == ucTmr9Efct)
{
if(Timer9Fun)
{
(*Timer9Fun)(ucTimer9Para);
}
if(anTimingCnt[0] > 1) //判断计时次数
{
anTimingCnt[0]--;
}
else if(1 == anTimingCnt[0]) //计时次数完成
{
KillTimer(9);
}
}
else
{
ucTmr9Efct = 1;
}
TIM9->SR&=~(1<<0);//清除中断标志位
}
}
//定时器10中断服务程序
void TIM1_UP_TIM10_IRQHandler(void)
{
if(TIM10->SR&0X0001)//溢出中断
{
if(1 == ucTmr10Efct)
{
if(Timer10Fun)
{
(*Timer10Fun)(ucTimer10Para);
}
if(anTimingCnt[1] > 1) //判断计时次数
{
anTimingCnt[1] --;
}
else if(1 == anTimingCnt[1]) //计时次数完成
{
KillTimer(10);
}
}
else
{
ucTmr10Efct = 1;
}
TIM10->SR&=~(1<<0);//清除中断标志位
}
}
//定时器11中断服务程序
void TIM1_TRG_COM_TIM11_IRQHandler(void)
{
if(TIM11->SR&0X0001)//溢出中断
{
if(1 == ucTmr11Efct)
{
if(Timer11Fun)
{
(*Timer11Fun)(ucTimer11Para);
}
if(anTimingCnt[2] > 1) //判断计时次数
{
anTimingCnt[2] --;
}
else if(1 == anTimingCnt[2]) //计时次数完成
{
KillTimer(11);
}
}
else
{
ucTmr11Efct = 1;
}
TIM11->SR&=~(1<<0);//清除中断标志位
}
}
//定时器12中断服务程序
void TIM8_BRK_TIM12_IRQHandler(void)
{
if(TIM12->SR&0X0001)//溢出中断
{
if(1 == ucTmr12Efct)
{
if(Timer12Fun)
{
(*Timer12Fun)(ucTimer12Para);
}
if(anTimingCnt[5] > 1) //判断计时次数
{
anTimingCnt[5] --;
}
else if(1 == anTimingCnt[5]) //计时次数完成
{
KillTimer(12);
}
}
else
{
ucTmr12Efct = 1;
}
TIM12->SR&=~(1<<0);//清除中断标志位
}
}
//定时器13中断服务程序
void TIM8_UP_TIM13_IRQHandler(void)
{
if(TIM13->SR&0X0001)//溢出中断
{
if(1 == ucTmr13Efct)
{
if(Timer13Fun)
{
(*Timer13Fun)(ucTimer13Para);
}
if(anTimingCnt[6] > 1) //判断计时次数
{
anTimingCnt[6] --;
}
else if(1 == anTimingCnt[6]) //计时次数完成
{
KillTimer(13);
}
}
else
{
ucTmr13Efct = 1;
}
TIM13->SR&=~(1<<0);//清除中断标志位
}
}
//定时器14中断服务程序
void TIM8_TRG_COM_TIM14_IRQHandler(void)
{
if(TIM14->SR&0X0001)//溢出中断
{
if(1 == ucTmr14Efct)
{
if(Timer14Fun)
{
(*Timer14Fun)(ucTimer14Para);
}
if(anTimingCnt[7] > 1) //判断计时次数
{
anTimingCnt[7] --;
}
else if(1 == anTimingCnt[7]) //计时次数完成
{
KillTimer(14);
}
}
else
{
ucTmr14Efct = 1;
}
TIM14->SR&=~(1<<0);//清除中断标志位
}
}
/*使能基本计时器
ucTimerIdx:计时器编号 范围:2~5 9~14
unCount 自动重装值。
uwPsc 计数器分频 2-65535 计时时间 = unCount * uwPsc / 84M(168M if ucTimerIdx in{9, 10, 11})
pHandler 计数完成后执行函数
ucPara 执行函数的参数
返回值:
0:成功
1:ucOpt unRunningFreqency unCount参数错误
2:定时器编号参数错误
3:定时器已经被占用
4:16位定时器传入的计数参数超阈值*/
u8 TimerEnable(u8 ucTimerIdx, u32 unCount, u16 uwPsc,TIMERFUN pHandler,u8 ucPara)
{
//参数检查
if(unCount < 2 || uwPsc < 2 || uwPsc > 65535) //参数错误:重装值、分频数设置错误
{
return 1;
}
if(ucTimerIdx < 2 || ucTimerIdx > 14 || (ucTimerIdx > 5 && ucTimerIdx < 9) ) //参数错误:不是2-5 9-14定时器
{
return 2;
}
switch(ucTimerIdx)
{
case 2:
if(0x0001 & TIM2 ->CR1) //定时器正在被使用
{
return 3;
}
RCC ->APB1ENR |= 1;
TIM2 ->ARR = unCount - 1;
TIM2 ->
SC = uwPsc - 1;
TIM2 ->DIER |= 1;
Timer2Fun = pHandler;
ucTimer2Para = ucPara;
MY_NVIC_Init(2,0,TIM2_IRQn,2);
TIM2->SR = 0;//清除中断标志位
TIM2 ->CR1 |= 0x01;
break;
case 3:
if(unCount > 0x0000FFFF)
{
return 4;
}
if(0x0001 & TIM3 ->CR1) //定时器正在被使用
{
return 3;
}
RCC ->APB1ENR |= 1 << 1; //使能定时器时钟
TIM3 ->ARR = unCount - 1;
TIM3 ->
SC = uwPsc - 1;
TIM3 ->DIER |= 1;
Timer3Fun = pHandler;
ucTimer3Para = ucPara;
MY_NVIC_Init(0,3,TIM3_IRQn,2);
TIM3->SR = 0;//清除中断标志位
TIM3 ->CR1 |= 0x01;
break;
case 4:
if(unCount > 0x0000FFFF)
{
return 4;
}
if(0x0001 & TIM4 ->CR1) //定时器正在被使用
{
return 3;
}
RCC ->APB1ENR |= 1 << 2; //使能定时器时钟
TIM4 ->ARR = unCount - 1;
TIM4 ->
SC = uwPsc - 1;
TIM4 ->DIER |= 1;
Timer4Fun = pHandler;
ucTimer4Para = ucPara;
MY_NVIC_Init(1, 0 , TIM4_IRQn, 2);
TIM4->SR = 0;//清除中断标志位
TIM4 ->CR1 |= 0x01;
break;
case 5:
if(0x0001 & TIM5 ->CR1) //定时器正在被使用
{
return 3;
}
RCC ->APB1ENR |= 1 << 3; //使能定时器时钟
TIM5 ->ARR = unCount - 1;
TIM5 ->
SC = uwPsc - 1;
TIM5 ->DIER |= 1;
Timer5Fun = pHandler;
ucTimer5Para = ucPara;
MY_NVIC_Init(2,1,TIM5_IRQn,2);
TIM5->SR = 0;//清除中断标志位
TIM5 ->CR1 |= 0x01;
break;
case 9:
if(0x0001 & TIM9 ->CR1) //定时器正在被使用
{
return 3;
}
RCC ->APB2ENR |= 1 << 16; //使能定时器时钟
TIM9 ->ARR = unCount - 1;
TIM9 ->
SC = uwPsc - 1;
TIM9 ->DIER |= 1;
Timer9Fun = pHandler;
ucTimer9Para = ucPara;
MY_NVIC_Init(0, 0 ,TIM1_BRK_TIM9_IRQn,2);
TIM9->SR = 0;//清除中断标志位
TIM9 ->CR1 |= 0x01;
break;
case 10:
if(0x0001 & TIM10 ->CR1) //定时器正在被使用
{
return 3;
}
RCC ->APB2ENR |= 1 << 17; //使能定时器时钟
TIM10 ->ARR = unCount - 1;
TIM10 ->
SC = uwPsc - 1;
TIM10 ->DIER |= 1;
Timer10Fun = pHandler;
ucTimer10Para = ucPara;
MY_NVIC_Init(0, 1 ,TIM1_UP_TIM10_IRQn,2);
TIM10->SR = 0;//清除中断标志位
TIM10 ->CR1 |= 0x01;
break;
case 11:
if(0x0001 & TIM11 ->CR1) //定时器正在被使用
{
return 3;
}
RCC ->APB2ENR |= 1 << 18; //使能定时器时钟
TIM11 ->ARR = unCount - 1;
TIM11 ->
SC = uwPsc - 1;
TIM11 ->DIER |= 1;
Timer11Fun = pHandler;
ucTimer11Para = ucPara;
MY_NVIC_Init(0, 2 ,TIM1_TRG_COM_TIM11_IRQn,2);
TIM11->SR = 0;//清除中断标志位
TIM11 ->CR1 |= 0x01;
break;
case 12:
if(0x0001 & TIM12 ->CR1) //定时器正在被使用
{
return 3;
}
RCC ->APB1ENR |= 1 << 6; //使能定时器时钟
TIM12 ->ARR = unCount - 1;
TIM12 ->
SC = uwPsc - 1;
TIM12 ->DIER |= 1;
Timer12Fun = pHandler;
ucTimer12Para = ucPara;
MY_NVIC_Init(1, 1 ,TIM8_BRK_TIM12_IRQn,2);
TIM12->SR = 0;//清除中断标志位
TIM12 ->CR1 |= 0x01;
break;
case 13:
if(0x0001 & TIM13 ->CR1) //定时器正在被使用
{
return 3;
}
RCC ->APB1ENR |= 1 << 7; //使能定时器时钟
TIM13 ->ARR = unCount - 1;
TIM13 ->
SC = uwPsc - 1;
TIM13 ->DIER |= 1;
Timer13Fun = pHandler;
ucTimer13Para = ucPara;
MY_NVIC_Init(1, 2 ,TIM8_UP_TIM13_IRQn,2);
TIM13->SR = 0;//清除中断标志位
TIM13 ->CR1 |= 0x01;
break;
case 14:
if(0x0001 & TIM14 ->CR1) //定时器正在被使用
{
return 3;
}
RCC ->APB1ENR |= 1 << 8; //使能定时器时钟
TIM14 ->ARR = unCount - 1;
TIM14 ->
SC = uwPsc - 1;
TIM14 ->DIER |= 1;
Timer14Fun = pHandler;
ucTimer14Para = ucPara;
MY_NVIC_Init(1, 3 ,TIM8_TRG_COM_TIM14_IRQn,2);
TIM14->SR = 0;//清除中断标志位
TIM14 ->CR1 |= 0x01;
break;
default:
break;
}
return 0; //返回成功
}
/*停止基本计时器 使能位置0,停止其时钟
ucTimerIdx:计时器编号 范围:2~5
ucOpt 可选参数 保留不用
*/
void TimerStop(u8 ucTimerIdx,u8 ucOpt)
{
switch(ucTimerIdx)
{
case 2:
TIM2 ->CR1 &= ~(1 << 0); //关闭使能
Timer2Fun = 0;
ucTimer2Para = 0;
ucTmr2Efct = 0;
break;
case 3:
TIM3 ->CR1 &= ~(1 << 0); //关闭使能
Timer3Fun = 0;
ucTimer3Para = 0;
ucTmr3Efct = 0;
break;
case 4:
TIM4 ->CR1 &= ~(1 << 0); //关闭使能
Timer4Fun = 0;
ucTimer4Para = 0;
ucTmr4Efct = 0;
break;
case 5:
TIM5 ->CR1 &= ~(1 << 0); //关闭使能
Timer5Fun = 0;
ucTimer5Para = 0;
ucTmr5Efct = 0;
break;
case 9:
TIM9 ->CR1 &= ~(1 << 0); //关闭使能
Timer9Fun = 0;
ucTimer9Para = 0;
ucTmr9Efct = 0;
break;
case 10:
TIM10 ->CR1 &= ~(1 << 0); //关闭使能
Timer10Fun = 0;
ucTimer10Para = 0;
ucTmr10Efct = 0;
break;
case 11:
TIM11 ->CR1 &= ~(1 << 0); //关闭使能
Timer11Fun = 0;
ucTimer11Para = 0;
ucTmr11Efct = 0;
break;
case 12:
TIM12 ->CR1 &= ~(1 << 0); //关闭使能
Timer12Fun = 0;
ucTimer12Para = 0;
ucTmr12Efct = 0;
break;
case 13:
TIM13 ->CR1 &= ~(1 << 0); //关闭使能
Timer13Fun = 0;
ucTimer13Para = 0;
ucTmr13Efct = 0;
break;
case 14:
TIM14 ->CR1 &= ~(1 << 0); //关闭使能
Timer14Fun = 0;
ucTimer14Para = 0;
ucTmr14Efct = 0;
break;
default:
break;
}
}
[/mw_shl_code]
防止小白copy代码而不仔细阅读说明,我把函数类型定义写在这里,大牛请自行添加或修改.
另外,SetTimer那里挖了个坑,摔死一个算一个。
typedef void (*TIMERFUN)(u8);
一周热门 更多>