基于STM32F103
步骤:
1、定时器的1ms初始化
1 //1ms TIMER IRQ 2 void Drv_timeout_Init(void) 3 { 4 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 5 NVIC_InitTypeDef NVIC_InitStructure; 6 RCC_APB1PeriphClockCmd(mBT_timer_Rcc, ENABLE); //时钟使能 7 8 TIM_TimeBaseStructure.TIM_Period = mBT_timer_arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 9 TIM_TimeBaseStructure.TIM_Prescaler =mBT_timer_psc; //设置用来作为TIMx时钟频率除数的预分频值 10 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim 11 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式 12 TIM_TimeBaseInit(mBT_timer_TIM, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位 13 14 TIM_ITConfig(mBT_timer_TIM,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断 15 16 //中断优先级NVIC设置 17 NVIC_InitStructure.NVIC_IRQChannel = mBT_timer_IRQ; //TIM3中断 18 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级 19 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级 20 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能 21 NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器 22 TIM_Cmd(mBT_timer_TIM, ENABLE); //使能TIMx 23 } 24 25 //定时器中断服务程序 26 void TIM5_IRQHandler() 27 { 28 if (TIM_GetITStatus(mBT_timer_TIM, TIM_IT_Update) != RESET) //检查TIM更新中断发生与否 29 { 30 Drv_Tmr_1MsTOut_Manage(); 31 TIM_ClearITPendingBit(mBT_timer_TIM, TIM_IT_Update ); //清除TIMx更新中断标志 32 } 33 }
2、结构体初始化
1 typedef void (*T_TmrOutCallBack)(void); 2 3 typedef enum emTmrOutEvt{ 4 E_TmrOutEvt_BtWkUpCheck, // 超时事件类型,蓝牙唤醒超时 5 E_TmrOutEvt_BtCmdRsp, // 超时事件类型,蓝牙命令应答交互超时 6 E_TmrOutEvt_MaxLmt, // 超时事件类型,最大阈值设定 7 }E_TmrOutEvt; 8 9 //E_TmrOutEvt_BtCmdRsp类超时 10 typedef struct stBt836B_CmdRspTOutRes{ 11 BOOL bIsProcDone; // 超时主体是否处理完毕标志位 12 BOOL bIsTOut; // 超时标志位 13 }T_Bt836B_CmdRspTOutRes; 14 15 typedef struct stTmrOutRes{ 16 BOOL bTimeOutFlag; 17 BOOL bUpdateFlag; // 更新标志位 18 UINT16 usUpdateTimeValue; // 待更新的超时数值 19 UINT16 usCurTimeCounter; // 当前定时器计数器 20 T_TmrOutCallBack ptTmrOutProcCallBack; // 超时后回调处理接口 21 BOOL *pbIsNrmlExit; // 主体正常退出超时处理标记位指针 22 }T_TmrOutRes;
3、注册函数及超时类型资源
1 //local 2 T_TmrOutRes atTmrOutRes[E_TmrOutEvt_MaxLmt]; 3 4 #if CVIEW("E_TmrOutEvt_BtCmdRsp类") 5 6 T_Bt836B_CmdRspTOutRes tBt836B_CmdRspTOutRes; 7 8 void Bt836B_CmdRspTOut_TOutEvtProc(void) 9 { 10 tBt836B_CmdRspTOutRes.bIsTOut = TRUE;//已经超时了 11 //LedBilnk(); 12 printf("Bt836B_CmdRspTOut_TOutEvtProc "); 13 } 14 15 void Bt836B_CmdRspTOut_TOutRes_Init(void) 16 { 17 tBt836B_CmdRspTOutRes.bIsProcDone = FALSE; 18 tBt836B_CmdRspTOutRes.bIsTOut = FALSE; 19 } 20 21 #endif /*E_TmrOutEvt_BtCmdRsp类*/ 22 23 // E_TmrOutEvt eTmrOutEvt,超时事件类型 24 // UINT16 usTimeOutValue,超时时间窗 25 // T_TmrOutCallBack pfTmrOutProcCallBack,超时后回调处理接口,允许在主体模块中添加简单超时后的处理操作 26 // BOOL *pbIsNrmlExit,主体正常退出超时处理标记位指针,用以在超时管理模块中自主结束超时处理逻辑 27 void Drv_Tmr_1MsTOut_Register( 28 E_TmrOutEvt eTmrOutEvt, UINT16 usTimeOutValue, T_TmrOutCallBack TmrOutProcCallBack, BOOL *pbIsNrmlExit) 29 { 30 // 同步当前超时时间 31 //while(FALSE == atTmrOutRes[eTmrOutEvt].bTimeOutFlag && 0 != atTmrOutRes[eTmrOutEvt].usCurTimeCounter); 32 while( 0 != atTmrOutRes[eTmrOutEvt].usCurTimeCounter); 33 atTmrOutRes[eTmrOutEvt].usUpdateTimeValue = usTimeOutValue; 34 atTmrOutRes[eTmrOutEvt].ptTmrOutProcCallBack = TmrOutProcCallBack; 35 atTmrOutRes[eTmrOutEvt].bUpdateFlag = TRUE; 36 atTmrOutRes[eTmrOutEvt].bTimeOutFlag = FALSE; 37 atTmrOutRes[eTmrOutEvt].pbIsNrmlExit = pbIsNrmlExit; 38 }
4、超时管理
1 void Drv_Tmr_1MsTOut_Manage(void) 2 { 3 UINT8 i=0; 4 for(i=0; i<E_TmrOutEvt_MaxLmt; i++){ 5 6 // 第一次更新超时计数器 7 if(TRUE == atTmrOutRes[i].bUpdateFlag){ 8 atTmrOutRes[i].bUpdateFlag = FALSE; 9 atTmrOutRes[i].usCurTimeCounter = atTmrOutRes[i].usUpdateTimeValue; 10 //printf("bUpdateFlag "); 11 } 12 13 // 此处进行超时处理逻辑 14 if(0 != atTmrOutRes[i].usCurTimeCounter){ 15 16 // 此处判断主体是否正常结束超时流程,并终止超时模块内的超时处理逻辑 17 if(NULL != atTmrOutRes[i].pbIsNrmlExit & (TRUE == *atTmrOutRes[i].pbIsNrmlExit) ){ 18 //printf("pbIsNrmlExit "); 19 atTmrOutRes[i].usCurTimeCounter = 0; continue; 20 21 } 22 23 atTmrOutRes[i].usCurTimeCounter--; 24 25 if(0 == atTmrOutRes[i].usCurTimeCounter){ 26 if(NULL != atTmrOutRes[i].ptTmrOutProcCallBack){ 27 //printf("ptTmr "); 28 atTmrOutRes[i].ptTmrOutProcCallBack(); 29 atTmrOutRes[i].bTimeOutFlag = TRUE; 30 } 31 } 32 } 33 } 34 }
5、demo
1: void Bt836B_CmdRspTOutDemo(void) { Drv_Bt836B_SendCmd(); // 初始化主体超时标志位缓存 Bt836B_CmdRspTOutDemo_TOutRes_Init(); // 初始化主体超时处理模块资源 Drv_Tmr_1MsTOut_Register(E_TmrOutEvt_BtCmdRsp, 1000, Bt836B_CmdRspTOutDemo_TOutEvtProc, &tBt836B_CmdRspTOutDemoRes.bIsProcDone); // 主体超时处理等待逻辑 while(FALSE == tBt836B_CmdRspTOutDemoRes.bIsTOut){ // 此处接收到Rsp以后通过bIsProcDone标志位告知超时模块终止倒计时处理 if(TRUE == Drv_Bt836B_GetRsp()){ tBt836B_CmdRspTOutDemoRes.bIsProcDone = TRUE; break;} } // 异常超时流程 if(TRUE == tBt836B_CmdRspTOutDemoRes.bIsTOut){ // ...... } } 2: // 初始化主体超时标志位缓存 Bt836B_CmdRspTOut_TOutRes_Init(); // 初始化主体超时处理模块资源 Drv_Tmr_1MsTOut_Register(E_TmrOutEvt_BtCmdRsp, 100, Bt836B_CmdRspTOut_TOutEvtProc, &tBt836B_CmdRspTOutRes.bIsProcDone); USART2_printf("AT+ADDR "); // 主体超时处理等待逻辑 //g_bBT_RSP_message_dispatcher_OK_Clear(); while(FALSE == tBt836B_CmdRspTOutRes.bIsTOut){ // 此处接收到Rsp以后通过bIsProcDone标志位告知超时模块终止倒计时处理 if(TRUE == g_bBT_RSP_message_dispatcher_OK_Get()) { Rsp_paresize=BT_836B_AT_GET("ADDR")->AT_GET_RunRsp(&ptRsp->aucRsp[0],Rsp_paresize); tBt836B_CmdRspTOutRes.bIsProcDone = TRUE; break; } } // 异常超时流程 if(TRUE == tBt836B_CmdRspTOutRes.bIsTOut){ //printf("异常超时流程 "); } return usRspParaLen;
总结: