这个实验大概在一个多月前就做过了,但是没写博客,现在开始做红外遥控实验需要用到输入捕获变化沿,但是这部分内容忘得一干二净了。所以重新回顾下该实验。
抛开书本,输入捕获其是就是可以捕获从定时器使能开始到触发上升沿或下降沿的时间。通俗的说就是定时器的计时是通过计数器来实现的,而硬件上又可以检测到对应管脚的变化沿,通过触发来计算时间。
t1就是从开始到触发到了上升沿的时间,t2就是从定时器开始到触发到了下降沿。ARR就是计数器的满值,我们本次实验设置为0xffffffff,向上计数,所以t1就是计数了CCRx1个定时器周期的时间。
在此图中我们要计算的是上升沿到下降沿之间的时间,也就是t2-t1的区间。
计数器值最大不超过0xffffffff,但是到达最大值只能记一次循环,然后再从0开始计数。
cubemx配置TIM5CH1为输入捕获,本次实验我们要获取到KEY_UP的高电平脉冲时间,所以根据管脚选择了TIM5CH1。
需要特别说明的是分频系数选择了90,那是为了计算时间方便,因为定时器的时钟APB1为90MHZ,如果分频90的话定时器时钟就是10MHZ。也就是说触发一次定时器,为1s/10M=1us。
由于要计算时间,所以需要用到中断来辅助计数,使能中断。
KEY_UP的IO口配置为复用功能,下拉。
生成代码后,我们先开启定时器
HAL_TIM_IC_Start_IT(&htim5,TIM_CHANNEL_1); //开启TIM5的捕获通道1,并且开启捕获中断
__HAL_TIM_ENABLE_IT(&htim5,TIM_IT_UPDATE); //使能更新中断
之后了解两个中断服务函数,第一个函数是输入捕获中断回调函数,当有变化沿的时候就会进入该函数。
//定时器输入捕获中断处理回调函数,该函数在HAL_TIM_IRQHandler中会被调用
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//捕获中断发生时执行
第二个函数是定时器的计数器计满一个周期触发的中断回调函数,也就是计数器从0到达0xffffffff的时候进入该函数。有两种情况会进入该函数,一种情况是定时器开启后在没有触发变化沿的时候也会在每次计数器值满的时候进入该中断;另一种情况是在上升沿触发后,高电平保持时间超过了计数器的周期而进入的中断,我们需要在这种情况下对进入中断的次数进行累加以算出高电平脉冲总时间。
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
在第一个上升沿的时候会进入该函数,然后设置为下降沿触发,并开启定时器。在下降沿到来的时候会再次进入,标记已经完整捕获了高电平脉冲。
该函数是定时器完成一周期就进入一次,我们判定在上升沿触发后计次数,没有触发上升沿的时候是不会计次数的。
在main()函数中,不断查询定时器是否完成了一次完整的高电平脉冲捕获,如果完成了,那么我们就可以计算这次高电平脉冲持续的时间了,见上。
输入捕获的确很精准,但是使用逻辑上有些复杂,牵扯到的函数太多,不方便使用。如果想要测量高电平脉冲时间,完全可以通过管脚的输入中断来判断是高电平,然后打开定时器,在再次触发中断是低电平的时候计算时间。
上面的认识并不正确,输入捕获很大程度上释放了CPU的资源,硬件定时器能够帮助你捕获到突变,为何要占用CPU的资源去读取GPIO状态?
输入捕获是十分有效的手段,也十分常用。