一、輸入捕獲
1.簡介
-
IC(Input Capture)輸入捕獲輸入
-
捕獲模式下,當通道輸入引腳出現指定電平跳變時,當前CNT的值將被鎖存到CCR中,可用于測量PWM波形的頻率、占空比、脈沖間隔、電平持續時間等參數
-
每個高級定時器和通用定時器都擁有4個輸入捕獲通道
-
可配置為PWMI模式,同時測量頻率和占空比
-
可配合主從觸發模式,實現硬件全自動測量
2.頻率測量
- 測頻法適合測量高頻信號,測周法適合測量低頻信號。測頻法要求信號頻率要稍微高一些。那對于測周法就要求信號頻率低一些了,低頻信號周期比較長,計次就會比較多,有助于減小誤差。
- 對應圖上,當待測信號頻率小于中介頻率時,測周法誤差更小,選用測周法更合適。當待測信號頻率大于中間頻率時,測頻法誤差更小,選用測頻法更合適。
3.輸入捕獲通道
4.主從觸發模式
- 主從觸發模式就是主模式、從模式和觸發源選擇這三個功能的簡稱。
- 其中主模式可以將定時器內部的信號映射到TRGO引腳。用于觸發別的外設。所以這部分叫做主模式。
- 從模式,就是接收其他外設或者自身外設的一些信號,用于控制自身定時器的運行,也就是被別的信號控制,所以這部分叫從模式。
- 觸發源選擇就是選擇從模式的觸發信號源的,你可以認為它是從模式的一部分。觸發源選擇指定的一個信號,得到TRGI,TRGI去觸發從模式,從模式可以在這個列表里選擇一項操作來自動執行。
5.輸入捕獲基本結構
6.PWMI基本結構
- 配置為PWMI模式,同時測量頻率和占空比。這個PWM模式就是PWM的輸入模式,是專門為測量PWM頻率和占空比設計的。
- PWM模式和主從觸發模式設計的非常巧妙,把這兩個功能結合起來測量頻率占空比,就是硬件全自動執行。軟件不需要進行任何干預,也不需要進行中斷,需要測量的時候直接讀取CCR計算器,極大的減輕了軟件的壓力。
二、輸入捕獲模式測頻率
1.接線圖
2.代碼
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
#include "IC.h"int main(void)
{/*模塊初始化*/OLED_Init(); //OLED初始化PWM_Init(); //PWM初始化IC_Init(); //輸入捕獲初始化/*顯示靜態字符串*/OLED_ShowString(1, 1, "Freq:00000Hz"); //1行1列顯示字符串Freq:00000Hz/*使用PWM模塊提供輸入捕獲的測試信號*/PWM_SetPrescaler(720 - 1); //PWM頻率Freq = 72M / (PSC + 1) / 100PWM_SetCompare1(50); //PWM占空比Duty = CCR / 100while (1){OLED_ShowNum(1, 6, IC_GetFreq(), 5); //不斷刷新顯示輸入捕獲測得的頻率}
}
IC.c
#include "stm32f10x.h" // Device header/*** 函 數:輸入捕獲初始化* 參 數:無* 返 回 值:無*/
void IC_Init(void)
{/*開啟時鐘*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //開啟TIM3的時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //開啟GPIOA的時鐘/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_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); //將PA6引腳初始化為上拉輸入/*配置時鐘源*/TIM_InternalClockConfig(TIM3); //選擇TIM3為內部時鐘,若不調用此函數,TIM默認也為內部時鐘/*時基單元初始化*/TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //定義結構體變量TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //時鐘分頻,選擇不分頻,此參數用于配置濾波器時鐘,不影響時基單元功能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_TimeBaseInit,配置TIM3的時基單元/*輸入捕獲初始化*/TIM_ICInitTypeDef TIM_ICInitStructure; //定義結構體變量TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; //選擇配置定時器通道1TIM_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_ICInit,配置TIM3的輸入捕獲通道/*選擇觸發源及從模式*/TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1); //觸發源選擇TI1FP1TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset); //從模式選擇復位//即TI1產生上升沿時,會觸發CNT歸零/*TIM使能*/TIM_Cmd(TIM3, ENABLE); //使能TIM3,定時器開始運行
}/*** 函 數:獲取輸入捕獲的頻率* 參 數:無* 返 回 值:捕獲得到的頻率*/
uint32_t IC_GetFreq(void)
{return 1000000 / (TIM_GetCapture1(TIM3) + 1); //測周法得到頻率fx = fc / N,這里不執行+1的操作也可
}
IC.c
#ifndef __IC_H
#define __IC_Hvoid IC_Init(void);
uint32_t IC_GetFreq(void);#endif
3.相關API
1. void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
功能:使能或禁用 APB1 總線上的外設時鐘
參數:
-
RCC_APB1Periph
:選擇 APB1 外設(x 為外設枚舉值)
- 可選值(部分):
RCC_APB1Periph_TIM2
:TIM2 定時器RCC_APB1Periph_TIM3
:TIM3 定時器(輸入捕獲用)RCC_APB1Periph_I2C1
:I2C1 接口
- 可選值(部分):
-
NewState
:時鐘使能狀態
- 可選值:
ENABLE
:使能時鐘DISABLE
:禁用時鐘
返回值:無
- 可選值:
2. void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
功能:初始化 GPIO 引腳的模式、速度等參數
參數:
-
GPIOx
:選擇 GPIO 端口(x 為端口字母)
- 可選值:
GPIOA
、GPIOB
、GPIOC
等(如 PA6 對應GPIOA
)
- 可選值:
-
GPIO_InitStruct
:指向 GPIO 配置結構體的指針
-
結構體成員(部分):
-
GPIO_Mode
:引腳模式
- 可選值:
GPIO_Mode_IPU
:上拉輸入(輸入捕獲用)GPIO_Mode_AF_PP
:復用推挽輸出
- 可選值:
-
GPIO_Pin
:引腳號
- 可選值:
GPIO_Pin_0
~GPIO_Pin_15
(如 PA6 對應GPIO_Pin_6
)
- 可選值:
-
GPIO_Speed
:輸出速度(輸入模式無效)
- 可選值:
GPIO_Speed_10MHz
、GPIO_Speed_50MHz
返回值:無
- 可選值:
-
-
3. void TIM_InternalClockConfig(TIM_TypeDef* TIMx);
功能:選擇定時器的時鐘源為內部時鐘(默認配置)
參數:
-
TIMx
:選擇定時器(x 為定時器編號)
- 可選值:
TIM2
、TIM3
(輸入捕獲用)、TIM4
等
返回值:無
- 可選值:
4. void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
功能:配置定時器的時基參數(計數周期、分頻等)
參數:
-
TIMx
:選擇定時器
- 可選值:
TIM3
(輸入捕獲用)、TIM2
、TIM4
等
- 可選值:
-
TIM_TimeBaseInitStruct
:指向時基配置結構體的指針
-
結構體成員(部分):
-
TIM_Period
:自動重裝值(ARR)
- 可選值:
- 0~65535(16 位計數器,如
65535
對應最大周期)
- 0~65535(16 位計數器,如
- 可選值:
-
TIM_Prescaler
:預分頻值(PSC)
- 可選值:
- 0~65535(如
71
對應 72 分頻,計數器時鐘 1MHz)
- 0~65535(如
- 可選值:
-
TIM_CounterMode
:計數模式
- 可選值:
TIM_CounterMode_Up
:向上計數(輸入捕獲用)TIM_CounterMode_Down
:向下計數
返回值:無
- 可選值:
-
-
5. void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);
功能:初始化定時器的輸入捕獲通道參數
參數:
-
TIMx
:選擇定時器
- 可選值:
TIM3
(輸入捕獲用)、TIM2
、TIM4
等
- 可選值:
-
TIM_ICInitStruct
:指向輸入捕獲配置結構體的指針
-
結構體成員(部分):
-
TIM_Channel
:捕獲通道
- 可選值:
TIM_Channel_1
:通道 1(輸入捕獲用)TIM_Channel_2
~TIM_Channel_4
- 可選值:
-
TIM_ICPolarity
:捕獲極性
- 可選值:
TIM_ICPolarity_Rising
:上升沿捕獲(輸入捕獲用)TIM_ICPolarity_Falling
:下降沿捕獲
- 可選值:
-
TIM_ICFilter
:輸入濾波器參數
- 可選值:
- 0x0~0xF(如
0xF
表示最強濾波,抗干擾)
返回值:無
- 0x0~0xF(如
- 可選值:
-
-
6. void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TS);
功能:選擇定時器從模式的觸發源
參數:
-
TIMx
:選擇定時器
- 可選值:
TIM3
(輸入捕獲用)、TIM2
、TIM4
等
- 可選值:
-
TIM_TS
:觸發源選擇
- 可選值(輸入捕獲相關):
TIM_TS_TI1FP1
:使用通道 1 的濾波后信號(輸入捕獲用)TIM_TS_TI2FP2
:使用通道 2 的濾波后信號
返回值:無
- 可選值(輸入捕獲相關):
7. void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode);
功能:配置定時器的從模式行為(如復位、門控)
參數:
-
TIMx
:選擇定時器
- 可選值:
TIM3
(輸入捕獲用)、TIM2
、TIM4
等
- 可選值:
-
TIM_SlaveMode
:從模式類型
- 可選值:
TIM_SlaveMode_Reset
:復位模式(輸入捕獲用,觸發時計數器歸零)TIM_SlaveMode_Gated
:門控模式(觸發有效時計數器運行)
返回值:無
- 可選值:
8. void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);
功能:啟動或停止定時器計數
參數:
-
TIMx
:選擇定時器
- 可選值:
TIM3
(輸入捕獲用)、TIM2
、TIM4
等
- 可選值:
-
NewState
:定時器使能狀態
- 可選值:
ENABLE
:啟動定時器(輸入捕獲用)DISABLE
:停止定時器
返回值:無
- 可選值:
9. uint16_t TIM_GetCapture1(TIM_TypeDef* TIMx);
功能:獲取定時器通道 1 的捕獲值(CCR1)
參數:
-
TIMx
:選擇定時器
- 可選值:
TIM3
(輸入捕獲用)、TIM2
、TIM4
等
返回值:
- 可選值:
-
通道 1 的捕獲寄存器值(0~65535,對應兩次上升沿間的計數值)
現象:測量波形的輸入口是PA6,用一根線把PA0和PA6連在一起,這樣就能測量自己PWM模塊產生波形的頻率。
三、PWMI模式測頻率占空比
1.接線圖
2.代碼
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
#include "IC.h"int main(void)
{/*模塊初始化*/OLED_Init(); //OLED初始化PWM_Init(); //PWM初始化IC_Init(); //輸入捕獲初始化/*顯示靜態字符串*/OLED_ShowString(1, 1, "Freq:00000Hz"); //1行1列顯示字符串Freq:00000HzOLED_ShowString(2, 1, "Duty:00%"); //2行1列顯示字符串Duty:00%/*使用PWM模塊提供輸入捕獲的測試信號*/PWM_SetPrescaler(720 - 1); //PWM頻率Freq = 72M / (PSC + 1) / 100PWM_SetCompare1(50); //PWM占空比Duty = CCR / 100while (1){OLED_ShowNum(1, 6, IC_GetFreq(), 5); //不斷刷新顯示輸入捕獲測得的頻率OLED_ShowNum(2, 6, IC_GetDuty(), 2); //不斷刷新顯示輸入捕獲測得的占空比}
}
IC.c
#include "stm32f10x.h" // Device header/*** 函 數:輸入捕獲初始化* 參 數:無* 返 回 值:無*/
void IC_Init(void)
{/*開啟時鐘*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //開啟TIM3的時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //開啟GPIOA的時鐘/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_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); //將PA6引腳初始化為上拉輸入/*配置時鐘源*/TIM_InternalClockConfig(TIM3); //選擇TIM3為內部時鐘,若不調用此函數,TIM默認也為內部時鐘/*時基單元初始化*/TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //定義結構體變量TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //時鐘分頻,選擇不分頻,此參數用于配置濾波器時鐘,不影響時基單元功能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_TimeBaseInit,配置TIM3的時基單元/*PWMI模式初始化*/TIM_ICInitTypeDef TIM_ICInitStructure; //定義結構體變量TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; //選擇配置定時器通道1TIM_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_PWMIConfig(TIM3, &TIM_ICInitStructure); //將結構體變量交給TIM_PWMIConfig,配置TIM3的輸入捕獲通道//此函數同時會把另一個通道配置為相反的配置,實現PWMI模式/*選擇觸發源及從模式*/TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1); //觸發源選擇TI1FP1TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset); //從模式選擇復位//即TI1產生上升沿時,會觸發CNT歸零/*TIM使能*/TIM_Cmd(TIM3, ENABLE); //使能TIM3,定時器開始運行
}/*** 函 數:獲取輸入捕獲的頻率* 參 數:無* 返 回 值:捕獲得到的頻率*/
uint32_t IC_GetFreq(void)
{return 1000000 / (TIM_GetCapture1(TIM3) + 1); //測周法得到頻率fx = fc / N,這里不執行+1的操作也可
}/*** 函 數:獲取輸入捕獲的占空比* 參 數:無* 返 回 值:捕獲得到的占空比*/
uint32_t IC_GetDuty(void)
{return (TIM_GetCapture2(TIM3) + 1) * 100 / (TIM_GetCapture1(TIM3) + 1); //占空比Duty = CCR2 / CCR1 * 100,這里不執行+1的操作也可
}
IC.h
#ifndef __IC_H
#define __IC_Hvoid IC_Init(void);
uint32_t IC_GetFreq(void);
uint32_t IC_GetDuty(void);#endif
現象:
- 硬件連接:
PWM 輸出(PA8) → 輸入捕獲引腳(PA6)
OLED 顯示屏通過 I2C 接口連接(通常為 PB6/PB7)
- 參數配置:
PWM 頻率:72MHz / (720) / 100 = 1kHz
PWM 占空比:50 / 100 = 50%
- 輸入捕獲配置:
TIM3 通道 1(PA6)配置為上升沿捕獲,用于測量頻率和占空比
從模式設為復位模式,確保每次上升沿觸發計數器歸零
2. 實時顯示效果
OLED 顯示內容:
Freq:00000Hz
Duty:00%