日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

stm32 输入捕获 测量脉宽

發(fā)布時(shí)間:2025/3/12 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 stm32 输入捕获 测量脉宽 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

選用通用定時(shí)器TIM5的CH1。

PA0接一個(gè)按鍵,默認(rèn)接GND,當(dāng)按鍵按下時(shí),IO口被拉高,此時(shí),可利用定時(shí)器的輸入捕獲功能,測(cè)量按鍵按下的這段高電平的時(shí)間。

宏定義方便程序升級(jí)、移植,舉個(gè)例子:

輸入捕獲通道 GPIO 初始化,里面有一個(gè)GENERAL_TIM_CH1_GPIO_CLK,這個(gè)東西是個(gè)宏定義。使用不同GPIO的時(shí)候,只需要修改頭文件里面的宏定義,不需要修改這個(gè)函數(shù)。

// TIM 輸入捕獲通道GPIO相關(guān)宏定義 #define GENERAL_TIM_CH1_GPIO_CLK RCC_APB2Periph_GPIOA static void GENERAL_TIM_GPIO_Config(void) {GPIO_InitTypeDef GPIO_InitStructure;// 輸入捕獲通道 GPIO 初始化RCC_APB2PeriphClockCmd(GENERAL_TIM_CH1_GPIO_CLK, ENABLE);GPIO_InitStructure.GPIO_Pin = GENERAL_TIM_CH1_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GENERAL_TIM_CH1_PORT, &GPIO_InitStructure); }

下面是宏定義。

#ifndef __BSP_GENERALTIME_H #define __BSP_GENERALTIME_H#include "stm32f10x.h"/************通用定時(shí)器TIM參數(shù)定義,只限TIM2、3、4、5************/ // 當(dāng)使用不同的定時(shí)器的時(shí)候,對(duì)應(yīng)的GPIO是不一樣的,這點(diǎn)要注意 // 我們這里默認(rèn)使用TIM5#define GENERAL_TIM TIM5 #define GENERAL_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd #define GENERAL_TIM_CLK RCC_APB1Periph_TIM5 #define GENERAL_TIM_PERIOD 0XFFFF #define GENERAL_TIM_PSC (72-1)// TIM 輸入捕獲通道GPIO相關(guān)宏定義 #define GENERAL_TIM_CH1_GPIO_CLK RCC_APB2Periph_GPIOA #define GENERAL_TIM_CH1_PORT GPIOA #define GENERAL_TIM_CH1_PIN GPIO_Pin_0 #define GENERAL_TIM_CHANNEL_x TIM_Channel_1// 中斷相關(guān)宏定義 #define GENERAL_TIM_IT_CCx TIM_IT_CC1 #define GENERAL_TIM_IRQ TIM5_IRQn #define GENERAL_TIM_INT_FUN TIM5_IRQHandler// 獲取捕獲寄存器值函數(shù)宏定義 #define GENERAL_TIM_GetCapturex_FUN TIM_GetCapture1 // 捕獲信號(hào)極性函數(shù)宏定義 #define GENERAL_TIM_OCxPolarityConfig_FUN TIM_OC1PolarityConfig// 測(cè)量的起始邊沿 #define GENERAL_TIM_STRAT_ICPolarity TIM_ICPolarity_Rising // 測(cè)量的結(jié)束邊沿 #define GENERAL_TIM_END_ICPolarity TIM_ICPolarity_Falling// 定時(shí)器輸入捕獲用戶自定義變量結(jié)構(gòu)體聲明 typedef struct { uint8_t Capture_FinishFlag; // 捕獲結(jié)束標(biāo)志位uint8_t Capture_StartFlag; // 捕獲開(kāi)始標(biāo)志位uint16_t Capture_CcrValue; // 捕獲寄存器的值uint16_t Capture_Period; // 自動(dòng)重裝載寄存器更新標(biāo)志 }TIM_ICUserValueTypeDef;extern TIM_ICUserValueTypeDef TIM_ICUserValueStructure;/**************************函數(shù)聲明********************************/ void GENERAL_TIM_Init(void);#endif /* __BSP_GENERALTIME_H */

下面GENERAL_TIM_Mode_Config是定時(shí)器模式配置。

里面初始化了兩個(gè)結(jié)構(gòu)體。

對(duì)于時(shí)基結(jié)構(gòu)體:

1.GENERAL_TIM_PERIOD配置ARR寄存器的值,決定計(jì)數(shù)器一個(gè)周期的計(jì)數(shù)時(shí)間,默認(rèn)配置為0XFFFF(65535),即最大。


