文章目录
- F407定时器输入捕获实验
- 支持输入捕获的定时器有哪些
- 输入捕获工作过程
- 输入捕获测量高电平脉宽原理
- 滤波器设置
- 配置步骤
- 开启TIM5时钟与端口时钟
- 配置PA0为用能复用功能(AF2)
- 初始化端口并开启下拉电阻
- 初始化TIM5
- 设置TIM5的输入捕获参数
- TIM_Channel通道
- TIM_ICPolarit极性
- TIM_ICSelection输入捕获映射通道
- TIM_ICPrescaler输入捕获预分频
- TIM_ICFilter输入捕获滤波器
- 代码
- 中断优先级分组,设置中断优先级
- 使能捕获和更新中断
- 编写中断服务函数
- 使能定时器
- 获取通道捕获值
- 捕获代码
- 定时器5中断代码
- 主函数代码
F407定时器输入捕获实验
支持输入捕获的定时器有哪些
F4开发指南,15.1,P221
输入捕获工作过程
输入捕获测量高电平脉宽原理
F4开发指南,15.1,P221
滤波器设置
Fdts是时钟分频后的时钟频率,可以在定时器中设置。
配置步骤
获取TIM5_CH1(P A0)上面的高电平脉冲宽度,并从串口打印捕获结果。
开启TIM5时钟与端口时钟
开启TIM5时钟的方法为:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE); //TIM5时钟使能
配置PA0为用能复用功能(AF2)
配置PA0为复用功能,要设置PA0引脚映射AF2,连接到TIM5上面。方法为:
GPIO_PinAFConfig(GPIOA,GPIO_PinSource0,GPIO_AF_TIM5); //GPIOF9复用位定时器14
初始化端口并开启下拉电阻
初始化GPIO的模式为复用功能,同时这里我们还要设置为开启下拉。方法为:
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //GPIOA0
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; //下拉
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化P A0
初始化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);//初始化TIM5
设置TIM5的输入捕获参数
设置TIM5_CCMR1寄存器
void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct)
同样,我们来看看参数设置结构体TIM_ICInitTypeDef的定义:
typedef struct
{
uint16_t TIM_Channel; //通道
uint16_t TIM_ICPolarity; //捕获极性
uint16_t TIM_ICSelection;//映射
uint16_t TIM_ICPrescaler;//分频系数
uint16_t TIM_ICFilter; //滤波器长度
} TIM_ICInitTypeDef;
TIM_Channel通道
#define TIM_Channel_1 ((uint16_t)0x0000)
#define TIM_Channel_2 ((uint16_t)0x0004)
#define TIM_Channel_3 ((uint16_t)0x0008)
#define TIM_Channel_4 ((uint16_t)0x000C)
#define IS_TIM_CHANNEL(CHANNEL) (((CHANNEL) == TIM_Channel_1) || \
((CHANNEL) == TIM_Channel_2) || \
((CHANNEL) == TIM_Channel_3) || \
((CHANNEL) == TIM_Channel_4))
TIM_ICPolarit极性
是 用 来 设 置 输 入 信 号 的 有 效 捕 获 极 性 :
#define TIM_ICPolarity_Rising 上升沿捕获 ((uint16_t)0x0000)
#define TIM_ICPolarity_Falling 下降沿捕获 ((uint16_t)0x0002)
#define TIM_ICPolarity_BothEdge 双沿捕获 ((uint16_t)0x000A)
#define IS_TIM_IC_POLARITY(POLARITY) (((POLARITY) == TIM_ICPolarity_Rising) || \
((POLARITY) == TIM_ICPolarity_Falling)|| \
((POLARITY) == TIM_ICPolarity_BothEdge))
TIM_ICSelection输入捕获映射通道
输入捕获映射通道
IC1直接映射在TI1上,选择TIM_ICSelection_DirectTI。
#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 */
#define TIM_ICSelection_IndirectTI ((uint16_t)0x0002) /*!< TIM Input 1, 2, 3 or 4 is selected to be connected to IC2, IC1, IC4 or IC3, respectively. */
#define TIM_ICSelection_TRC ((uint16_t)0x0003) /*!< TIM Input 1, 2, 3 or 4 is selected to be connected to TRC. */
#define IS_TIM_IC_SELECTION(SELECTION) (((SELECTION) == TIM_ICSelection_DirectTI) || \
((SELECTION) == TIM_ICSelection_IndirectTI) || \
((SELECTION) == TIM_ICSelection_TRC))
TIM_ICPrescaler输入捕获预分频
用 来 设 置 输 入 捕 获 分 频 系 数 :
不 分 频 , 所 以 选 中TIM_ICPSC_DIV1,还有2,4,8分频可选。
#define TIM_ICPSC_DIV1 ((uint16_t)0x0000) /*!< Capture performed each time an edge is detected on the capture input. */
#define TIM_ICPSC_DIV2 ((uint16_t)0x0004) /*!< Capture performed once every 2 events. */
#define TIM_ICPSC_DIV4 ((uint16_t)0x0008) /*!< Capture performed once every 4 events. */
#define TIM_ICPSC_DIV8 ((uint16_t)0x000C) /*!< Capture performed once every 8 events. */
#define IS_TIM_IC_PRESCALER(PRESCALER) (((PRESCALER) == TIM_ICPSC_DIV1) || \
((PRESCALER) == TIM_ICPSC_DIV2) || \
((PRESCALER) == TIM_ICPSC_DIV4) || \
((PRESCALER) == TIM_ICPSC_DIV8))
TIM_ICFilter输入捕获滤波器
设置滤波器长度
取值范围0x00-0x16。
代码
TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1; //选择输入端 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);
中断优先级分组,设置中断优先级
使能捕获和更新中断
设置TIM5的DIER寄存器
使用定时器的开中断函数TIM_ITConfig即可使能捕获和更新中断:
TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);//允许更新中断和捕获中断
编写中断服务函数
if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET){}//判断是否为更新中断
if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET){}//判断是否发生捕获事件
TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update);//清除中断和捕获标志位
使能定时器
设置TIM5的CR1寄存器
启动TIM5的计数器,开始输入捕获。
TIM_Cmd(TIM5,ENABLE ); //使能定时器5
获取通道捕获值
uint32_t TIM_GetCapture1(TIM_TypeDef* TIMx);
捕获代码
要捕获的是高电平信号的脉宽
- 第一次捕获是上升沿,第二次捕获时下降沿,必须在捕获上升沿之后,设置捕获边沿为下降沿,同时,如果脉宽比较长,那么定时器就会溢出,对溢出必须做处理。
定时器5中断代码
void TIM5_IRQHandler(void)
{
if((TIM5CH1_CAPTURE_STA&0X80)==0)//还未成功捕获
{
if(TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)//溢出,reset=0
{
if(TIM5CH1_CAPTURE_STA&0X40)//已经捕获到高电平了
{
if((TIM5CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了00111111
{
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); //CC1P=0 设置为上升沿捕获
}else //还未开始,第一次捕获上升沿
{
TIM5CH1_CAPTURE_STA=0; //清空
TIM5CH1_CAPTURE_VAL=0;
TIM5CH1_CAPTURE_STA|=0X40; //标记捕获到了上升沿
TIM_Cmd(TIM5,DISABLE ); //关闭定时器5
TIM_SetCounter(TIM5,0);
TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling); //CC1P=1 设置为下降沿捕获
TIM_Cmd(TIM5,ENABLE ); //使能定时器5
}
}
}
TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位
}
主函数代码
int main(void)
{
long long temp=0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
delay_init(168); //初始化延时函数
uart_init(115200);//初始化串口波特率为115200
TIM14_PWM_Init(500-1,84-1); //84M/84=1Mhz的计数频率计数到500,PWM频率为1M/500=2Khz
TIM5_CH1_Cap_Init(0XFFFFFFFF,84-1); //以1Mhz的频率计数 。把ARR设置到了最大值。分频到1M
while(1)
{
delay_ms(10);
if(TIM5CH1_CAPTURE_STA&0X80) //成功捕获到了一次高电平
{
temp=TIM5CH1_CAPTURE_STA&0X3F;
temp*=0XFFFFFFFF; //溢出时间总和。每次溢出的次数就是0xFFFFFFFF,有temp次
temp+=TIM5CH1_CAPTURE_VAL; //得到总的高电平时间
printf("HIGH:%lld us\r\n",temp); //打印总的高点平时间
TIM5CH1_CAPTURE_STA=0; //开启下一次捕获
}
}
}