1. 程式人生 > >stm32f103輸入捕獲

stm32f103輸入捕獲

stm32的定時器具有捕獲功能,能夠捕獲上升沿或者下降沿然後觸發中斷。

定時器框圖:

細化框圖:

濾波器:判斷在捕獲到邊沿訊號的時候,以Fdts的頻率連續採集N次該引腳上電平判斷電平是否穩定。其中Fdts由控制暫存器 1(TIMx_CR1)的CKD位控制而採集頻率又受到IC1F位的控制。

注意:這裡有兩個頻率,一個Fdts一個取樣頻率分開理解。取樣頻率可能受Fdts有可能受FINT的控制所以要設定CDK是中分頻因子,而N為採集次數。

例如:IC1F設定為011:N=8且上升沿捕獲,當我們捕獲到上升沿後濾波器以取樣頻率採集8次io上的電平如果8次都是1那麼說明是有效觸發就會觸發中斷反之不會觸發中斷。

邊沿檢測器:檢測是上升沿還是下降沿。

輸入捕獲對映通道:我們通過配置CCMR1暫存器可以使得TI1的輸入捕獲對映到TI1或者TI2上

 

輸入捕獲分頻器:實際就是配置捕獲到幾次有效邊沿觸發一次中斷,例如ICPS=10也就是4分頻,當捕獲到4次有效邊沿時才會觸發一次中斷請求。

捕獲到有效訊號可以開啟中斷

輸入捕獲過程總結:得到io邊沿---->濾波------>檢測是上升沿還是下降沿------->是否要開啟通道對映------->分頻(幾次有效觸發產生一起中斷請求)

stm32庫函式配置過程:

① 初始化定時器和通道對應

IO的時鐘。

② 初始化IO口,模式為輸入:GPIO_Init();

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 輸入

③初始化定時器ARRPSC

   TIM_TimeBaseInit();

④初始化輸入捕獲通道

   TIM_ICInit();

⑤如果要開啟捕獲中斷,

    TIM_ITConfig();

    NVIC_Init();

⑥使能定時器:TIM_Cmd

();

⑦編寫中斷服務函式:TIMx_IRQHandler();

注意:

通道極性設定獨立函式:

void TIM_OCxPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity)

獲取通道捕獲值:

uint32_t TIM_GetCapture1(TIM_TypeDef* TIMx)

輸入捕獲通道初始化函式:

void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);

typedef struct

{

  uint16_t TIM_Channel; //捕獲通道1-4  

  uint16_t TIM_ICPolarity; //捕獲極性

  uint16_t TIM_ICSelection; //對映關係

  uint16_t TIM_ICPrescaler; //分頻係數

  uint16_t TIM_ICFilter;  //濾波器

} TIM_ICInitTypeDef;

例如:

TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1; TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;

TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;

TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;

TIM5_ICInitStructure.TIM_ICFilter = 0x00;

TIM_ICInit(TIM5, &TIM5_ICInitStructure);

這裡我們參考原子歷程說說如何捕獲高電平所佔時間:

首先我們初始化捕獲中斷時設定捕獲上升沿觸發中斷。當我們捕獲到上升沿後開啟下降沿捕獲模式,並且當定時器發生溢位事件CAPTURE_STA++直到我們捕獲到下降沿時標誌著捕獲完成此時的高電平所佔時間=CAPTURE_STA&0x3f*定時間一出一次的時間+當前拘束暫存器中的值。由於我們設定捕獲頻率為1Mhz也就是1us中斷一次表示式變為:

高電平所佔時間=+CAPTURE_STA&0x3f*65536+當前拘束暫存器中的值(的道德實踐單位為us)

其中:CAPTURE_STA為8位高兩位為捕獲標誌位:bit7帶包捕獲完成,bit6代表捕獲到下降沿,其餘的為溢位次數。

注意:當溢位次數達到3f時代表高電平持續時間太長,捕獲失敗。

void TIM2_IRQHandler(void)

     if((TIM2CH1_CAPTURE_STA&0X80)==0)//還未成功捕獲    
    {      
        if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
         
        {        
            if(TIM2CH1_CAPTURE_STA&0X40)//已經捕獲到高電平了
            {
                if((TIM2CH1_CAPTURE_STA&0X3F)==0X3F)//高電平太長了
                {
                    TIM2CH1_CAPTURE_STA|=0X80;//標記成功捕獲了一次
                    TIM2CH1_CAPTURE_VAL=0XFFFF;
                }else TIM2CH1_CAPTURE_STA++;
            }     
        }
    if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)//捕獲1發生捕獲事件
        {    
            if(TIM2CH1_CAPTURE_STA&0X40)        //捕獲到一個下降沿         
            {                  
                TIM2CH1_CAPTURE_STA|=0X80;        //標記成功捕獲到一次上升沿
                TIM2CH1_CAPTURE_VAL=TIM_GetCapture1(TIM2);
                   TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Rising); //CC1P=0 設定為上升沿捕獲
            }else                                  //還未開始,第一次捕獲上升沿
            {
                TIM2CH1_CAPTURE_STA=0;            //清空
                TIM2CH1_CAPTURE_VAL=0;
                 TIM_SetCounter(TIM2,0);
                TIM2CH1_CAPTURE_STA|=0X40;        //標記捕獲到了上升沿
                   TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Falling);        //CC1P=1 設定為下降沿捕獲
            }            
        }                                                
     }
 
    TIM_ClearITPendingBit(TIM2, TIM_IT_CC1|TIM_IT_Update); //清除中斷標誌位