輸入捕獲簡介:
????????IC(Input Capture)輸入捕獲
????????輸入捕獲模式下,當通道輸入引腳出現指定電平跳變時,當前CNT的值將被鎖存到CCR中,可用于測量PWM波形的頻率、占空比、脈沖間隔、電平持續時間等參數
????????每個高級定時器和通用定時器都擁有4個輸入捕獲通道
????????可配置為PWMI模式,同時測量頻率和占空比
????????可配合主從觸發模式,實現硬件全自動測量
頻率測量:
輸入捕獲基本結構
主從觸發模式:
接線圖:
代碼配置:
實現功能在屏幕上顯示頻率,頻率通過ARR與PSC共同控制,而ARR也涉及到占空比的改變,所以我們選擇更改PSC,在初始化后單獨寫一個函數更改PSC
需要調用到這個函數,單獨用來寫入PSC的函數
void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode);
void pWM_SetPrescaler(uint16_t Prescaler)
{TIM_PrescalerConfig(TIM2, Prescaler, TIM_PSCReloadMode_Immediate);}
函數介紹:
用結構體配置輸入捕獲單元的函數
注意:輸入捕獲與輸出比較都有4個通道,OCInit,4個通道每個通道各占一個函數,而ICInit,4個通道是共用一個函數的,在結構體里會有一個參數,來配置具體哪個通道,因為可能有交叉通道的配置,所以函數合在一起比較方便
void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);
這個函數與上一個函數類似,都是用于初始化輸入捕獲單元的,但是上一個函數只是單一的配置一個通道,這個函數可以快速配置兩個通道
void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);
這個函數可以給輸入捕獲結構體賦一個初始值
void TIM_ICStructInit(TIM_ICInitTypeDef* TIM_ICInitStruct);
下面三個對應主從觸發模式:
選擇輸入觸發源TRGI
void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);
選擇輸出觸發源TRGO
void TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TRGOSource);
選擇從模式
void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode);
下面四個函數,分別單獨配置通道1、2、3、4的分頻器
void TIM_SetIC1Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC2Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC3Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC4Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
分別讀取4個通道的CCR,這4個函數和SetCompare1、2、3、4是對應的,輸出比較模式下,CCR是只寫的,要用SetCompare寫入,輸入捕獲模式下,CCR是只讀的,要用GetCapture讀出
uint16_t TIM_GetCapture1(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture2(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture3(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture4(TIM_TypeDef* TIMx);
輸入捕獲代碼配置
????????根據結構圖配置
1.定義結構體變量
定義GPIO、TimeBase時基單元、IC輸入捕獲單元結構體變量
//定義結構體變量
GPIO_InitTypeDef GPIO_InitStructure;//定義GPIO結構體變量
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//定義時基單元結構體變量
TIM_ICInitTypeDef TIM_ICInitStructure; //定義IC結構體變量
2.RCC開啟時鐘
把GPIO和TIM的時鐘打開
//RCC開啟時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//開啟GPIO A族時鐘
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//開啟TIM3時鐘
3.GPIO初始化
把GPIO配置成輸入模式,一般選擇上拉輸入或者浮空輸入模式,這里選擇TIM3_CH1通道,根據引腳圖為PA6,所以這次配置這個引腳,模式選擇上拉輸入
//配置GPIOGPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉輸入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;//配置引腳
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);
4.配置時基單元
讓CNT計數器在內部時鐘的驅動下自增運行,這里的周期給到最大,PSC的值給72 - 1,這樣標準頻率就是72M / 72 = 1MHz 方便計算。
//配置時基單元TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//選擇向上計數
TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1; //ARR周期的值
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //預分頻器PSC的值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重復計數器的值TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
5.配置輸入捕獲單元
包括濾波器、極性、直連通道還是交叉通道、分頻器這些參數
//配置輸入捕獲單元TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;//選擇通道 我們這里選擇的是TIM3的CH1
TIM_ICInitStructure.TIM_ICFilter = 0xF;//選擇輸入捕獲的濾波器
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//邊沿檢測極性選擇 選擇上升沿觸發
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//分頻器
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//選擇觸發信號從那個引腳輸入TIM_ICInit(TIM3, &TIM_ICInitStructure);
6.選擇從模式的觸發源
觸發源選擇為TI1FP1,這里調用一個庫函數,給一個參數就行
//配置主從模式觸發源
TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);//配置TRIG的觸發源
7.選擇觸發之后執行的操作
執行Reset操作,這里也是調用一個庫函數就行了
TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);//配置從模式為Reset
最后調用TIM_CMD函數開啟定時器,當我們需要讀取最新一個周期的頻率時,直接讀取CCR寄存器,然后按照fc/N,計算一下就行了。
//啟動定時器
TIM_Cmd(TIM3,ENABLE);
整體代碼:
void IC_Init(void)
{//定義結構體變量GPIO_InitTypeDef GPIO_InitStructure;//定義GPIO結構體變量TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//定義時基單元結構體變量TIM_ICInitTypeDef TIM_ICInitStructure; //定義IC結構體變量//RCC開啟時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//開啟GPIO A族時鐘RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//開啟TIM3時鐘//配置GPIOGPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉輸入GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;//配置引腳GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);//配置時基單元TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//選擇向上計數TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1; //ARR周期的值TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //預分頻器PSC的值TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重復計數器的值TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);//配置輸入捕獲單元TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;//選擇通道 我們這里選擇的是TIM3的CH1TIM_ICInitStructure.TIM_ICFilter = 0xF;//選擇輸入捕獲的濾波器TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//邊沿檢測極性選擇 選擇上升沿觸發TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//分頻器TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//選擇觸發信號從那個引腳輸入TIM_ICInit(TIM3, &TIM_ICInitStructure);//配置主從模式觸發源TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);//配置TRIG的觸發源TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);//配置從模式為Reset//啟動定時器TIM_Cmd(TIM3,ENABLE);}
功能代碼:
????????測量頻率,在頻幕上顯示
uint32_t IC_GetFreg(void)
{return 1000000 / (TIM_GetCapture1(TIM3) + 1);}
主函數:
#include "IC.h"
int main(void)
{LED_Init();OLED_Init();PWM_Init();IC_Init();pWM_SetPrescaler(720 - 1); //Freg = 72M / (PSC + 1) / 100PWM_SetComPer(50); //Duty = CCR / 100OLED_ShowString(1, 1, "Freg:00000Hz");while(1){OLED_ShowNum(1, 6, IC_GetFreg(), 5);}}