自動(dòng)重裝載寄存器ARR:16位寄存器,這里面裝著計(jì)數(shù)器能計(jì)數(shù)的最大數(shù)值。當(dāng)計(jì)數(shù)到這個(gè)值的時(shí)候,如果使能了中斷,定時(shí)器就產(chǎn)生溢出中斷。

CNT是16位的計(jì)數(shù)器,只能往上計(jì)數(shù),最大計(jì)數(shù)值為65535。當(dāng)計(jì)數(shù)達(dá)到自動(dòng)重裝載寄存器的時(shí)候產(chǎn)生更新事件,并清零從頭開(kāi)始計(jì)數(shù)


[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-JOmOfWyS-1646185240167)(stm32 輸入捕獲 測(cè)量脈寬.assets/Snipaste_2022-02-27_10-49-11.png)]

時(shí)鐘源:定時(shí)器時(shí)鐘TIMxCLK,即內(nèi)部時(shí)鐘CK_INT,經(jīng)APB1預(yù)分頻器分頻提供。

APB1預(yù)分頻系數(shù)等于1,頻率不變。

庫(kù)函數(shù)中APB1預(yù)分頻的系數(shù)是2,即PCLK1=36M,所以定時(shí)器時(shí)鐘TIMxCLK=36*2=72M

計(jì)數(shù)器時(shí)鐘CK_CNT

定時(shí)器時(shí)鐘經(jīng)過(guò)PSC預(yù)分頻器后,即CK_CNT,用來(lái)驅(qū)動(dòng)計(jì)數(shù)器計(jì)數(shù)。

PSC是16位的預(yù)分頻器,可以對(duì)定時(shí)器時(shí)鐘TIMxCLK進(jìn)行1~65536之間的任何一個(gè)數(shù)進(jìn)行分頻。CK_CNT=TIMxCLK/(PSC+1)

2.GENERAL_TIM_PSC配置分頻因子,默認(rèn)配置為72-1。可以計(jì)算出計(jì)數(shù)器的計(jì)數(shù)周期為(GENERAL_TIM_PSC+1)/72M=1us。


當(dāng)捕獲通道TIx上出現(xiàn)上升沿時(shí),發(fā)生第一次捕獲。

計(jì)數(shù)器CNT的值,被鎖存到捕獲寄存器CCR中,進(jìn)入捕獲中斷。

輸入捕獲能捕獲的最小的時(shí)間為1us,最長(zhǎng)的時(shí)間為1us *(0Xffff+1)=65536us=65.536ms。

超過(guò)這個(gè)計(jì)數(shù)周期的時(shí)候,產(chǎn)生中斷,然后在中斷里面做額外的處理。

需要記錄好產(chǎn)生了多少次更新中斷,最后把更新時(shí)間加入脈寬時(shí)間里面。


GENERAL_TIM_NVIC_Config是中斷優(yōu)先級(jí)配置。只有一個(gè)中斷源,優(yōu)先級(jí)可以隨便配置。

