OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 9729|回复: 10

分享一个强大的定时器吧。使用灵活

[复制链接]

33

主题

984

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8017
金钱
8017
注册时间
2014-8-13
在线时间
1594 小时
发表于 2015-4-29 15:40:07 | 显示全部楼层 |阅读模式

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\r\n",tmrIrb); if(0 != tmrIrb) { ucCnt = SetTimer(10 * 1000, 1, KillBlink, tmrIrb); //10s后关闭位4反转 printf("KillBlink Timer Id: %d\r\n",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)\r\n", 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);

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2015-4-29 22:03:59 | 显示全部楼层
大牛喔,谢谢分享!!!
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165516
金钱
165516
注册时间
2010-12-1
在线时间
2116 小时
发表于 2015-4-29 22:30:12 | 显示全部楼层
不错啊,谢谢分享。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

0

主题

7

帖子

0

精华

新手上路

积分
32
金钱
32
注册时间
2013-9-6
在线时间
1 小时
发表于 2015-5-4 19:13:08 | 显示全部楼层
这个真心不错!谢谢分享!
回复 支持 反对

使用道具 举报

3

主题

16

帖子

0

精华

新手上路

积分
32
金钱
32
注册时间
2016-9-2
在线时间
8 小时
发表于 2016-9-3 18:56:06 | 显示全部楼层
牛人!!!!
回复 支持 反对

使用道具 举报

4

主题

211

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2600
金钱
2600
注册时间
2016-7-6
在线时间
546 小时
发表于 2017-4-26 12:13:27 | 显示全部楼层
谢谢分享。
回复 支持 反对

使用道具 举报

0

主题

3

帖子

0

精华

新手上路

积分
45
金钱
45
注册时间
2017-6-26
在线时间
10 小时
发表于 2017-6-28 16:42:14 | 显示全部楼层
为什么我在while 循环里调用这个函数会出现死机的现象
回复 支持 反对

使用道具 举报

33

主题

984

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8017
金钱
8017
注册时间
2014-8-13
在线时间
1594 小时
 楼主| 发表于 2017-6-28 17:56:35 | 显示全部楼层
FortuneDi 发表于 2017-6-28 16:42
为什么我在while 循环里调用这个函数会出现死机的现象

我记得我在设计这个的时候,没有一个地方是阻塞设计的,也就是不存在类似while(P)这样的设计,因为有可能P的条件受外部限制,而使的while循环一直无法通过,其他的可能阻塞的设计也都是避免了的。

刚刚我又重新检查了一遍整个设计,还是没有找到能都导致阻塞的循环、等待之类的代码。


然后我有想了一下,发现TIMERFUN这个由用户设计的回调函数是不受我控制的,而且也没有像OS那样设计时间片轮询,强行剥离TIMERFUN执行,这个地方如果用户编写的回调函数是阻塞的话,是有可能会出现死机的现象的。

会不会是你自己的回调函数TIMERFUN阻塞了?

在定时器调用、中断处理、关闭定时器以及回调函数这里多打几个断点,看一下哪些断点执行了,哪些不执行,观察一下究竟卡在哪里吧
回复 支持 反对

使用道具 举报

10

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
62
金钱
62
注册时间
2017-5-3
在线时间
44 小时
发表于 2017-7-9 14:37:43 | 显示全部楼层
好东西学习
回复 支持 反对

使用道具 举报

17

主题

354

帖子

0

精华

高级会员

Rank: 4

积分
797
金钱
797
注册时间
2017-5-21
在线时间
340 小时
发表于 2017-12-22 21:37:34 来自手机 | 显示全部楼层
虽然简化了设置,但是优先级是个坑
回复 支持 反对

使用道具 举报

33

主题

984

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8017
金钱
8017
注册时间
2014-8-13
在线时间
1594 小时
 楼主| 发表于 2017-12-23 09:12:07 | 显示全部楼层
l6931639 发表于 2017-12-22 21:37
虽然简化了设置,但是优先级是个坑

设计思路:短延时申请计时器得到16位定时器,长延时申请计时器得到32位定时器。

中断级别和分组没提到,是因为使用了系统默认的中断分配。

如果你有什么其他的设计思路,欢迎给出解决方案。

你说的优先级是个坑不知道具体是说哪方面。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-19 17:04

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表