IntputCapture.c
#include "stm32f4xx.h"
#include "IntputCapture.h"
//AutomaticReload:自动重装载值 PrioritySendCount:时钟预分频数
void TIM14_Init(u32 AutomaticReload,u32 PrioritySendCount)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,ENABLE);//使能TIM14_CH1 1通道时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);// 使能GPIOF引脚
GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14);//引脚复用PF9引脚复用为TIM14的通道1
//GPIO的初始化函数,设置初始化的模式为复用
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF; //设置GPIO模式为复用 对应上述引脚复用PF9引脚复用为TIM14的通道1
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOF,&GPIO_InitStructure);
//初始化TIM14定时器,设置预分频值和自动重装载值
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数,也就是递增计数
TIM_TimeBaseInitStructure.TIM_Period=AutomaticReload;//自动重装载值
TIM_TimeBaseInitStructure.TIM_Prescaler=PrioritySendCount;//时钟预分频值
TIM_TimeBaseInit(TIM14,&TIM_TimeBaseInitStructure);
//设置TIM14的PWM模式
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;//输出极性低,也就意味着占空比中低电平有效
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//PWM调质模式1
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//输出比较使能
TIM_OCInitStructure.TIM_Pulse=0;
TIM_OC1Init(TIM14,&TIM_OCInitStructure);//初始化TIM14通道1
TIM_OC2PreloadConfig(TIM14,TIM_OCPreload_Enable);//使能TIM14在CCR2上的预装载寄存器
TIM_ARRPreloadConfig(TIM14,ENABLE);//使能自动重装载寄存器
TIM_Cmd(TIM14,ENABLE);//使能TIM14
}
//AutomationReload:自动重装值(TIM2,TIM5的自动重装载值是32位的) PrioritySendCount:时钟预分频数
void TIM5_CH1_InterCapture_Init(u32 AutomationReload,u16 PrioritySendCount)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);//TIM5时钟使能
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//使能GPIOA
GPIO_PinAFConfig(GPIOA,GPIO_PinSource0,GPIO_AF_TIM5);//PA0复用为TIM5
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_DOWN; //引脚设置为下拉,因为PA0对应KEY_UP按键,KEY_UP按键左侧接V3.3
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);//GPIOA初始化
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数模式
TIM_TimeBaseInitStructure.TIM_Period=AutomationReload;
TIM_TimeBaseInitStructure.TIM_Prescaler=PrioritySendCount;
TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStructure);
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICInitStructure.TIM_Channel=TIM_Channel_1;//映射通道1上
TIM_ICInitStructure.TIM_ICFilter=0x00;//不滤波
TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;//上升沿捕获
TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;//配置输入不分频
TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;//映射到TI1上,也就是TIM5通道1
TIM_ICInit(TIM5,&TIM_ICInitStructure);//初始化TIM5输入捕获
TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);//使能捕获和更新中断
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=TIM5_IRQn;//TIM5通道
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//使能中断优先级
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//抢占优先级2
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;//响应优先级0
NVIC_Init(&NVIC_InitStructure);//初始化NVIC
TIM_Cmd(TIM5,ENABLE);//使能定时器5
}
//捕获状态位
//位7:0 还没成功捕获 1 成功捕获到一次
//位6:0 还没有捕获到低电平 1 成功捕获到一次低电平
//位5:0 捕获低电平后溢出的次数,当达到最高的溢出次数时,标记成功捕获一次
//这里需要注意,之所以设置低电平捕获状态和溢出次数,是因为初始化TIM5的时候设置的是上升沿捕获,那么就意味着初始化时上升沿就会进行一次捕获,想要获得高电平的持续时间,就要在中断中获得捕获低电平时的计数器值
u8 TIM5_CH1_CAPTURE_STA=0;//定义全局变量输入捕获的状态
u32 TIM5_CH1_CAPTURE_VAL;//输入捕获的值(注意TIM2/TIM5的输入捕获值是32位的)
void TIM5_IRQHandler(void)//两种情况 一种是溢出次数也就是循环了多少次,另一种是发生捕获也就是最后一次的时间,两个相加才是总的时间
//这个也比较好理解,因为我们不确定在我们捕获的低电平是第一次低电平,还是第n次低电平;
//如果只是单纯的记录低电平的计数器值,可能要比实际的高电平时间要小很多,因为中间掺杂着多个周期,我们都没有记录在内
{
if((TIM5_CH1_CAPTURE_STA&0x80)==0)//输入捕获状态位的最高位为0,还未成功捕获
{
if(TIM_GetITStatus(TIM5,TIM_IT_Update)!=RESET)//判断是否为更新中断,溢出
{
if(TIM5_CH1_CAPTURE_STA&0x40)//已经捕获到高电平了
{
if((TIM5_CH1_CAPTURE_STA&0x3F)==0x3F)//低6位为1,表示溢出的次数达到了最高,默认标记成功捕获一次
{
TIM5_CH1_CAPTURE_STA=TIM5_CH1_CAPTURE_STA|0X80;//状态位的最高位置1,表示已经成功捕获了一次
TIM5_CH1_CAPTURE_VAL=0xFFFFFFFF;//捕获值达到最高
}
else //不是因为溢出次数达到顶峰而标记捕获,则捕获状态++;
TIM5_CH1_CAPTURE_STA++;
}
}
if(TIM_GetITStatus(TIM5,TIM_IT_CC1)!=RESET)//捕获1发生捕获事件
{
if(TIM5_CH1_CAPTURE_STA&0x40)//捕获一个下降沿,一次捕获已经结束了,我需要做以下几件事:
//标记状态位的最高位为1,表明成功捕获一次,将捕获到的值给到全局变量VAL,
//因为要捕获高电平的频率,所以先设置上升沿捕获,在设置下降沿捕获,这样一来,一个上升沿一个下降沿就会得到一个完整的高电平频率
{
TIM5_CH1_CAPTURE_STA|=0x80;//状态最高位置1,表示成功捕获一次
TIM5_CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5);//获取捕获值给到全局变量
TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising);//设置上升沿捕获
}
else //否则意味着还没有捕获到下降沿
{
TIM5_CH1_CAPTURE_STA=0;//清空
TIM5_CH1_CAPTURE_VAL=0;
TIM5_CH1_CAPTURE_STA|=0x40;//标记捕获到了一个上升沿
TIM_Cmd(TIM5,ENABLE);//使能定时器5
TIM_SetCounter(TIM5,0);//将定时器5清空
TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling);//设置下降沿捕获
TIM_Cmd(TIM5,ENABLE);//使能定时器5
}
}
}
TIM_ClearITPendingBit(TIM5,TIM_IT_CC1|TIM_IT_Update);//清除中断标志位
}
|