stm32 输入捕获学习(一)
輸入捕獲模式可以用來測量脈沖寬度或者測量頻率。STM32 的定時器,除了 TIM6 和 TIM7,其他定時器都有輸入捕獲功能。STM32 的輸入捕獲,簡單地說就是通過檢測 TIMx_CHx 上的邊沿信號,在邊沿信號發生跳變(比如上升沿/下降沿)的時候,將當前定時器的值(TIMx_CNT)存放到對應的通道的捕獲/比較寄存器(TIMx_CCRx)中。
1. 相關寄存器介紹
1)?捕獲/比較模式寄存器 (TIMx_CCMRx)?
當在輸入捕獲模式下使用的時候,對應上圖的第二行描述,從圖中可以看出,TIMx_CCMR1 明顯是針對 2 個通道的配置,低八位[7:0]用于捕獲/比較通道 1 的控制,而高八位[15:8]則用于捕獲/比較通道 2 的控制。同理,CCMR2 這個寄存器用來控制通道 3 和通道 4。今天的實驗,我們用到的是 TIM5 的捕獲/比較通道 1。
?(1)CC1S[1:0],這兩個位用于 CCR1 的通道配置,這里我們設置 CC1S[1:0]=01,也就是配置 IC1 映射在 TI1 上。如果不理解沒有關系,看圖就知道了。
從圖中可以知道,IC1有三個輸入源,分別是TI1,TI2,TRC。
TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; 這是通過庫函數配置,映射到TI1。
頭文件(stm32f10x_tim.h)定義如下:
#define TIM_ICSelection_DirectTI ? ? ? ? ? ((uint16_t)0x0001)?
#define TIM_ICSelection_IndirectTI ? ? ? ? ((uint16_t)0x0002)?
#define TIM_ICSelection_TRC ? ? ? ? ? ? ? ? ((uint16_t)0x0003)
(2)IC1F[3:0]
表格中的f_ck_int 是定時器的輸入頻率(TIMxCLK),f_dts?則是根據 TIMx_CR1 的 CKD[1:0]來確定。
上圖就是TIMx_CR1寄存器。
#define TIM_CKD_DIV1 ? ? ? ? ? ? ? ? ? ? ? ((uint16_t)0x0000)
#define TIM_CKD_DIV2 ? ? ? ? ? ? ? ? ? ? ? ((uint16_t)0x0100)
#define TIM_CKD_DIV4 ? ? ? ? ? ? ? ? ? ? ? ((uint16_t)0x0200)
假定選IC1F[3:0]=0101,即采樣頻率為fDTS/2, N=8;
選CKD[1:0]=01,即 tDTS = 2 × tCK_INT;并假定 fCK_INT=72MHz。 ?
這時可以算出,采樣頻率為72MHz/2/2=18MHz.
1/(18MHz)*8 = 0.4444us = 444.4ns.
因為N=8,所以濾波器可以濾除掉輸入端小于444.4ns的脈沖。?
“數字濾波器由一個事件計數器組成,它記錄到N個事件后會產生一個輸出的跳變”,這句話可以這樣理解:
當濾波器連續采樣到N個有效電平時,就輸出這個有效電平。?
當濾波器沒有連續采樣到N個有效電平時,再從0開始計數,輸出一直保持上一次輸出的有效電平。
例如:濾波器上一次輸出是高電平,本次連續采樣到(N-1)個高電平,但第N個是個低電平,那么濾波器仍然保持上次輸出的高電平,并重新開始計數,記錄1次低電平,如果其后采樣的(N-1)個也是低電平,此時濾波才輸出低電平,于是一個下降沿才出現在IC1上。
(3)IC1PSC[1:0]
這里的“事件”指的是上升沿或者下降沿,具體是哪個由TIMx_CCER寄存器的CCxP位決定。
2)捕獲/比較使能寄存器:TIMx_CCER
所以,要使能輸入捕獲,必須設置 CC1E=1,而 CC1P 則根據自己的需要來配置(捕獲發生在上升沿還是下降沿)。?
3)?DMA/中斷使能寄存器(TIMx_DIER)?
在實驗中,我們需要允許位0和位1的中斷。
#define TIM_IT_Update ? ? ? ? ? ? ? ? ? ? ?((uint16_t)0x0001)
#define TIM_IT_CC1 ? ? ? ? ? ? ? ? ? ? ? ? ((uint16_t)0x0002)
#define TIM_IT_CC2 ? ? ? ? ? ? ? ? ? ? ? ? ((uint16_t)0x0004)
#define TIM_IT_CC3 ? ? ? ? ? ? ? ? ? ? ? ? ((uint16_t)0x0008)
#define TIM_IT_CC4 ? ? ? ? ? ? ? ? ? ? ? ? ((uint16_t)0x0010)
對應的庫函數是:TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);
4)?捕獲/比較寄存器 (TIMx_CCRx)?
該寄存器用來存儲捕獲發生時,TIMx_CNT的值,我們從 TIMx_CCR1 就可以讀出通道 1 捕獲發生時刻的 TIMx_CNT 值,通過兩次捕獲(一次上升沿捕獲,一次下降沿捕獲)的差值,就可以計算出高電平脈沖的寬度。
2. 實驗設計
通過TIM3產生一路PWM(從PB5輸出),把PB5連接到PA0上,PA0和?TIM5_CH1是同一個管腳。利用TIM5_CH1的輸入捕獲功能,測量出PWM的寬度。
3. 參考代碼
//TIM5_CH1輸入捕獲配置 void TIM5_Cap_Init(u16 arr,u16 psc) { TIM_ICInitTypeDef TIM5_ICInitStructure;TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //使能TIM5時鐘//TIM5的配置TIM_TimeBaseStructure.TIM_Period = arr; //重裝載值TIM_TimeBaseStructure.TIM_Prescaler =psc; //分頻系數 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //tDTS = tCK_INTTIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上計數TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); //TIM5輸入捕獲配置TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1; //我們用通道1TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕獲TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //無預分頻器 TIM5_ICInitStructure.TIM_ICFilter = 0x00; //IC1F=0000 ,無濾波器TIM_ICInit(TIM5, &TIM5_ICInitStructure);//中斷優先級配置NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);//打開更新中斷和捕獲中斷TIM_Cmd(TIM5,ENABLE ); //使能定時器5}
#define START 0X01 #define WAIT_RISING 0X02 #define WAIT_FALLING 0X03u16 TIM5CH1_CAPTURE_VAL; //輸入捕獲值 u32 a[500] = {0}; //存放電平寬度 u32 i = 0; //數組下標 u8 overflow = 0; //記錄定時器更新中斷的次數 u8 state = START;//定時器5中斷服務程序 void TIM5_IRQHandler(void) { if(i<500){ if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET){ ++overflow;}if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)//捕獲事件{ if(state == START) //初始狀態 { overflow = 0;TIM_SetCounter(TIM5,0);state = WAIT_FALLING;TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling); //設置為下降沿捕獲} else if(state == WAIT_RISING) //等待上升沿{TIM5CH1_CAPTURE_VAL = TIM_GetCapture1(TIM5);a[i++] = TIM5CH1_CAPTURE_VAL + overflow*65536;overflow = 0;TIM_SetCounter(TIM5,0);state = WAIT_FALLING;TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling); //設置為下降沿捕獲}else // wait falling{TIM5CH1_CAPTURE_VAL = TIM_GetCapture1(TIM5);a[i++] = TIM5CH1_CAPTURE_VAL + overflow*65536;overflow = 0;TIM_SetCounter(TIM5,0);state = WAIT_RISING;TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //設置為上升沿捕獲}} }TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); //清除中斷 } int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中斷優先級分組TIM3_PWM_Init(999,71); // 72/(71+1)=1MHz, T=1us*(999+1) = 1ms TIM_SetCompare2(TIM3,650); TIM5_Cap_Init(0XFFFF,71); //以1MHz頻率計數while(1){;} }4.實驗結果
1) 仿真圖
PWM 高電平= 350us, 低電平=650us
2) 得出的數組
高電平:347us, 低電平 647us
結論:實驗OK
總結
以上是生活随笔為你收集整理的stm32 输入捕获学习(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 高效率人士的日常习惯
- 下一篇: 2020国货彩妆市场研究报告