#include "bsp_GeneralTim.h"// 定時(shí)器輸入捕獲用戶自定義變量結(jié)構(gòu)體定義 TIM_ICUserValueTypeDef TIM_ICUserValueStructure = {0,0,0,0};// 中斷優(yōu)先級(jí)配置 static void GENERAL_TIM_NVIC_Config(void) {NVIC_InitTypeDef NVIC_InitStructure; // 設(shè)置中斷組為0NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); // 設(shè)置中斷來(lái)源NVIC_InitStructure.NVIC_IRQChannel = GENERAL_TIM_IRQ ; // 設(shè)置主優(yōu)先級(jí)為 0NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 設(shè)置搶占優(yōu)先級(jí)為3NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure); }static void GENERAL_TIM_GPIO_Config(void) {GPIO_InitTypeDef GPIO_InitStructure;// 輸入捕獲通道 GPIO 初始化RCC_APB2PeriphClockCmd(GENERAL_TIM_CH1_GPIO_CLK, ENABLE);GPIO_InitStructure.GPIO_Pin = GENERAL_TIM_CH1_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GENERAL_TIM_CH1_PORT, &GPIO_InitStructure); }///* // * 注意:TIM_TimeBaseInitTypeDef結(jié)構(gòu)體里面有5個(gè)成員,TIM6和TIM7的寄存器里面只有 // * TIM_Prescaler和TIM_Period,所以使用TIM6和TIM7的時(shí)候只需初始化這兩個(gè)成員即可, // * 另外三個(gè)成員是通用定時(shí)器和高級(jí)定時(shí)器才有. // *----------------------------------------------------------------------------- // *typedef struct // *{ TIM_Prescaler 都有 // * TIM_CounterMode TIMx,x[6,7]沒(méi)有,其他都有 // * TIM_Period 都有 // * TIM_ClockDivision TIMx,x[6,7]沒(méi)有,其他都有 // * TIM_RepetitionCounter TIMx,x[1,8,15,16,17]才有 // *}TIM_TimeBaseInitTypeDef; // *----------------------------------------------------------------------------- // *//* ---------------- PWM信號(hào) 周期和占空比的計(jì)算--------------- */ // ARR :自動(dòng)重裝載寄存器的值 // CLK_cnt:計(jì)數(shù)器的時(shí)鐘,等于 Fck_int / (psc+1) = 72M/(psc+1) // PWM 信號(hào)的周期 T = ARR * (1/CLK_cnt) = ARR*(PSC+1) / 72M // 占空比P=CCR/(ARR+1)static void GENERAL_TIM_Mode_Config(void) {// 開(kāi)啟定時(shí)器時(shí)鐘,即內(nèi)部時(shí)鐘CK_INT=72MGENERAL_TIM_APBxClock_FUN(GENERAL_TIM_CLK,ENABLE);/*--------------------時(shí)基結(jié)構(gòu)體初始化-------------------------*/ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;// 自動(dòng)重裝載寄存器的值,累計(jì)TIM_Period+1個(gè)頻率后產(chǎn)生一個(gè)更新或者中斷TIM_TimeBaseStructure.TIM_Period=GENERAL_TIM_PERIOD; // 驅(qū)動(dòng)CNT計(jì)數(shù)器的時(shí)鐘 = Fck_int/(psc+1)TIM_TimeBaseStructure.TIM_Prescaler= GENERAL_TIM_PSC; // 時(shí)鐘分頻因子 ,配置死區(qū)時(shí)間時(shí)需要用到TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; // 計(jì)數(shù)器計(jì)數(shù)模式,設(shè)置為向上計(jì)數(shù)TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; // 重復(fù)計(jì)數(shù)器的值,沒(méi)用到不用管TIM_TimeBaseStructure.TIM_RepetitionCounter=0; // 初始化定時(shí)器TIM_TimeBaseInit(GENERAL_TIM, &TIM_TimeBaseStructure);/*--------------------輸入捕獲結(jié)構(gòu)體初始化-------------------*/ TIM_ICInitTypeDef TIM_ICInitStructure;// 配置輸入捕獲的通道,需要根據(jù)具體的GPIO來(lái)配置TIM_ICInitStructure.TIM_Channel = GENERAL_TIM_CHANNEL_x;// 輸入捕獲信號(hào)的極性配置TIM_ICInitStructure.TIM_ICPolarity = GENERAL_TIM_STRAT_ICPolarity;// 輸入通道和捕獲通道的映射關(guān)系,有直連和非直連兩種TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;// 輸入的需要被捕獲的信號(hào)的分頻系數(shù)TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;// 輸入的需要被捕獲的信號(hào)的濾波系數(shù)TIM_ICInitStructure.TIM_ICFilter = 0;// 定時(shí)器輸入捕獲初始化TIM_ICInit(GENERAL_TIM, &TIM_ICInitStructure);// 清除更新和捕獲中斷標(biāo)志位TIM_ClearFlag(GENERAL_TIM, TIM_FLAG_Update|GENERAL_TIM_IT_CCx); // 開(kāi)啟更新和捕獲中斷 TIM_ITConfig (GENERAL_TIM, TIM_IT_Update | GENERAL_TIM_IT_CCx, ENABLE );// 使能計(jì)數(shù)器TIM_Cmd(GENERAL_TIM, ENABLE); }void GENERAL_TIM_Init(void) {GENERAL_TIM_GPIO_Config();GENERAL_TIM_NVIC_Config();GENERAL_TIM_Mode_Config(); }

中斷服務(wù)函數(shù)

輸入捕獲的起始邊沿為GENERAL_TIM_STRAT_ICPolarity,這是一個(gè)宏,默認(rèn)配置為上升沿。

// 測(cè)量的起始邊沿 #define GENERAL_TIM_STRAT_ICPolarity TIM_ICPolarity_Rising

按鍵默認(rèn)接GND,按鍵按下的時(shí)候被拉高,這個(gè)時(shí)候這個(gè)由低到高的上升沿被捕獲到,這是第一次捕獲。

