定時器外部脈沖計數(shù)功能
兩種方法用于在單片機中實現(xiàn)頻率計的功能。
第一種方法是通過定時器來衡量信號的周期,然后將周期轉(zhuǎn)換為頻率。在這種方法中,你可以使用單片機的定時器模塊來測量輸入信號的周期,定時器會產(chǎn)生一個計數(shù)值,你可以根據(jù)這個計數(shù)值來推算出輸入信號的周期,并通過簡單的數(shù)學(xué)運算將周期轉(zhuǎn)換為頻率?!径〞r器捕獲功能】
第二種方法是統(tǒng)計一定時間內(nèi)脈沖的個數(shù)。在這種方法中,你可以使用單片機的輸入捕獲功能來記錄輸入脈沖的次數(shù)。通過在一段固定的時間內(nèi)記錄脈沖的個數(shù),然后將脈沖個數(shù)除以時間,就可以得到頻率值?!径〞r器外部脈沖計數(shù)功能】
本文使用第二種,【定時器外部脈沖計數(shù)功能】。
程序?qū)崿F(xiàn)
TIM1 定時一秒鐘中斷
這里有篇博客介紹:
https://qq742971636.blog.csdn.net/article/details/131387700
TIM2 外部脈沖計數(shù)配置
首先,通過RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE)和RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE)使能了TIM2和GPIOA的時鐘。
然后,使用GPIO_InitStructure結(jié)構(gòu)體對GPIOA的Pin 0進行配置,設(shè)置為輸入模式(GPIO_Mode_IPD)并設(shè)置為下拉模式。這樣可以確保輸入信號的穩(wěn)定性。
接著,初始化定時器TIM2。設(shè)置計數(shù)器自動重裝值為0xFFFF,表示計數(shù)器將在達到該值后重新裝載。預(yù)分頻器被設(shè)為0,時鐘分割被設(shè)置為TIM_CKD_DIV1,即不分割時鐘。計數(shù)模式被設(shè)置為向上計數(shù)模式(TIM_CounterMode_Up)。最后通過TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure)函數(shù)進行初始化。
使用TIM_ITRxExternalClockConfig(TIM2,TIM_TS_ETRF)配置外部觸發(fā)模式,這樣定時器才能根據(jù)外部脈沖信號進行計數(shù)。
使用TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0)配置外部觸發(fā)源的細(xì)節(jié),包括設(shè)置分頻系數(shù)、極性等。這里的參數(shù)都是一些默認(rèn)值。
通過TIM_SetCounter(TIM2, 0)將計數(shù)器的初始值設(shè)置為0。
最后,使用TIM_Cmd(TIM2, ENABLE)使能定時器。
TIM3 PWM產(chǎn)生
這里有篇博客介紹:
https://qq742971636.blog.csdn.net/article/details/131445707
總程序
將TIM3_CH1 PWM引腳PA6接上外部脈沖計數(shù)引腳TIM2_CH1 PA0,電腦接收串口0的輸出,即可看到打印出的頻率數(shù)值。文章來源:http://www.zghlxwxcb.cn/news/detail-514791.html
#include "sys.h"
#include "usart.h"
long freq = 0;//頻率
long freq_cnt = 0;
void TIM2_Cap_Init(u16 arr, u16 psc) //配置 TIM2_CH1_ETR 為外部脈沖計數(shù)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能TIM2時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA時鐘
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PA0 清除之前設(shè)置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 輸入
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA, GPIO_Pin_0); //PA0 下拉
//初始化定時器2 TIM2
TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)定計數(shù)器自動重裝值
TIM_TimeBaseStructure.TIM_Prescaler = psc; //預(yù)分頻器
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設(shè)置時鐘分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數(shù)模式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根據(jù)TIM_TimeBaseInitStruct中指定的參數(shù)初始化TIMx的時間基數(shù)單位
TIM_ITRxExternalClockConfig(TIM2, TIM_TS_ETRF); //配置外部觸發(fā),否則不會計數(shù)
TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0);
TIM_SetCounter(TIM2, 0);
//中斷優(yōu)先級NVIC設(shè)置
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //TIM2中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占優(yōu)先級0級
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //從優(yōu)先級3級
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
TIM_Cmd(TIM2, ENABLE); //使能定時器
}
void TIM2_UP_IRQHandler(void) //TIM2中斷
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET) //溢出中斷
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除中斷標(biāo)志
freq_cnt++; //freq_cnt加1
}
}
//初始化定時器為中斷觸發(fā)
void TIM1_Init(u16 arr, u16 psc) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //時鐘使能
//定時器TIM1初始化
TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)置在下一個更新事件裝入活動的自動重裝載寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler = psc; //設(shè)置用來作為TIMx時鐘頻率除數(shù)的預(yù)分頻值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設(shè)置時鐘分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數(shù)模式
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根據(jù)指定的參數(shù)初始化TIMx的時間基數(shù)單位
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE); //使能指定的TIM3中斷,允許更新中斷
//中斷優(yōu)先級NVIC設(shè)置
NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn; //TIM1中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占優(yōu)先級0級
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //從優(yōu)先級3級
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
TIM_Cmd(TIM1, ENABLE); //使能TIM1
}
/* 定時器1中斷服務(wù)程序 */
void TIM1_UP_IRQHandler(void) /* TIM1中斷 */
{
if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET) /* 檢查TIM1更新中斷發(fā)生與否 */
{
TIM_ClearITPendingBit(TIM1, TIM_IT_Update); /* 清除TIM1更新中斷標(biāo)志 */
freq = freq_cnt * 0XFFFF + TIM_GetCounter(TIM2); //讀取單位時間內(nèi)計數(shù)器計的CNT值
printf("%ld Hz \r\n", freq);//打印頻率
freq = 0;
freq_cnt = 0;
TIM_SetCounter(TIM2, 0);
}
}
//TIM3 PWM部分初始化
//PWM輸出初始化
//arr:自動重裝值
//psc:時鐘預(yù)分頻數(shù)
void TIM3_PWM_Init(u16 arr, u16 psc) {
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定時器3時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); //使能GPIO外設(shè)和AFIO復(fù)用功能模塊時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); //使能GPIO外設(shè)和AFIO復(fù)用功能模塊時鐘
//設(shè)置該引腳為復(fù)用輸出功能
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; //TIM3_CH1 TIM3_CH2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; //TIM3_CH3 TIM3_CH4
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
//初始化TIM3
TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)置在下一個更新事件裝入活動的自動重裝載寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler = psc; //設(shè)置用來作為TIMx時鐘頻率除數(shù)的預(yù)分頻值
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //設(shè)置時鐘分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數(shù)模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根據(jù)TIM_TimeBaseInitStruct中指定的參數(shù)初始化TIMx的時間基數(shù)單位
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //選擇定時器模式:TIM脈沖寬度調(diào)制模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //輸出極性:TIM輸出比較極性高
TIM_OC1Init(TIM3, &TIM_OCInitStructure); //根據(jù)T指定的參數(shù)初始化外設(shè)TIM3 OC1
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //選擇定時器模式:TIM脈沖寬度調(diào)制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //輸出極性:TIM輸出比較極性高
TIM_OC2Init(TIM3, &TIM_OCInitStructure); //根據(jù)T指定的參數(shù)初始化外設(shè)TIM3 OC2
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //選擇定時器模式:TIM脈沖寬度調(diào)制模式3
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //輸出極性:TIM輸出比較極性高
TIM_OC3Init(TIM3, &TIM_OCInitStructure); //根據(jù)T指定的參數(shù)初始化外設(shè)TIM3 OC3
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //選擇定時器模式:TIM脈沖寬度調(diào)制模式4
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //輸出極性:TIM輸出比較極性高
TIM_OC4Init(TIM3, &TIM_OCInitStructure); //根據(jù)T指定的參數(shù)初始化外設(shè)TIM3 OC4
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM3在CCR1上的預(yù)裝載寄存器
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM3在CCR2上的預(yù)裝載寄存器
TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM3在CCR3上的預(yù)裝載寄存器
TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM3在CCR4上的預(yù)裝載寄存器
TIM_Cmd(TIM3, ENABLE); //使能TIM3
}
int main(void) {
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /* 設(shè)置NVIC中斷分組2:2位搶占優(yōu)先級,2位響應(yīng)優(yōu)先級 */
delay_init(); /* 延時函數(shù)初始化 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); /* 關(guān)閉jtag,使能SWD,可以用SWD模式調(diào)試 */
delay_ms(500); /* 等待穩(wěn)定 */
uart_init(115200);
TIM1_Init(10000 - 1, 7200 - 1);//1s一次中斷
TIM2_Cap_Init(0XFFFF, 0); //定時器2初始化
TIM3_PWM_Init(7200, 0); /* 10KHz PWM PA6 */
TIM_SetCompare1(TIM3, 3600);
TIM_SetCompare2(TIM3, 3600);
TIM_SetCompare3(TIM3, 3600);
TIM_SetCompare4(TIM3, 3600);
while (1) {
}
}
10KHz PWM PA6 接到TIM2 PA0。文章來源地址http://www.zghlxwxcb.cn/news/detail-514791.html
到了這里,關(guān)于【單片機】STM32單片機頻率計程序,外部脈沖計數(shù)程序,基于脈沖計數(shù)的頻率計程序,STM32F103的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!