簡(jiǎn)單介紹
下面的定時(shí)器都具有輸入捕獲能力:
外部計(jì)數(shù)頻率計(jì)
查看另一篇文章:https://qq742971636.blog.csdn.net/article/details/131471539
外部計(jì)數(shù)頻率計(jì)的缺點(diǎn):需要兩個(gè)定時(shí)器配合,最高能測(cè)量的頻率是否有限制我沒(méi)具體嘗試。
基于捕獲的頻率計(jì)的缺點(diǎn):最高能測(cè)量的頻率有限制。
TIM2 頻率計(jì) 捕獲
TIM3_CH1 PWM PA6 10KHZ。
輸入到TIM2_CH1 PA0。
#include "sys.h"
#include "usart.h"
//定時(shí)器2通道1輸入捕獲配置
TIM_ICInitTypeDef TIM2_ICInitStructure;
void TIM2_Cap_Init(u16 arr, u16 psc) {
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能TIM2時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA時(shí)鐘
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 下拉
//初始化定時(shí)器5 TIM2
TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)定計(jì)數(shù)器自動(dòng)重裝值
TIM_TimeBaseStructure.TIM_Prescaler = psc; //預(yù)分頻器
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設(shè)置時(shí)鐘分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計(jì)數(shù)模式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根據(jù)TIM_TimeBaseInitStruct中指定的參數(shù)初始化TIMx的時(shí)間基數(shù)單位
//初始化TIM2輸入捕獲參數(shù)
TIM2_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01 選擇輸入端 IC1映射到TI1上
TIM2_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕獲
TIM2_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上
TIM2_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置輸入分頻,不分頻
TIM2_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置輸入濾波器 不濾波
TIM_ICInit(TIM2, &TIM2_ICInitStructure);
//中斷分組初始化
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //TIM2中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占優(yōu)先級(jí)2級(jí)
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //從優(yōu)先級(jí)0級(jí)
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //根據(jù)NVIC_InitStruct中指定的參數(shù)初始化外設(shè)NVIC寄存器
TIM_ITConfig(TIM2, TIM_IT_Update | TIM_IT_CC1, ENABLE);//允許更新中斷 ,允許CC1IE捕獲中斷
TIM_Cmd(TIM2, ENABLE); //使能定時(shí)器5
//TIM_OC1PolarityConfig(TIM2, TIM_ICPolarity_Rising); //CC1P=0 設(shè)置為上升沿捕獲 隨時(shí)可改捕獲極性
}
u8 cap_status = 0; //輸入捕獲狀態(tài)
u16 cap_value; //輸入捕獲值
u32 cap_value_cnt = 0;//輸入捕獲值計(jì)數(shù)器
u32 freq;
//定時(shí)器5中斷服務(wù)程序
void TIM2_IRQHandler(void) {
if ((cap_status & 0X80) == 0)//還未成功捕獲
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
if (cap_status & 0X40)//已經(jīng)捕獲到高電平了
{
cap_value_cnt++;//定時(shí)器溢出一次
}
}
if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)//捕獲1發(fā)生捕獲事件
{
if (cap_status & 0X40) //在"標(biāo)記捕獲到了上升沿"之后,再次捕獲到了上升沿
{
cap_status |= 0X80; //標(biāo)記成功捕獲到一次高電平脈寬
cap_value = TIM_GetCapture1(TIM2);
//TIM_OC1PolarityConfig(TIM2, TIM_ICPolarity_Rising); //CC1P=0 設(shè)置為上升沿捕獲
} else //還未開(kāi)始,第一次捕獲上升沿
{
cap_status = 0; //清空
cap_value = 0;
TIM_SetCounter(TIM2, 0);
cap_status |= 0X40; //標(biāo)記捕獲到了上升沿
//TIM_OC1PolarityConfig(TIM2, TIM_ICPolarity_Falling); //CC1P=1 設(shè)置為下降沿捕獲
}
}
}
TIM_ClearITPendingBit(TIM2, TIM_IT_CC1 | TIM_IT_Update); //清除中斷標(biāo)志位
}
//TIM3 PWM部分初始化
//PWM輸出初始化
//arr:自動(dòng)重裝值
//psc:時(shí)鐘預(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); //使能定時(shí)器3時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); //使能GPIO外設(shè)和AFIO復(fù)用功能模塊時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); //使能GPIO外設(shè)和AFIO復(fù)用功能模塊時(shí)鐘
//設(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è)置在下一個(gè)更新事件裝入活動(dòng)的自動(dòng)重裝載寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //設(shè)置用來(lái)作為TIMx時(shí)鐘頻率除數(shù)的預(yù)分頻值
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //設(shè)置時(shí)鐘分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計(jì)數(shù)模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根據(jù)TIM_TimeBaseInitStruct中指定的參數(shù)初始化TIMx的時(shí)間基數(shù)單位
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //選擇定時(shí)器模式: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; //選擇定時(shí)器模式: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; //選擇定時(shí)器模式: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; //選擇定時(shí)器模式: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) {
u32 temp = 0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /* 設(shè)置NVIC中斷分組2:2位搶占優(yōu)先級(jí),2位響應(yīng)優(yōu)先級(jí) */
delay_init(); /* 延時(shí)函數(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);
TIM2_Cap_Init(0XFFFF, 72 - 1); //以1Mhz的頻率計(jì)數(shù)
TIM3_PWM_Init( 7200, 0 ); /* 10KHz */
TIM_SetCompare1( TIM3, 3600 );
TIM_SetCompare2( TIM3, 3600 );
TIM_SetCompare3( TIM3, 3600 );
TIM_SetCompare4( TIM3, 3600 );
while (1) {
delay_ms(100);
if (cap_status & 0X80)//成功捕獲到了一次上升沿
{
temp = cap_value_cnt * 65536 + cap_value;//兩次捕獲之間的時(shí)間差
printf("HIGH+LOW:%d us\r\n", temp);//打印總的高點(diǎn)平時(shí)間
freq = 1000000 / temp;//計(jì)算頻率
printf("freq:%d Hz\r\n", freq);//打印頻率
cap_status = 0;//開(kāi)啟下一次捕獲
}
}
}
TIM3 頻率計(jì) 捕獲
TIM3_CH1 PA6 捕獲輸入。
TIM2_CH2 PWM 10khz輸出。
接起來(lái)看到:
#include "sys.h"
#include "usart.h"
//定時(shí)器2通道1輸入捕獲配置
TIM_ICInitTypeDef TIM3_ICInitStructure;
void TIM3_Cap_Init(u16 arr, u16 psc) {
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能TIM3時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA時(shí)鐘
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //PA0 清除之前設(shè)置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 輸入
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA, GPIO_Pin_0); //PA0 下拉
//初始化定時(shí)器5 TIM3
TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)定計(jì)數(shù)器自動(dòng)重裝值
TIM_TimeBaseStructure.TIM_Prescaler = psc; //預(yù)分頻器
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設(shè)置時(shí)鐘分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計(jì)數(shù)模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根據(jù)TIM_TimeBaseInitStruct中指定的參數(shù)初始化TIMx的時(shí)間基數(shù)單位
//初始化TIM3輸入捕獲參數(shù)
TIM3_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01 選擇輸入端 IC1映射到TI1上
TIM3_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕獲
TIM3_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上
TIM3_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置輸入分頻,不分頻
TIM3_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置輸入濾波器 不濾波
TIM_ICInit(TIM3, &TIM3_ICInitStructure);
//中斷分組初始化
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占優(yōu)先級(jí)2級(jí)
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //從優(yōu)先級(jí)0級(jí)
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //根據(jù)NVIC_InitStruct中指定的參數(shù)初始化外設(shè)NVIC寄存器
TIM_ITConfig(TIM3, TIM_IT_Update | TIM_IT_CC1, ENABLE);//允許更新中斷 ,允許CC1IE捕獲中斷
TIM_Cmd(TIM3, ENABLE); //使能定時(shí)器5
//TIM_OC1PolarityConfig(TIM3, TIM_ICPolarity_Rising); //CC1P=0 設(shè)置為上升沿捕獲 隨時(shí)可改捕獲極性
}
u8 cap_status = 0; //輸入捕獲狀態(tài)
u16 cap_value; //輸入捕獲值
u32 cap_value_cnt = 0;//輸入捕獲值計(jì)數(shù)器
u32 freq;
//定時(shí)器5中斷服務(wù)程序
void TIM3_IRQHandler(void) {
if ((cap_status & 0X80) == 0)//還未成功捕獲
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) {
if (cap_status & 0X40)//已經(jīng)捕獲到高電平了
{
cap_value_cnt++;//定時(shí)器溢出一次
}
}
if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)//捕獲1發(fā)生捕獲事件
{
if (cap_status & 0X40) //在"標(biāo)記捕獲到了上升沿"之后,再次捕獲到了上升沿
{
cap_status |= 0X80; //標(biāo)記成功捕獲到一次高電平脈寬
cap_value = TIM_GetCapture1(TIM3);
//TIM_OC1PolarityConfig(TIM3, TIM_ICPolarity_Rising); //CC1P=0 設(shè)置為上升沿捕獲
} else //還未開(kāi)始,第一次捕獲上升沿
{
cap_status = 0; //清空
cap_value = 0;
TIM_SetCounter(TIM3, 0);
cap_status |= 0X40; //標(biāo)記捕獲到了上升沿
//TIM_OC1PolarityConfig(TIM3, TIM_ICPolarity_Falling); //CC1P=1 設(shè)置為下降沿捕獲
}
}
}
TIM_ClearITPendingBit(TIM3, TIM_IT_CC1 | TIM_IT_Update); //清除中斷標(biāo)志位
}
//TIM2 PWM部分初始化
//PWM輸出初始化
//arr:自動(dòng)重裝值
//psc:時(shí)鐘預(yù)分頻數(shù)
//配置7路PWM
void TIM2_PWM_Init(u16 arr, u16 psc) {
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能定時(shí)器2時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); //使能GPIO外設(shè)和AFIO復(fù)用功能模塊時(shí)鐘
//設(shè)置該引腳為復(fù)用輸出功能
GPIO_InitStructure.GPIO_Pin =
GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3; //TIM2_CH1 TIM2_CH2 TIM2_CH3 TIM2_CH4
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO
//初始化TIM2
TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)置在下一個(gè)更新事件裝入活動(dòng)的自動(dòng)重裝載寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler = psc; //設(shè)置用來(lái)作為TIMx時(shí)鐘頻率除數(shù)的預(yù)分頻值
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //設(shè)置時(shí)鐘分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計(jì)數(shù)模式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根據(jù)TIM_TimeBaseInitStruct中指定的參數(shù)初始化TIMx的時(shí)間基數(shù)單位
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //選擇定時(shí)器模式:TIM脈沖寬度調(diào)制模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //輸出極性:TIM輸出比較極性高
TIM_OC1Init(TIM2, &TIM_OCInitStructure); //根據(jù)T指定的參數(shù)初始化外設(shè)TIM2 OC1
TIM_OC2Init(TIM2, &TIM_OCInitStructure); //根據(jù)T指定的參數(shù)初始化外設(shè)TIM2 OC2
TIM_OC3Init(TIM2, &TIM_OCInitStructure); //根據(jù)T指定的參數(shù)初始化外設(shè)TIM2 OC3
TIM_OC4Init(TIM2, &TIM_OCInitStructure); //根據(jù)T指定的參數(shù)初始化外設(shè)TIM2 OC4
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能TIM2在CCR1上的預(yù)裝載寄存器
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能TIM2在CCR2上的預(yù)裝載寄存器
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能TIM2在CCR3上的預(yù)裝載寄存器
TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能TIM2在CCR4上的預(yù)裝載寄存器
TIM_Cmd(TIM2, ENABLE); //使能TIM2
}
int main(void) {
u32 temp = 0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /* 設(shè)置NVIC中斷分組2:2位搶占優(yōu)先級(jí),2位響應(yīng)優(yōu)先級(jí) */
delay_init(); /* 延時(shí)函數(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);
TIM3_Cap_Init(0XFFFF, 72 - 1); //以1Mhz的頻率計(jì)數(shù)
TIM2_PWM_Init(7200, 0); /* 10KHz */
TIM_SetCompare1(TIM2, 2000);//PA0
TIM_SetCompare2(TIM2, 2000);
TIM_SetCompare3(TIM2, 2000);
TIM_SetCompare4(TIM2, 2000);
while (1) {
delay_ms(100);
if (cap_status & 0X80)//成功捕獲到了一次上升沿
{
temp = cap_value_cnt * 65536 + cap_value;//兩次捕獲之間的時(shí)間差
printf("HIGH+LOW:%d us\r\n", temp);//打印總的高點(diǎn)平時(shí)間
freq = 1000000 / temp;//計(jì)算頻率
printf("freq:%d Hz\r\n", freq);//打印頻率
cap_status = 0;//開(kāi)啟下一次捕獲
}
}
}
TIM4 頻率計(jì) 捕獲
TIM4_CH1 PB6 捕獲輸入。
TIM2_CH2 PWM 10khz輸出。
接起來(lái)看到:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-623950.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-623950.html
#include "sys.h"
#include "usart.h"
//定時(shí)器2通道1輸入捕獲配置
TIM_ICInitTypeDef TIM4_ICInitStructure;
void TIM4_Cap_Init(u16 arr, u16 psc) {
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //使能TIM4時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA時(shí)鐘
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //PA0 清除之前設(shè)置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 輸入
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA, GPIO_Pin_0); //PA0 下拉
//初始化定時(shí)器5 TIM4
TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)定計(jì)數(shù)器自動(dòng)重裝值
TIM_TimeBaseStructure.TIM_Prescaler = psc; //預(yù)分頻器
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設(shè)置時(shí)鐘分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計(jì)數(shù)模式
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根據(jù)TIM_TimeBaseInitStruct中指定的參數(shù)初始化TIMx的時(shí)間基數(shù)單位
//初始化TIM4輸入捕獲參數(shù)
TIM4_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01 選擇輸入端 IC1映射到TI1上
TIM4_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕獲
TIM4_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上
TIM4_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置輸入分頻,不分頻
TIM4_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置輸入濾波器 不濾波
TIM_ICInit(TIM4, &TIM4_ICInitStructure);
//中斷分組初始化
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; //TIM4中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占優(yōu)先級(jí)2級(jí)
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //從優(yōu)先級(jí)0級(jí)
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //根據(jù)NVIC_InitStruct中指定的參數(shù)初始化外設(shè)NVIC寄存器
TIM_ITConfig(TIM4, TIM_IT_Update | TIM_IT_CC1, ENABLE);//允許更新中斷 ,允許CC1IE捕獲中斷
TIM_Cmd(TIM4, ENABLE); //使能定時(shí)器5
//TIM_OC1PolarityConfig(TIM4, TIM_ICPolarity_Rising); //CC1P=0 設(shè)置為上升沿捕獲 隨時(shí)可改捕獲極性
}
u8 cap_status = 0; //輸入捕獲狀態(tài)
u16 cap_value; //輸入捕獲值
u32 cap_value_cnt = 0;//輸入捕獲值計(jì)數(shù)器
u32 freq;
//定時(shí)器5中斷服務(wù)程序
void TIM4_IRQHandler(void) {
if ((cap_status & 0X80) == 0)//還未成功捕獲
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) {
if (cap_status & 0X40)//已經(jīng)捕獲到高電平了
{
cap_value_cnt++;//定時(shí)器溢出一次
}
}
if (TIM_GetITStatus(TIM4, TIM_IT_CC1) != RESET)//捕獲1發(fā)生捕獲事件
{
if (cap_status & 0X40) //在"標(biāo)記捕獲到了上升沿"之后,再次捕獲到了上升沿
{
cap_status |= 0X80; //標(biāo)記成功捕獲到一次高電平脈寬
cap_value = TIM_GetCapture1(TIM4);
//TIM_OC1PolarityConfig(TIM4, TIM_ICPolarity_Rising); //CC1P=0 設(shè)置為上升沿捕獲
} else //還未開(kāi)始,第一次捕獲上升沿
{
cap_status = 0; //清空
cap_value = 0;
TIM_SetCounter(TIM4, 0);
cap_status |= 0X40; //標(biāo)記捕獲到了上升沿
//TIM_OC1PolarityConfig(TIM4, TIM_ICPolarity_Falling); //CC1P=1 設(shè)置為下降沿捕獲
}
}
}
TIM_ClearITPendingBit(TIM4, TIM_IT_CC1 | TIM_IT_Update); //清除中斷標(biāo)志位
}
//TIM2 PWM部分初始化
//PWM輸出初始化
//arr:自動(dòng)重裝值
//psc:時(shí)鐘預(yù)分頻數(shù)
//配置7路PWM
void TIM2_PWM_Init(u16 arr, u16 psc) {
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能定時(shí)器2時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); //使能GPIO外設(shè)和AFIO復(fù)用功能模塊時(shí)鐘
//設(shè)置該引腳為復(fù)用輸出功能
GPIO_InitStructure.GPIO_Pin =
GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3; //TIM2_CH1 TIM2_CH2 TIM2_CH3 TIM2_CH4
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO
//初始化TIM2
TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)置在下一個(gè)更新事件裝入活動(dòng)的自動(dòng)重裝載寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler = psc; //設(shè)置用來(lái)作為TIMx時(shí)鐘頻率除數(shù)的預(yù)分頻值
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //設(shè)置時(shí)鐘分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計(jì)數(shù)模式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根據(jù)TIM_TimeBaseInitStruct中指定的參數(shù)初始化TIMx的時(shí)間基數(shù)單位
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //選擇定時(shí)器模式:TIM脈沖寬度調(diào)制模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //輸出極性:TIM輸出比較極性高
TIM_OC1Init(TIM2, &TIM_OCInitStructure); //根據(jù)T指定的參數(shù)初始化外設(shè)TIM2 OC1
TIM_OC2Init(TIM2, &TIM_OCInitStructure); //根據(jù)T指定的參數(shù)初始化外設(shè)TIM2 OC2
TIM_OC3Init(TIM2, &TIM_OCInitStructure); //根據(jù)T指定的參數(shù)初始化外設(shè)TIM2 OC3
TIM_OC4Init(TIM2, &TIM_OCInitStructure); //根據(jù)T指定的參數(shù)初始化外設(shè)TIM2 OC4
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能TIM2在CCR1上的預(yù)裝載寄存器
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能TIM2在CCR2上的預(yù)裝載寄存器
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能TIM2在CCR3上的預(yù)裝載寄存器
TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能TIM2在CCR4上的預(yù)裝載寄存器
TIM_Cmd(TIM2, ENABLE); //使能TIM2
}
int main(void) {
u32 temp = 0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /* 設(shè)置NVIC中斷分組2:2位搶占優(yōu)先級(jí),2位響應(yīng)優(yōu)先級(jí) */
delay_init(); /* 延時(shí)函數(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);
TIM4_Cap_Init(0XFFFF, 72 - 1); //以1Mhz的頻率計(jì)數(shù)
TIM2_PWM_Init(7200, 0); /* 10KHz */
TIM_SetCompare1(TIM2, 2000);//PB6
TIM_SetCompare2(TIM2, 2000);
TIM_SetCompare3(TIM2, 2000);
TIM_SetCompare4(TIM2, 2000);
while (1) {
delay_ms(100);
if (cap_status & 0X80)//成功捕獲到了一次上升沿
{
temp = cap_value_cnt * 65536 + cap_value;//兩次捕獲之間的時(shí)間差
printf("HIGH+LOW:%d us\r\n", temp);//打印總的高點(diǎn)平時(shí)間
freq = 1000000 / temp;//計(jì)算頻率
printf("freq:%d Hz\r\n", freq);//打印頻率
cap_status = 0;//開(kāi)啟下一次捕獲
}
}
}
TIM5 頻率計(jì) 捕獲
#include "sys.h"
#include "usart.h"
//定時(shí)器5通道1輸入捕獲配置
TIM_ICInitTypeDef TIM5_ICInitStructure;
void TIM5_Cap_Init(u16 arr, u16 psc) {
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //使能TIM5時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA時(shí)鐘
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 下拉
//初始化定時(shí)器5 TIM5
TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)定計(jì)數(shù)器自動(dòng)重裝值
TIM_TimeBaseStructure.TIM_Prescaler = psc; //預(yù)分頻器
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設(shè)置時(shí)鐘分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計(jì)數(shù)模式
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); //根據(jù)TIM_TimeBaseInitStruct中指定的參數(shù)初始化TIMx的時(shí)間基數(shù)單位
//初始化TIM5輸入捕獲參數(shù)
TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01 選擇輸入端 IC1映射到TI1上
TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕獲
TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上
TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置輸入分頻,不分頻
TIM5_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置輸入濾波器 不濾波
TIM_ICInit(TIM5, &TIM5_ICInitStructure);
//中斷分組初始化
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn; //TIM5中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占優(yōu)先級(jí)2級(jí)
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //從優(yōu)先級(jí)0級(jí)
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //根據(jù)NVIC_InitStruct中指定的參數(shù)初始化外設(shè)NVIC寄存器
TIM_ITConfig(TIM5, TIM_IT_Update | TIM_IT_CC1, ENABLE);//允許更新中斷 ,允許CC1IE捕獲中斷
TIM_Cmd(TIM5, ENABLE); //使能定時(shí)器5
//TIM_OC1PolarityConfig(TIM5, TIM_ICPolarity_Rising); //CC1P=0 設(shè)置為上升沿捕獲 隨時(shí)可改捕獲極性
}
u8 cap_status = 0; //輸入捕獲狀態(tài)
u16 cap_value; //輸入捕獲值
u32 cap_value_cnt = 0;//輸入捕獲值計(jì)數(shù)器
u32 freq;
//定時(shí)器5中斷服務(wù)程序
void TIM5_IRQHandler(void) {
if ((cap_status & 0X80) == 0)//還未成功捕獲
{
if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET) {
if (cap_status & 0X40)//已經(jīng)捕獲到高電平了
{
cap_value_cnt++;//定時(shí)器溢出一次
}
}
if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)//捕獲1發(fā)生捕獲事件
{
if (cap_status & 0X40) //在"標(biāo)記捕獲到了上升沿"之后,再次捕獲到了上升沿
{
cap_status |= 0X80; //標(biāo)記成功捕獲到一次高電平脈寬
cap_value = TIM_GetCapture1(TIM5);
//TIM_OC1PolarityConfig(TIM5, TIM_ICPolarity_Rising); //CC1P=0 設(shè)置為上升沿捕獲
} else //還未開(kāi)始,第一次捕獲上升沿
{
cap_status = 0; //清空
cap_value = 0;
TIM_SetCounter(TIM5, 0);
cap_status |= 0X40; //標(biāo)記捕獲到了上升沿
//TIM_OC1PolarityConfig(TIM5, TIM_ICPolarity_Falling); //CC1P=1 設(shè)置為下降沿捕獲
}
}
}
TIM_ClearITPendingBit(TIM5, TIM_IT_CC1 | TIM_IT_Update); //清除中斷標(biāo)志位
}
int main(void) {
u32 temp = 0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /* 設(shè)置NVIC中斷分組2:2位搶占優(yōu)先級(jí),2位響應(yīng)優(yōu)先級(jí) */
delay_init(); /* 延時(shí)函數(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);
TIM5_Cap_Init(0XFFFF, 72 - 1); //以1Mhz的頻率計(jì)數(shù)
while (1) {
delay_ms(10);
if (cap_status & 0X80)//成功捕獲到了一次上升沿
{
temp = cap_value_cnt * 65536 + cap_value;//兩次捕獲之間的時(shí)間差
printf("HIGH+LOW:%d us\r\n", temp);//打印總的高點(diǎn)平時(shí)間
freq = 1000000 / temp;//計(jì)算頻率
printf("freq:%d Hz\r\n", freq);//打印頻率
cap_status = 0;//開(kāi)啟下一次捕獲
}
}
}
到了這里,關(guān)于【單片機(jī)】STM32單片機(jī),定時(shí)器的輸入捕獲,基于捕獲的頻率計(jì),STM32F103的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!