stm32定時器pwm模式輸入捕獲 stm32中的定時器,除了TIM6和TIM7,其他定時器都有輸入捕獲功能。這種模式通常用在對輸入信號頻率frequency、占空比duty、高低脈寬的計算中,具有很廣泛的用途。 STM32的輸入捕獲,簡單的說就是通過檢測TIMx_CHx上的邊沿信號,在邊沿信號發生跳變(比如上升沿/下降沿)的時候,將當前定時器的值(TIMx_CNT)存放到對應的通道的捕獲/比較寄存(TIMx_CCRx)里面,完成一次捕獲。同時還可以配置捕獲時是否觸發中斷/DMA 等。 PWM模式捕獲方法:利用TIM3_CH1作PWM輸出,TIM2_CH2捕獲上述PWM信號,并測出頻率和占空比。設置PWM頻率為1KHz,占空比50%。 具體步驟: 1. 為了實現PWM輸入捕獲,TIM2占用了2個通道。第2通道的電平變化會被第一通道和第二通道引腳檢測到,其中第一通道被設置為從機模式(如何快速判別主從機模式,規則如下:如果設置的是第二通道作為PWM輸入捕獲,則剩余的第一通道都為從機,反之亦然)。 2. 假設輸入的PWM從低電平開始跳變,在第一個上升沿到來時,1,2通道同時檢測到上升沿。而從機設置為復位模式,所以將TIM2的計數值復位至0,此時不會產生一個中斷請求。 3. 下一個到來的電平是下降沿,此時通道1發生捕獲事件,將計數值存入通道1的CCR1里。 4. 然后是第二個上升沿到來后,此時通道2發生捕獲事件,將此時的計數值存入通道2的CCR2里。復位模式此時又將TIM2計數值復位至0,等待第二個下降沿到來。 5. 一次捕獲過程完成,則PWM的頻率f=72M/CCR2;占空比:duty=(CCR1/CCR2)X100% 注: PWM輸入模式時,用到兩個通道(一般用TIMx_CH1或TIMx_CH2),只給其中一個通道分配gpio時鐘即可,另一個在內部使用。給一個通道分配gpio時鐘后,需要設置另一個為從機且復位模式。(例如使用ch2,ch1就得設置成從機模式)。當一個輸入信號(TI1或TI2)來臨時,主通道捕獲上升沿,從機捕獲下降沿。 在CH2通道中: TI2FP1和TI2FP2都來自同一信號TI2 的邊沿檢測,信號相同,同一個TIx輸入映射了兩個ICx信號。 TI2FP1和TI2FP2可以分別由連接到的ICx(IC1或是IC2)相對應的控制寄存器設為上升沿或是下降沿觸發,這兩個ICx信號分別在相反的極性邊沿有效。如果TI2FP2設置為上升沿觸發,則TI2FP1設置為下降沿觸發,二者極性相反。 CH1,3,4相同。 file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image002.jpg 具體程序: include “pbdata.h” void RCC_Configuration(void); void GPIO_Configuration(void); void NVIC_Configuration(void); void TIM2_Configuration(void); void TIM3_Configuration(void); void USART_Configuration(void); int fputc(int ch,FILE *f) { USART_SendData(USART1,(u8)ch); while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET); return ch; } int main(void) { RCC_Configuration(); //配置時鐘 GPIO_Configuration();//IO口配置 TIM3_Configuration(); TIM2_Configuration(); NVIC_Configuration(); USART_Configuration(); while(1) { if(flag==1) { flag=0; printf(“the duty is %d/r/n”,duty); printf(“the frequency is %.2fKHz/r/n”,freq); } } } void RCC_Configuration(void) { SystemInit(); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2|RCC_APB1Periph_TIM3,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); } void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; //LED GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//TX GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; GPIO_Init(GPIOA,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//RX GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;//PWM,TIM3_CH1 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; GPIO_Init(GPIOA,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;//TIM2_CH2 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA,&GPIO_InitStructure); } void TIM2_Configuration(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct; TIM_ICInitTypeDef TIM_ICInitStructure; TIM_ICInitStructure.TIM_Channel=TIM_Channel_2;//選擇TIM2_CH2,選擇輸入端 IC2映射到TI2上 TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;//上升沿捕獲 TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;//映射到TI2上 TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;//在捕獲輸入上每探測到一個邊沿執行一次捕獲 TIM_ICInitStructure.TIM_ICFilter=0;//濾波設置,經歷幾個周期跳變認定波形穩定。(采樣高電平,只有連續采集到N個電平是高電平時才認為是有效的,否則低于N個時認為是無效的,N取0x0-0xF) TIM_PWMIConfig(TIM2,&TIM_ICInitStructure);//以上是輸入捕獲配置 TIM_SelectInputTrigger(TIM2,TIM_TS_TI2FP2);//選擇濾波后的TI2FP2輸入作為觸發源,觸發下面程序的復位 TIM_SelectSlaveMode(TIM2,TIM_SlaveMode_Reset);//從模式控制器被設置為復位模式-選中的觸發信號上升沿重新初始化計數器并產生一個更新信號(上升沿一到,TIM2->CNT被清零,每次上升沿來到,CNT都會被清零) TIM_SelectMasterSlaveMode(TIM2,TIM_MasterSlaveMode_Enable);//啟動定時器的被動觸發 TIM_ITConfig(TIM2,TIM_IT_CC2,ENABLE);//捕獲中斷打開 TIM_ClearFlag(TIM2,TIM_IT_CC2);//清除標志位 TIM_Cmd(TIM2,ENABLE);//使能定時器2 } void TIM3_Configuration(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct; TIM_OCInitTypeDef TIM_OCInitStructure; TIM_TimeBaseStruct.TIM_Period=72000;//計數初值 TIM_TimeBaseStruct.TIM_Prescaler=0;//分頻系數 TIM_TimeBaseStruct.TIM_ClockDivision=0;//時鐘分割 TIM_TimeBaseStruct.TIM_CounterMode=TIM_CounterMode_Up;//向上計數模式 TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStruct); //TIM3_CH1作為pwm輸出 TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse=36000; TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High; TIM_OC1Init(TIM3,&TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable); TIM_ARRPreloadConfig(TIM3,ENABLE); TIM_Cmd(TIM3,ENABLE); } void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); NVIC_InitStructure.NVIC_IRQChannel =TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority= 1; NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE; NVIC_Init(&NVIC_InitStructure); } void USART_Configuration(void) { USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate=115200; USART_InitStructure.USART_WordLength=USART_WordLength_8b; USART_InitStructure.USART_StopBits=USART_StopBits_1; USART_InitStructure.USART_Parity=USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx; USART_Init(USART1,&USART_InitStructure); USART_Cmd(USART1,ENABLE); USART_ClearFlag(USART1,USART_FLAG_TC); } //中斷程序 void TIM2_IRQHandler(void) { if(TIM_GetITStatus(TIM2,TIM_IT_CC2)==Bit_SET) { float IC2Value=0; float DutyCycle=0; float Frequency=0; float pulse=0; IC2Value=TIM_GetCapture2(TIM2);//獲得CCR2的值 pulse=TIM_GetCapture1(TIM2);//獲得CCR1的值 DutyCycle=pulse/IC2Value; Frequency=72000000/IC2Value; duty=(u32)(DutyCycle*100); freq=(Frequency/1000); flag=1; TIM_ClearITPendingBit(TIM2,TIM_IT_CC2); } } duty和freq是定義的全局變量 extern u32 duty; extern u16 freq; u32 duty=0; u16 freq=0; 經調試程序可用。頻率和占空比都對。頻率的設置不要太高,因為printf函數發數所需時間較多,兩次捕獲的時間間隔短的話可能使printf不能及時地送出數據,造成數據被刷新。更改方法,使用:USART_SendData();函數發數。 其他應用: 1.測量高電平時間:a,上文中的CCR1就是高電平時間;b,當使用一個通道CH1時,先將觸發沿選為為上升沿,產生捕獲中斷,讀取CCR1中的內容,再改變觸發沿為下降沿,下降沿到來時捕獲,再次讀出CCR1的內容,兩次相減為高電平時間。 2.測量脈沖個數:a,開啟定時器1的捕獲中斷,捕獲信號邊沿(上升沿或下降沿)進中斷,count++計數,再開啟定時器2的更新中斷,定時一定時間進更新中斷,讀取count值,此為脈沖個數。b,開啟外部中斷,配置沿觸發中斷,count++計數,再開啟定時器x的更新中斷,定時一定時間進更新中斷,讀取count值,此為脈沖個數。 3.計算一路信號的頻率,可以選擇定時器的CH1或CH2(不可同時計算兩路頻率,否則計算出的頻率是后初始化的那個通道代表的信號頻率。當然,要同時也可以,每次得到頻率后切換通道,將數據通過DMA取走即可),使用PWM輸入捕獲模式,使用上升沿觸發。而CH3和CH4通道則不行,如圖2所示,只有紅線所指的4個信號連在了從模式控制器上。所以,對于3和4通道,計數器的值不可能在接受到信號上升沿時候,有復位這個動作。 file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image004.jpg --------------------- 原文:https://blog.csdn.net/qq_29413829/article/details/52743273 版權聲明:本文為博主原創文章,轉載請附上博文鏈接!
|