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相同。
具體程序:
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通道,計數器的值不可能在接受到信號上升沿時候,有復位這個動作。
上一篇:STM32+MS5611測氣壓溫度例程詳解,測試無誤
下一篇:STM32 TIM1 做PWM輸出問題
推薦閱讀
史海拾趣
C&D公司自創立之初,就專注于電子技術的研發與創新。創始團隊憑借深厚的行業經驗和前瞻性的市場洞察力,成功開發出一系列具有競爭力的電子產品。在市場競爭激烈的背景下,C&D公司憑借卓越的產品性能和精準的市場定位,迅速在行業中嶄露頭角。
星海鋼琴集團有限公司的起點可以追溯到1949年成立的北京鋼琴廠。在那個特殊的年代,陳艾生等紅軍戰士為實現張貞黻的遺愿,即“北平解放后,一定要辦起我們自己的樂器廠”,他們四處奔走,多方求助,最終成功創辦了星海鋼琴廠。從最初的手工制作到現代化生產線的建立,星海鋼琴不斷傳承和發展,成為中國乃至世界知名的鋼琴品牌。
宗旨:培養EE友們動手實踐能力、提高和RF應用、MCU編程開發能力等。 項目:智能家庭遙控器 主芯片:SI4020/SI4021 遙控距離:>15米。 電池規格:3節干電池供電。 電池使用壽命:半年以上。 成本控制:接收器+發送器共不超過60 RMB(DIY10套, ...… 查看全部問答∨ |
|
XP Embedded是微軟Windows Embedded產品線中非常重要的一環,不過比起大名鼎鼎的Windows Embedded CE,XPe顯得過于低調了。在接下來的一段時間里,我希望能夠用六篇的篇幅來描述一下XPe的整個開發過程。這個系列文章主要是針對有Windows編程經驗, ...… 查看全部問答∨ |
|
module signalcreat(clk,out); input clk; reg[5:0] data; reg a; output out; reg out; initial &nbs ...… 查看全部問答∨ |
Vcc為3.8V,P2口輸出為2.75V[空載,直接萬用表量的]一般各位用的輸出電平是多少? [ 本帖最后由 njkzjk 于 2011-7-12 12:50 編輯 ]… 查看全部問答∨ |
作者:武漢華嵌技術部 本文主要介紹了怎么使用QTextEdit控件實現類似QQ聊天對話框的效果,包括令對話框顯示不同的字體、顏色,實現QQ震動效果和QQ表情效果(即在QTextEdit中顯示圖片)。Demo運行的界面如下圖所示: 點擊相關按鈕可以改 ...… 查看全部問答∨ |
在學AVR,寫定時器中斷的程序時遇到問題,程序在計數溢出后沒有跳進中斷服務程序中。 我用的是AVR STUDIO6 編程,選的是ATMEGA88PA芯片,用STUDIO6自帶的軟件仿真。單步運行時,發現計數溢出后程序沒有進入中斷。 求大神解惑,附上程序。 #inclu ...… 查看全部問答∨ |
北航新書 <<MSP430FRAM鐵電單片機原理及C程序設計>> 北航新書:http://item.jd.com/11084937.html 《MSP430FRAM鐵電單片機原理及C程序設計》詳細介紹了TI公司的MSP430FRAM系列單片機的特性和優勢,主要內容包括MSP430FRAM單片機的基礎部分和實際應用設計部分。其中,基礎部分包括通用FRAM鐵電概述、T ...… 查看全部問答∨ |
本帖最后由 qwqwqw2088 于 2014-7-24 08:59 編輯 “出門手機電池沒有充滿或者晚上要睡覺電池充了90%,是否需要繼續充滿?電池(手機鋰電池)究竟是充不滿傷害大,還是充過量傷害大?” 還有”怎樣判斷電池是充滿了?,,,” 上述問 ...… 查看全部問答∨ |