此時(shí)把計(jì)數(shù)器清0,開(kāi)始計(jì)數(shù),同時(shí)把捕獲邊沿改成下降沿捕獲。

第二次進(jìn)入中斷服務(wù)函數(shù)的時(shí)候,說(shuō)明捕獲到下降沿,這個(gè)時(shí)候表示脈寬捕獲完畢。

讀取捕獲寄存器的值,然后可以通過(guò)這個(gè)值算出脈寬的時(shí)間。

最后,把捕獲編譯配置為上升沿,為的是下一次捕獲。

脈寬的時(shí)間超過(guò)了計(jì)數(shù)器的最大計(jì)數(shù)時(shí)間,就會(huì)產(chǎn)生更新中斷,需要記錄產(chǎn)生了多少次更新中斷。

最后算脈寬的時(shí)間的時(shí)候加上更新的時(shí)間。

中斷服務(wù)函數(shù)里面,捕獲結(jié)束標(biāo)志位、捕獲開(kāi)始標(biāo)志位、捕獲寄存器的值、自動(dòng)重裝載更新標(biāo)志,在一個(gè)結(jié)構(gòu)體里面定義。

// 定時(shí)器輸入捕獲用戶自定義變量結(jié)構(gòu)體聲明 typedef struct { uint8_t Capture_FinishFlag; // 捕獲結(jié)束標(biāo)志位uint8_t Capture_StartFlag; // 捕獲開(kāi)始標(biāo)志位uint16_t Capture_CcrValue; // 捕獲寄存器的值uint16_t Capture_Period; // 自動(dòng)重裝載寄存器更新標(biāo)志 }TIM_ICUserValueTypeDef; void GENERAL_TIM_INT_FUN(void) {// 當(dāng)要被捕獲的信號(hào)的周期大于定時(shí)器的最長(zhǎng)定時(shí)時(shí),定時(shí)器就會(huì)溢出,產(chǎn)生更新中斷// 這個(gè)時(shí)候我們需要把這個(gè)最長(zhǎng)的定時(shí)周期加到捕獲信號(hào)的時(shí)間里面去if ( TIM_GetITStatus ( GENERAL_TIM, TIM_IT_Update) != RESET ) { TIM_ICUserValueStructure.Capture_Period ++; TIM_ClearITPendingBit ( GENERAL_TIM, TIM_FLAG_Update ); }// 上升沿捕獲中斷if ( TIM_GetITStatus (GENERAL_TIM, GENERAL_TIM_IT_CCx ) != RESET){// 第一次捕獲if ( TIM_ICUserValueStructure.Capture_StartFlag == 0 ){// 計(jì)數(shù)器清0TIM_SetCounter(GENERAL_TIM, 0 );// 自動(dòng)重裝載寄存器更新標(biāo)志清0TIM_ICUserValueStructure.Capture_Period = 0;// 存捕獲比較寄存器的值的變量的值清0 TIM_ICUserValueStructure.Capture_CcrValue = 0;// 當(dāng)?shù)谝淮尾东@到上升沿之后,就把捕獲邊沿配置為下降沿GENERAL_TIM_OCxPolarityConfig_FUN(GENERAL_TIM, TIM_ICPolarity_Falling);// 開(kāi)始捕獲標(biāo)準(zhǔn)置1 TIM_ICUserValueStructure.Capture_StartFlag = 1; }// 下降沿捕獲中斷else // 第二次捕獲{// 獲取捕獲比較寄存器的值,這個(gè)值就是捕獲到的高電平的時(shí)間的值TIM_ICUserValueStructure.Capture_CcrValue = GENERAL_TIM_GetCapturex_FUN (GENERAL_TIM);// 當(dāng)?shù)诙尾东@到下降沿之后,就把捕獲邊沿配置為上升沿,好開(kāi)啟新的一輪捕獲GENERAL_TIM_OCxPolarityConfig_FUN(GENERAL_TIM, TIM_ICPolarity_Rising);// 開(kāi)始捕獲標(biāo)志清0 TIM_ICUserValueStructure.Capture_StartFlag = 0;// 捕獲完成標(biāo)志置1 TIM_ICUserValueStructure.Capture_FinishFlag = 1; }TIM_ClearITPendingBit (GENERAL_TIM,GENERAL_TIM_IT_CCx); } }

main函數(shù)里面,一些初始化,在一個(gè)while循環(huán)中打印測(cè)量的脈寬時(shí)間。

