STM32輸入捕獲TIM2四通道


相比於一通道,原子的例程里因為清了計數時間,所以要對程序進行修改。

記錄上升沿后的計數,然后記錄下降沿的計數。相減后計算高電平時間,對於定時器中斷間隔的邊界要分開處理。

這里因為我的接收機時間是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資源,所以不在中斷中處理。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM