stm32定時(shí)器pwm模式輸入捕獲 stm32中的定時(shí)器,除了TIM6和TIM7,其他定時(shí)器都有輸入捕獲功能。這種模式通常用在對(duì)輸入信號(hào)頻率frequency、占空比duty、高低脈寬的計(jì)算中,具有很廣泛的用途。 STM32的輸入捕獲,簡(jiǎn)單的說(shuō)就是通過(guò)檢測(cè)TIMx_CHx上的邊沿信號(hào),在邊沿信號(hào)發(fā)生跳變(比如上升沿/下降沿)的時(shí)候,將當(dāng)前定時(shí)器的值(TIMx_CNT)存放到對(duì)應(yīng)的通道的捕獲/比較寄存(TIMx_CCRx)里面,完成一次捕獲。同時(shí)還可以配置捕獲時(shí)是否觸發(fā)中斷/DMA 等。 PWM模式捕獲方法:利用TIM3_CH1作PWM輸出,TIM2_CH2捕獲上述PWM信號(hào),并測(cè)出頻率和占空比。設(shè)置PWM頻率為1KHz,占空比50%。 具體步驟: 1. 為了實(shí)現(xiàn)PWM輸入捕獲,TIM2占用了2個(gè)通道。第2通道的電平變化會(huì)被第一通道和第二通道引腳檢測(cè)到,其中第一通道被設(shè)置為從機(jī)模式(如何快速判別主從機(jī)模式,規(guī)則如下:如果設(shè)置的是第二通道作為PWM輸入捕獲,則剩余的第一通道都為從機(jī),反之亦然)。 2. 假設(shè)輸入的PWM從低電平開(kāi)始跳變,在第一個(gè)上升沿到來(lái)時(shí),1,2通道同時(shí)檢測(cè)到上升沿。而從機(jī)設(shè)置為復(fù)位模式,所以將TIM2的計(jì)數(shù)值復(fù)位至0,此時(shí)不會(huì)產(chǎn)生一個(gè)中斷請(qǐng)求。 3. 下一個(gè)到來(lái)的電平是下降沿,此時(shí)通道1發(fā)生捕獲事件,將計(jì)數(shù)值存入通道1的CCR1里。 4. 然后是第二個(gè)上升沿到來(lái)后,此時(shí)通道2發(fā)生捕獲事件,將此時(shí)的計(jì)數(shù)值存入通道2的CCR2里。復(fù)位模式此時(shí)又將TIM2計(jì)數(shù)值復(fù)位至0,等待第二個(gè)下降沿到來(lái)。 5. 一次捕獲過(guò)程完成,則PWM的頻率f=72M/CCR2;占空比:duty=(CCR1/CCR2)X100% 注: PWM輸入模式時(shí),用到兩個(gè)通道(一般用TIMx_CH1或TIMx_CH2),只給其中一個(gè)通道分配gpio時(shí)鐘即可,另一個(gè)在內(nèi)部使用。給一個(gè)通道分配gpio時(shí)鐘后,需要設(shè)置另一個(gè)為從機(jī)且復(fù)位模式。(例如使用ch2,ch1就得設(shè)置成從機(jī)模式)。當(dāng)一個(gè)輸入信號(hào)(TI1或TI2)來(lái)臨時(shí),主通道捕獲上升沿,從機(jī)捕獲下降沿。 在CH2通道中: TI2FP1和TI2FP2都來(lái)自同一信號(hào)TI2 的邊沿檢測(cè),信號(hào)相同,同一個(gè)TIx輸入映射了兩個(gè)ICx信號(hào)。 TI2FP1和TI2FP2可以分別由連接到的ICx(IC1或是IC2)相對(duì)應(yīng)的控制寄存器設(shè)為上升沿或是下降沿觸發(fā),這兩個(gè)ICx信號(hào)分別在相反的極性邊沿有效。如果TI2FP2設(shè)置為上升沿觸發(fā),則TI2FP1設(shè)置為下降沿觸發(fā),二者極性相反。 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(); //配置時(shí)鐘 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;//在捕獲輸入上每探測(cè)到一個(gè)邊沿執(zhí)行一次捕獲 TIM_ICInitStructure.TIM_ICFilter=0;//濾波設(shè)置,經(jīng)歷幾個(gè)周期跳變認(rèn)定波形穩(wěn)定。(采樣高電平,只有連續(xù)采集到N個(gè)電平是高電平時(shí)才認(rèn)為是有效的,否則低于N個(gè)時(shí)認(rèn)為是無(wú)效的,N取0x0-0xF) TIM_PWMIConfig(TIM2,&TIM_ICInitStructure);//以上是輸入捕獲配置 TIM_SelectInputTrigger(TIM2,TIM_TS_TI2FP2);//選擇濾波后的TI2FP2輸入作為觸發(fā)源,觸發(fā)下面程序的復(fù)位 TIM_SelectSlaveMode(TIM2,TIM_SlaveMode_Reset);//從模式控制器被設(shè)置為復(fù)位模式-選中的觸發(fā)信號(hào)上升沿重新初始化計(jì)數(shù)器并產(chǎn)生一個(gè)更新信號(hào)(上升沿一到,TIM2->CNT被清零,每次上升沿來(lái)到,CNT都會(huì)被清零) TIM_SelectMasterSlaveMode(TIM2,TIM_MasterSlaveMode_Enable);//啟動(dòng)定時(shí)器的被動(dòng)觸發(fā) TIM_ITConfig(TIM2,TIM_IT_CC2,ENABLE);//捕獲中斷打開(kāi) TIM_ClearFlag(TIM2,TIM_IT_CC2);//清除標(biāo)志位 TIM_Cmd(TIM2,ENABLE);//使能定時(shí)器2 } void TIM3_Configuration(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct; TIM_OCInitTypeDef TIM_OCInitStructure; TIM_TimeBaseStruct.TIM_Period=72000;//計(jì)數(shù)初值 TIM_TimeBaseStruct.TIM_Prescaler=0;//分頻系數(shù) TIM_TimeBaseStruct.TIM_ClockDivision=0;//時(shí)鐘分割 TIM_TimeBaseStruct.TIM_CounterMode=TIM_CounterMode_Up;//向上計(jì)數(shù)模式 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; 經(jīng)調(diào)試程序可用。頻率和占空比都對(duì)。頻率的設(shè)置不要太高,因?yàn)?/font>printf函數(shù)發(fā)數(shù)所需時(shí)間較多,兩次捕獲的時(shí)間間隔短的話可能使printf不能及時(shí)地送出數(shù)據(jù),造成數(shù)據(jù)被刷新。更改方法,使用:USART_SendData();函數(shù)發(fā)數(shù)。 其他應(yīng)用: 1.測(cè)量高電平時(shí)間:a,上文中的CCR1就是高電平時(shí)間;b,當(dāng)使用一個(gè)通道CH1時(shí),先將觸發(fā)沿選為為上升沿,產(chǎn)生捕獲中斷,讀取CCR1中的內(nèi)容,再改變觸發(fā)沿為下降沿,下降沿到來(lái)時(shí)捕獲,再次讀出CCR1的內(nèi)容,兩次相減為高電平時(shí)間。 2.測(cè)量脈沖個(gè)數(shù):a,開(kāi)啟定時(shí)器1的捕獲中斷,捕獲信號(hào)邊沿(上升沿或下降沿)進(jìn)中斷,count++計(jì)數(shù),再開(kāi)啟定時(shí)器2的更新中斷,定時(shí)一定時(shí)間進(jìn)更新中斷,讀取count值,此為脈沖個(gè)數(shù)。b,開(kāi)啟外部中斷,配置沿觸發(fā)中斷,count++計(jì)數(shù),再開(kāi)啟定時(shí)器x的更新中斷,定時(shí)一定時(shí)間進(jìn)更新中斷,讀取count值,此為脈沖個(gè)數(shù)。 3.計(jì)算一路信號(hào)的頻率,可以選擇定時(shí)器的CH1或CH2(不可同時(shí)計(jì)算兩路頻率,否則計(jì)算出的頻率是后初始化的那個(gè)通道代表的信號(hào)頻率。當(dāng)然,要同時(shí)也可以,每次得到頻率后切換通道,將數(shù)據(jù)通過(guò)DMA取走即可),使用PWM輸入捕獲模式,使用上升沿觸發(fā)。而CH3和CH4通道則不行,如圖2所示,只有紅線所指的4個(gè)信號(hào)連在了從模式控制器上。所以,對(duì)于3和4通道,計(jì)數(shù)器的值不可能在接受到信號(hào)上升沿時(shí)候,有復(fù)位這個(gè)動(dòng)作。 file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image004.jpg --------------------- 原文:https://blog.csdn.net/qq_29413829/article/details/52743273 版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請(qǐng)附上博文鏈接!
|