timer.h
#ifndef _TIM5SANP_H
#define _TIM5SANP_H
#include "sys.h"
void TIM14_PWM_Init(u32 arr,u32 psc);
void TIM5_CH1_Cap_Init(u32 arr,u16 psc);
#endif
timer.c
#include "timer.h"
TIM_ICInitTypeDef TIM5_ICInitStructre;
void TIM5_CH1_Cap_Init(u32 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);//TIM5时钟使能
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//GPIOA时钟使能
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_DOWN;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource0,GPIO_AF_TIM5);//PA0复用tim5
TIM_TimeBaseStructure.TIM_Prescaler=psc;//定时器分频
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数模式
TIM_TimeBaseStructure.TIM_Period=arr;//自动重装载值
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;//配置输入分频,不分频
TIM_TimeBaseInit(TIM5,&TIM_TimeBaseStructure);//
//#define TIM_Channel_1 ((uint16_t)0x0000)
//
//#define TIM_ICSelection_DirectTI ((uint16_t)0x0001)
// TIM Input 1, 2, 3 or 4 is selected to be connected to IC1, IC2, IC3 or IC4, respectively
//TIM5_CCMR1寄存器
//位 1:0 CC1S:捕获/比较 1 选择 (Capture/Compare 1 selection)
//此位域定义通道方向(输入/输出)以及所使用的输入。
//00: CC1 通道配置为输出。
//01: CC1 通道配置为输入, IC1 映射到 TI1 上。
//书本178页 或中文参考434页
TIM5_ICInitStructre.TIM_Channel=TIM_Channel_1;//选择输入端IC1映射到TI1
TIM5_ICInitStructre.TIM_ICPolarity=TIM_ICPolarity_Rising;//上升沿捕获
TIM5_ICInitStructre.TIM_ICSelection=TIM_ICSelection_DirectTI;//映射到TI1上
TIM5_ICInitStructre.TIM_ICPrescaler=TIM_ICPSC_DIV1;//配置输入分频,不分频
TIM5_ICInitStructre.TIM_ICFilter=0x00;//配置输入滤波器不滤波
TIM_ICInit(TIM5,&TIM5_ICInitStructre);//初始化TIM5输入捕获参数
TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);//允许更新和捕获中断
TIM_Cmd(TIM5,ENABLE);//使能定时器5
NVIC_InitStructure.NVIC_IRQChannel=TIM5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
//捕获状态
//[7]:0,没有成功的捕获,1,成功捕获到1次
//[6]:0,还没捕获到低电平;1,已经捕获到低电平了
//[5:0]:捕获低电平后溢出的次数(对于32位定时器来说,1us计数器加1,溢出时间:4294s)
u8 TIM5CH1_CAPTURE_STA=0;//输入捕获状态
u32 TIM5CH1_CAPTURE_VAL; //输入捕获值(TIM2/TIM5是32位)
//定时器5中断服务程序
void TIM5_IRQHandler(void)
{
if((TIM5CH1_CAPTURE_STA & 0x80)==0)//还未成功捕获
{
if(TIM_GetITStatus(TIM5,TIM_IT_Update) != RESET)//溢出
{
if(TIM5CH1_CAPTURE_STA & 0x40)//已经捕获到高电平了
{
if((TIM5CH1_CAPTURE_STA & 0X3F)==0X3F)//高电平太长了
{
TIM5CH1_CAPTURE_STA |= 0X80;//标记成功捕获了一次
TIM5CH1_CAPTURE_VAL=0XFFFFFFFF;
}
else
TIM5CH1_CAPTURE_STA++;
}
}
if(TIM_GetITStatus(TIM5,TIM_IT_CC1) != RESET)//捕获1发生捕获事件
{
if(TIM5CH1_CAPTURE_STA & 0x40)//捕获到一个下降下沿
{
TIM5CH1_CAPTURE_STA |= 0X80;//标记成功捕获了一次高电平脉宽
TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5);//获取当前的捕获值
TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising);//设置上升沿捕获
}
else //还未开始,第一次捕获了上升沿
{
TIM5CH1_CAPTURE_STA=0;//清空
TIM5CH1_CAPTURE_VAL=0;
TIM5CH1_CAPTURE_STA |=0x40;//标记捕获了上升沿
TIM_Cmd(TIM5,ENABLE);
TIM_SetCounter(TIM5,0);//计数器清空
TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling); //设置下降沿捕获
TIM_Cmd(TIM5,ENABLE);//使能定时器5
}
}
}
TIM_ClearITPendingBit(TIM5,TIM_IT_CC1|TIM_IT_Update); //清除中断标志位
}
/*
程序思路:
TIM5CH1_CAPTURE_STA:用来记录捕获状态
TIM5CH1_CAPTURE_STA=0x40 第7位为1说明捕获到高电平
TIM5CH1_CAPTURE_STA的bit7 第8位为1说明捕获完成了
TIM5CH1_CAPTURE_STA的[5:0]是记录溢出次数
第一次进入中断
开始时TIM5CH1_CAPTURE_STA=0;必然会进入这个if
if((TIM5CH1_CAPTURE_STA & 0x80)==0)
1.如果在捕获到高电平前溢出了,则溢出部份不处理
2.如果在捕获高电平之后TIM5CH1_CAPTURE_STA++;
如果捕获1发生捕获事件,计数器清0,TIM5CH1_CAPTURE_STA=0x40 (0100 0000),改成下降沿捕获
第N次进入中断
如果前面已经捕获了上升沿,
TIM5CH1_CAPTURE_STA |= 0X80; //标记成功捕获了一次高电平脉宽
TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5);//获取当前的捕获值
TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising);//设置上升沿捕获
*/
main.c
#include "sys.h"
#include "delay.h"
#include "timer.h"
#include "usart.h"
extern u8 TIM5CH1_CAPTURE_STA;//输入捕获状态
extern u32 TIM5CH1_CAPTURE_VAL; //输入捕获值(TIM2/TIM5是32位)
int main(void)
{
//long long是属于int型, 一般来讲, 是long int型大小的两倍, int型的4倍.
long long temp=0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
delay_init(168);
uart_init(115200);
TIM5_CH1_Cap_Init(0XFFFFFFFF,84-1);
//84Mhz 84分频为1Mhz 一个周期是1us
//自动重装载值取到最大2的32次方-1 约4294.96秒才会溢出
while(1)
{
if(TIM5CH1_CAPTURE_STA & 0x80)
{
temp=TIM5CH1_CAPTURE_STA & 0x3f;//取到溢出次数通常为0因为很少有能超出4294.96秒
temp *=0XFFFFFFFF;//溢出一次时间加上0XFFFFFFFF us
temp +=TIM5CH1_CAPTURE_VAL; //得到总的高电平时间和 一次刚好是1us
printf("高电平的时间为:%lld us \r\n",temp);
TIM5CH1_CAPTURE_STA=0;//下一次捕获开启
}
}
}