計(jì)算的時(shí)候,把周期GENERAL_TIMPERIOD和Capture_CcrValue的值都加1后再運(yùn)算

#define GENERAL_TIM_PSC (72-1) //CK_CNT=TIMxCLK/(PSC+1) // TIM 計(jì)數(shù)器的驅(qū)動(dòng)時(shí)鐘,定時(shí)器時(shí)鐘經(jīng)過(guò)PSC預(yù)分頻器后,即CK_CNT,用來(lái)驅(qū)動(dòng)計(jì)數(shù)器計(jì)數(shù)。uint32_t TIM_PscCLK = 72000000 / (GENERAL_TIM_PSC+1);// 自動(dòng)重裝載寄存器的值,累計(jì)TIM_Period+1個(gè)頻率后產(chǎn)生一個(gè)更新或者中斷TIM_TimeBaseStructure.TIM_Period=GENERAL_TIM_PERIOD; #define GENERAL_TIM_PERIOD 0XFFFFuint16_t Capture_CcrValue; // 捕獲寄存器的值uint16_t Capture_Period; // 自動(dòng)重裝載寄存器更新標(biāo)志 /*當(dāng)要被捕獲的信號(hào)的周期大于定時(shí)器的最長(zhǎng)定時(shí)時(shí),定時(shí)器就會(huì)溢出,產(chǎn)生更新中斷 Capture_Period記錄進(jìn)入更新中斷的次數(shù)*/

下面這個(gè)計(jì)算高電平時(shí)間的計(jì)數(shù)器的值,進(jìn)入更新中斷的次數(shù)*(自動(dòng)重裝載寄存器的值+1)+第二次捕獲時(shí),捕獲比較寄存器的值+1。

// 計(jì)算高電平時(shí)間的計(jì)數(shù)器的值time = TIM_ICUserValueStructure.Capture_Period * (GENERAL_TIM_PERIOD+1) + (TIM_ICUserValueStructure.Capture_CcrValue+1);

為什么都要加一呢,是因?yàn)?#xff1a;

計(jì)數(shù)器CNT:CNT是16位的計(jì)數(shù)器,只能往上計(jì)數(shù),最大計(jì)數(shù)值為65535。當(dāng)計(jì)數(shù)達(dá)到自動(dòng)重裝載寄存器的時(shí)候產(chǎn)生更新事件,并清零從頭開(kāi)始計(jì)數(shù)。

計(jì)數(shù)器是從0開(kāi)始計(jì)數(shù)的,0計(jì)數(shù)到65536,就是65537個(gè)數(shù)了。

計(jì)算高電平脈寬時(shí)間:TIM_PscCLK是計(jì)數(shù)頻率,倒數(shù)就是計(jì)一個(gè)數(shù)的周期。

計(jì)數(shù)器的計(jì)數(shù)周期 * 高電平時(shí)間的計(jì)數(shù)器的值=(1/TIM_PscCLK) * time=time/TIM_PscCLK。

printf ( "\r\n測(cè)得高電平脈寬時(shí)間:%d.%d s\r\n",time/TIM_PscCLK,time%TIM_PscCLK );

#include "stm32f10x.h" #include "bsp_led.h" #include "bsp_usart.h" #include "bsp_GeneralTim.h" /*** @brief 主函數(shù)* @param 無(wú) * @retval 無(wú)*/ int main(void) {uint32_t time;// TIM 計(jì)數(shù)器的驅(qū)動(dòng)時(shí)鐘uint32_t TIM_PscCLK = 72000000 / (GENERAL_TIM_PSC+1);/* 串口初始化 */USART_Config();/* 定時(shí)器初始化 */GENERAL_TIM_Init();printf ( "\r\nSTM32 輸入捕獲實(shí)驗(yàn)\r\n" );printf ( "\r\n按下K1,測(cè)試K1按下的時(shí)間\r\n" );while ( 1 ){if(TIM_ICUserValueStructure.Capture_FinishFlag == 1){// 計(jì)算高電平時(shí)間的計(jì)數(shù)器的值time = TIM_ICUserValueStructure.Capture_Period * (GENERAL_TIM_PERIOD+1) + (TIM_ICUserValueStructure.Capture_CcrValue+1);// 打印printf ( "\r\n測(cè)得高電平脈寬時(shí)間:%d.%d s\r\n",time/TIM_PscCLK,time%TIM_PscCLK );TIM_ICUserValueStructure.Capture_FinishFlag = 0; } } }

總結(jié)

以上是生活随笔為你收集整理的stm32 输入捕获 测量脉宽的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。