相比於一通道,原子的例程里因為清了計數時間,所以要對程序進行修改。
記錄上升沿后的計數,然后記錄下降沿的計數。相減后計算高電平時間,對於定時器中斷間隔的邊界要分開處理。
這里因為我的接收機時間是1ms~2ms,而中斷時間設置為20ms。所以根本不需要考慮時間延遲超過計時器時間。
下面是我的代碼
//arr:自動重裝值 psc:時鍾預分頻數 //定時器溢出時間計算:Tout=((arr+1)*(psc+1))/Ft us //Ft = 定時器工作頻率,單位Mhz //TIM2在APB1上,為HCLK/2 36Mhz void TIM2_CAP_Init(u16 arr, u16 psc) { GPIO_InitTypeDef GPIO_InitStruct; TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; TIM_ICInitTypeDef TIM_ICInitStruct; NVIC_InitTypeDef NVIC_InitStruct; //開啟TIM2和GPIO時鍾 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //PA0初始化 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD; //下拉輸入 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStruct); //TIM2定時器初始化 TIM_TimeBaseInitStruct.TIM_Period = arr; TIM_TimeBaseInitStruct.TIM_Prescaler = psc; TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; //向上計數 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct); //TIM2_CH1輸入捕獲初始化 TIM_ICInitStruct.TIM_Channel = TIM_Channel_1; TIM_ICInitStruct.TIM_ICFilter = 0x00; //不濾波 TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕獲 TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1; //輸入器不分頻 TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到IC1 TIM_ICInit(TIM2, &TIM_ICInitStruct); TIM_ICInitStruct.TIM_Channel = TIM_Channel_2; TIM_ICInitStruct.TIM_ICFilter = 0x00; //不濾波 TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕獲 TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1; //輸入器不分頻 TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到IC2 TIM_ICInit(TIM2, &TIM_ICInitStruct); TIM_ICInitStruct.TIM_Channel = TIM_Channel_3; TIM_ICInitStruct.TIM_ICFilter = 0x00; //不濾波 TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕獲 TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1; //輸入器不分頻 TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到IC3 TIM_ICInit(TIM2, &TIM_ICInitStruct); TIM_ICInitStruct.TIM_Channel = TIM_Channel_4; TIM_ICInitStruct.TIM_ICFilter = 0x00; //不濾波 TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕獲 TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1; //輸入器不分頻 TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到IC4 TIM_ICInit(TIM2, &TIM_ICInitStruct); //中斷分組初始化 NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; NVIC_Init(&NVIC_InitStruct); TIM_ITConfig(TIM2, TIM_IT_CC1|TIM_IT_CC2|TIM_IT_CC3|TIM_IT_CC4, ENABLE); //更新中斷和CC1IE捕獲中斷 TIM_Cmd(TIM2, ENABLE); printf("Init TIM2 CAP success\n"); }
然后是中斷處理函數
//捕獲狀態 //[7]:0,沒有成功捕獲;1,成功捕獲到一次 //[6]:0,還沒捕獲到低電平;1,已經捕獲到低電平了. //[5:0]:捕獲低電平后溢出第次數 u8 CAPTURE_STA_TIM2CH[4] = {0}; u16 CAPTURE_VAL_TIM2CH[4]; u16 CAPTURE_UP_TIM2CH[4], CAPTURE_DOWN_TIM2CH[4]; void TIM2_IRQHandler(void) { // if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { // if((CAPTURE_STA_TIM2CH[1]&0x80) == 0) { //還未捕獲成功 // if(CAPTURE_STA_TIM2CH[1]&0x40) { //已經捕獲到高電平了 // if((CAPTURE_STA_TIM2CH[1]&0x3F)==0x3F) { //高電平太長了 // CAPTURE_STA_TIM2CH[1] |= 0x80; //標記成功捕獲了一次 // CAPTURE_VAL_TIM2CH[1] = 0xFFFF; // } else // CAPTURE_VAL_TIM2CH[1]++; // } // } // TIM_ClearITPendingBit(TIM2, TIM_IT_Update); // } if((CAPTURE_STA_TIM2CH[0]&0x80) == 0) { //還未捕獲成功 if(TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET) { //捕獲1發生捕獲事件 if(CAPTURE_STA_TIM2CH[0]&0x40) { //捕獲到一個下降沿 CAPTURE_STA_TIM2CH[0] |= 0x80; //標記成功捕獲到一次高電平脈寬 CAPTURE_DOWN_TIM2CH[0] = TIM_GetCapture1(TIM2); if(CAPTURE_DOWN_TIM2CH[0] >= CAPTURE_UP_TIM2CH[0]) CAPTURE_VAL_TIM2CH[0] = CAPTURE_DOWN_TIM2CH[0] - CAPTURE_UP_TIM2CH[0]; else CAPTURE_VAL_TIM2CH[0] = 0xffff + CAPTURE_DOWN_TIM2CH[0] - CAPTURE_UP_TIM2CH[0]; TIM_OC1PolarityConfig(TIM2, TIM_ICPolarity_Rising); //CC1P=0 設置為上升沿捕獲 } else { //還未開始,第一次捕獲上升沿 CAPTURE_STA_TIM2CH[0] = 0; //清空 CAPTURE_VAL_TIM2CH[0] = 0; CAPTURE_UP_TIM2CH[0] = TIM_GetCapture1(TIM2); CAPTURE_STA_TIM2CH[0] |= 0x40; //標記捕獲到了上升沿 TIM_OC1PolarityConfig(TIM2, TIM_ICPolarity_Falling); //CC1P=1 設置為下降沿捕獲 } TIM_ClearFlag(TIM2, TIM_FLAG_CC1); //清除狀態標志 } } if((CAPTURE_STA_TIM2CH[1]&0x80) == 0) { //還未捕獲成功 if(TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET) { //捕獲2發生捕獲事件 if(CAPTURE_STA_TIM2CH[1]&0x40) { //捕獲到一個下降沿 CAPTURE_STA_TIM2CH[1] |= 0x80; //標記成功捕獲到一次高電平脈寬 CAPTURE_DOWN_TIM2CH[1] = TIM_GetCapture2(TIM2); //獲取捕獲2計數 if(CAPTURE_DOWN_TIM2CH[1] >= CAPTURE_UP_TIM2CH[1]) CAPTURE_VAL_TIM2CH[1] = CAPTURE_DOWN_TIM2CH[1] - CAPTURE_UP_TIM2CH[1]; else CAPTURE_VAL_TIM2CH[1] = 0xffff + CAPTURE_DOWN_TIM2CH[1] - CAPTURE_UP_TIM2CH[1]; TIM_OC2PolarityConfig(TIM2, TIM_ICPolarity_Rising); //CC1P=0 設置為上升沿捕獲 } else { //還未開始,第一次捕獲上升沿 CAPTURE_STA_TIM2CH[1] = 0; //清空 CAPTURE_VAL_TIM2CH[1] = 0; CAPTURE_UP_TIM2CH[1] = TIM_GetCapture2(TIM2); CAPTURE_STA_TIM2CH[1] |= 0x40; //標記捕獲到了上升沿 TIM_OC2PolarityConfig(TIM2, TIM_ICPolarity_Falling); //CC1P=1 設置為下降沿捕獲 } TIM_ClearFlag(TIM2, TIM_FLAG_CC2); //清除狀態標志 } } if((CAPTURE_STA_TIM2CH[2]&0x80) == 0) { //還未捕獲成功 if(TIM_GetITStatus(TIM2, TIM_IT_CC3) != RESET) { //捕獲2發生捕獲事件 if(CAPTURE_STA_TIM2CH[2]&0x40) { //捕獲到一個下降沿 CAPTURE_STA_TIM2CH[2] |= 0x80; //標記成功捕獲到一次高電平脈寬 CAPTURE_DOWN_TIM2CH[2] = TIM_GetCapture3(TIM2); //獲取捕獲2計數 if(CAPTURE_DOWN_TIM2CH[2] >= CAPTURE_UP_TIM2CH[2]) CAPTURE_VAL_TIM2CH[2] = CAPTURE_DOWN_TIM2CH[2] - CAPTURE_UP_TIM2CH[2]; else CAPTURE_VAL_TIM2CH[2] = 0xffff + CAPTURE_DOWN_TIM2CH[2] - CAPTURE_UP_TIM2CH[2]; TIM_OC3PolarityConfig(TIM2, TIM_ICPolarity_Rising); //CC1P=0 設置為上升沿捕獲 } else { //還未開始,第一次捕獲上升沿 CAPTURE_STA_TIM2CH[2] = 0; //清空 CAPTURE_VAL_TIM2CH[2] = 0; CAPTURE_UP_TIM2CH[2] = TIM_GetCapture3(TIM2); CAPTURE_STA_TIM2CH[2] |= 0x40; //標記捕獲到了上升沿 TIM_OC3PolarityConfig(TIM2, TIM_ICPolarity_Falling); //CC1P=1 設置為下降沿捕獲 } TIM_ClearFlag(TIM2, TIM_FLAG_CC3); //清除狀態標志 } } if((CAPTURE_STA_TIM2CH[3]&0x80) == 0) { //還未捕獲成功 if(TIM_GetITStatus(TIM2, TIM_IT_CC4) != RESET) { //捕獲2發生捕獲事件 if(CAPTURE_STA_TIM2CH[3]&0x40) { //捕獲到一個下降沿 CAPTURE_STA_TIM2CH[3] |= 0x80; //標記成功捕獲到一次高電平脈寬 CAPTURE_DOWN_TIM2CH[3] = TIM_GetCapture4(TIM2); //獲取捕獲2計數 if(CAPTURE_DOWN_TIM2CH[3] >= CAPTURE_UP_TIM2CH[3]) CAPTURE_VAL_TIM2CH[3] = CAPTURE_DOWN_TIM2CH[3] - CAPTURE_UP_TIM2CH[3]; else CAPTURE_VAL_TIM2CH[3] = 0xffff + CAPTURE_DOWN_TIM2CH[3] - CAPTURE_UP_TIM2CH[3]; TIM_OC4PolarityConfig(TIM2, TIM_ICPolarity_Rising); //CC1P=0 設置為上升沿捕獲 } else { //還未開始,第一次捕獲上升沿 CAPTURE_STA_TIM2CH[3] = 0; //清空 CAPTURE_VAL_TIM2CH[3] = 0; CAPTURE_UP_TIM2CH[3] = TIM_GetCapture4(TIM2); CAPTURE_STA_TIM2CH[3] |= 0x40; //標記捕獲到了上升沿 TIM_OC4PolarityConfig(TIM2, TIM_ICPolarity_Falling); //CC1P=1 設置為下降沿捕獲 } TIM_ClearFlag(TIM2, TIM_FLAG_CC4); //清除狀態標志 } } //處理幀數據 if(CAPTURE_STA_TIM2CH[0]&0x80) { //成功捕獲到了一次上升沿 //溢出時間總和 myControl.remoteControl[0] = CAPTURE_VAL_TIM2CH[0]; //得到總的高電平時間 // printf("TIM2 CH1:%d\t", temp[0]); CAPTURE_STA_TIM2CH[0] = 0; } if(CAPTURE_STA_TIM2CH[1]&0x80) { //成功捕獲到了一次上升沿 //溢出時間總和 myControl.remoteControl[1] = CAPTURE_VAL_TIM2CH[1]; //得到總的高電平時間 // printf("TIM2 CH2:%d\t", temp[1]); CAPTURE_STA_TIM2CH[1] = 0; } if(CAPTURE_STA_TIM2CH[2]&0x80) { //成功捕獲到了一次上升沿 //溢出時間總和 myControl.remoteControl[2] = CAPTURE_VAL_TIM2CH[2]; //得到總的高電平時間 // printf("TIM2 CH3:%d\t", temp[2]); CAPTURE_STA_TIM2CH[2] = 0; } if(CAPTURE_STA_TIM2CH[3]&0x80) { //成功捕獲到了一次上升沿 //溢出時間總和 myControl.remoteControl[3] = CAPTURE_VAL_TIM2CH[3]; //得到總的高電平時間 // printf("TIM2 CH4:%d\t", temp[3]); CAPTURE_STA_TIM2CH[3] = 0; } }
這些printf函數會極大的占用MCU資源,所以不在中斷中處理。