標(biāo)題: stm32定時器pwm模式輸入捕獲 [打印本頁]
作者: sunok1234 時間: 2018-11-5 19:36
標(biāo)題: stm32定時器pwm模式輸入捕獲
stm32定時器pwm模式輸入捕獲
stm32中的定時器,除了TIM6和TIM7,其他定時器都有輸入捕獲功能。這種模式通常用在對輸入信號頻率frequency、占空比duty、高低脈寬的計(jì)算中,具有很廣泛的用途。
STM32的輸入捕獲,簡單的說就是通過檢測TIMx_CHx上的邊沿信號,在邊沿信號發(fā)生跳變(比如上升沿/下降沿)的時候,將當(dāng)前定時器的值(TIMx_CNT)存放到對應(yīng)的通道的捕獲/比較寄存(TIMx_CCRx)里面,完成一次捕獲。同時還可以配置捕獲時是否觸發(fā)中斷/DMA 等。
PWM模式捕獲方法:利用TIM3_CH1作PWM輸出,TIM2_CH2捕獲上述PWM信號,并測出頻率和占空比。設(shè)置PWM頻率為1KHz,占空比50%。
具體步驟:
1. 為了實(shí)現(xiàn)PWM輸入捕獲,TIM2占用了2個通道。第2通道的電平變化會被第一通道和第二通道引腳檢測到,其中第一通道被設(shè)置為從機(jī)模式(如何快速判別主從機(jī)模式,規(guī)則如下:如果設(shè)置的是第二通道作為PWM輸入捕獲,則剩余的第一通道都為從機(jī),反之亦然)。
2. 假設(shè)輸入的PWM從低電平開始跳變,在第一個上升沿到來時,1,2通道同時檢測到上升沿。而從機(jī)設(shè)置為復(fù)位模式,所以將TIM2的計(jì)數(shù)值復(fù)位至0,此時不會產(chǎn)生一個中斷請求。
3. 下一個到來的電平是下降沿,此時通道1發(fā)生捕獲事件,將計(jì)數(shù)值存入通道1的CCR1里。
4. 然后是第二個上升沿到來后,此時通道2發(fā)生捕獲事件,將此時的計(jì)數(shù)值存入通道2的CCR2里。復(fù)位模式此時又將TIM2計(jì)數(shù)值復(fù)位至0,等待第二個下降沿到來。
5. 一次捕獲過程完成,則PWM的頻率f=72M/CCR2;占空比:duty=(CCR1/CCR2)X100%
注:
PWM輸入模式時,用到兩個通道(一般用TIMx_CH1或TIMx_CH2),只給其中一個通道分配gpio時鐘即可,另一個在內(nèi)部使用。給一個通道分配gpio時鐘后,需要設(shè)置另一個為從機(jī)且復(fù)位模式。(例如使用ch2,ch1就得設(shè)置成從機(jī)模式)。當(dāng)一個輸入信號(TI1或TI2)來臨時,主通道捕獲上升沿,從機(jī)捕獲下降沿。
在CH2通道中:
TI2FP1和TI2FP2都來自同一信號TI2 的邊沿檢測,信號相同,同一個TIx輸入映射了兩個ICx信號。
TI2FP1和TI2FP2可以分別由連接到的ICx(IC1或是IC2)相對應(yīng)的控制寄存器設(shè)為上升沿或是下降沿觸發(fā),這兩個ICx信號分別在相反的極性邊沿有效。如果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(); //配置時鐘
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;//在捕獲輸入上每探測到一個邊沿執(zhí)行一次捕獲
TIM_ICInitStructure.TIM_ICFilter=0;//濾波設(shè)置,經(jīng)歷幾個周期跳變認(rèn)定波形穩(wěn)定。(采樣高電平,只有連續(xù)采集到N個電平是高電平時才認(rèn)為是有效的,否則低于N個時認(rèn)為是無效的,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ā)信號上升沿重新初始化計(jì)數(shù)器并產(chǎn)生一個更新信號(上升沿一到,TIM2->CNT被清零,每次上升沿來到,CNT都會被清零)
TIM_SelectMasterSlaveMode(TIM2,TIM_MasterSlaveMode_Enable);//啟動定時器的被動觸發(fā)
TIM_ITConfig(TIM2,TIM_IT_CC2,ENABLE);//捕獲中斷打開
TIM_ClearFlag(TIM2,TIM_IT_CC2);//清除標(biāo)志位
TIM_Cmd(TIM2,ENABLE);//使能定時器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;//時鐘分割
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)試程序可用。頻率和占空比都對。頻率的設(shè)置不要太高,因?yàn)?/font>printf函數(shù)發(fā)數(shù)所需時間較多,兩次捕獲的時間間隔短的話可能使printf不能及時地送出數(shù)據(jù),造成數(shù)據(jù)被刷新。更改方法,使用:USART_SendData();函數(shù)發(fā)數(shù)。
其他應(yīng)用:
1.測量高電平時間:a,上文中的CCR1就是高電平時間;b,當(dāng)使用一個通道CH1時,先將觸發(fā)沿選為為上升沿,產(chǎn)生捕獲中斷,讀取CCR1中的內(nèi)容,再改變觸發(fā)沿為下降沿,下降沿到來時捕獲,再次讀出CCR1的內(nèi)容,兩次相減為高電平時間。
2.測量脈沖個數(shù):a,開啟定時器1的捕獲中斷,捕獲信號邊沿(上升沿或下降沿)進(jìn)中斷,count++計(jì)數(shù),再開啟定時器2的更新中斷,定時一定時間進(jìn)更新中斷,讀取count值,此為脈沖個數(shù)。b,開啟外部中斷,配置沿觸發(fā)中斷,count++計(jì)數(shù),再開啟定時器x的更新中斷,定時一定時間進(jìn)更新中斷,讀取count值,此為脈沖個數(shù)。
3.計(jì)算一路信號的頻率,可以選擇定時器的CH1或CH2(不可同時計(jì)算兩路頻率,否則計(jì)算出的頻率是后初始化的那個通道代表的信號頻率。當(dāng)然,要同時也可以,每次得到頻率后切換通道,將數(shù)據(jù)通過DMA取走即可),使用PWM輸入捕獲模式,使用上升沿觸發(fā)。而CH3和CH4通道則不行,如圖2所示,只有紅線所指的4個信號連在了從模式控制器上。所以,對于3和4通道,計(jì)數(shù)器的值不可能在接受到信號上升沿時候,有復(fù)位這個動作。
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)載請附上博文鏈接!
作者: lizhimin 時間: 2018-11-6 09:10
受用了
作者: lizhimin 時間: 2018-11-6 09:11
不錯不粗
作者: zyluglugl 時間: 2021-8-24 08:51
我最近在學(xué)習(xí)輸入捕獲頻率,真的是謝謝了!
歡迎光臨 (http://www.torrancerestoration.com/bbs/) |
Powered by Discuz! X3.1 |