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口,模式為輸入:GPIO_Init();
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 輸入
③初始化定時器ARR,PSC
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); //清除中斷標誌位