在输入捕获模式下,当边沿来临时,可以将计数器的数值记录到捕获寄存器当中,记录边沿的发生时刻。
输入捕获模式
在输入捕获模式下,输入通道会经过一个预分频器后连接到捕获寄存器上。当定时器输入通道检测到上升沿(或下降沿)时,立即将此时计数器的数值记录到捕获寄存器中。若为此捕获开启了中断,则还会触发输入捕获中断。

但是,此处的边沿检测器只能检测上边沿或者下边沿,不能双边沿检测。但是,借助输入捕获的直接模式和间接模式,我们可以实现记录一条信号线上的上升沿与下降沿:
- TI1从边沿检测器会输出TI1FP1和TI1FP2,其中TI1FP1连接到捕获寄存器1,而TI1FP2连接到捕获寄存器2;
- TI2从边沿检测器会输出TI2FP1和TI2FP2,同样地TI2FP1连接到捕获寄存器1,TI2FP2连接到捕获寄存器2。
TI1在自己的捕获寄存器1上进行输入捕获就是直接模式,而在捕获寄存器2上进行输入捕获就是间接模式。
借助直接模式和间接模式,我们就可以实现一个GPIO口的信号在两个端口进行捕获,间接地实现了双边沿检测。

当然,除了TI1和TI2这一对输入信号可以互相借用对方的捕获寄存器,TI3和TI4也有相同的机制。

芯片配置
本文章中使用HC-SR04超声波模块,最终显示超声波测距的结果。
分析:HC-SR04在接收到电平脉冲后会发送超声波,然后检测反射回来的超声波。发射超声波时会将输出电平信号拉高,而接收到超声波时会将输出电平信号拉低,因此只要通过定时器的输入捕获模式,得知拉高和拉低的时间戳,再通过简单的计算,便可得到距离。
- 在Clock Configuration中将HCLK改为72MHz;
- 在CubeMX左侧Timers中点开TIM1,选择Internal Clock,并将Channel3设置为Input Capture direct mode(输入捕获直接模式),Channel 4设置为Input Capture indirect mode(输入捕获间接模式)。;
- 在下方的设置中,将Prescaler设置为72-1,即每1微秒,计数器+1;
- 在更下方的Input Capture Channel 4中,需要将Polarity Selection更改为Falling Edge,用于在下降沿时记录计数器的值;
- 此外,还需要用到中断用于获取数据信息,因此在NVIC中将TIM1 capture compare interrupt启用;
- 最后,再单独设置一个GPIO口为GPIO_Output用于发送脉冲启动HC-SR04模块。
代码配置
函数HAL_TIM_IC_Start和HAL_TIM_IC_Start_IT用于启用输入捕获:
HAL_TIM_Base_Start(&htim1);HAL_TIM_IC_Start(&htim1, TIM_CHANNEL_3);HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_4);其中HAL_TIM_IC_Start(&htim1, TIM_CHANNEL_3):
&htim1:启用的定时器的句柄;TIM_CHANNEL_3:启用的定时器的通道。
捕获中断回调函数是HAL_TIM_IC_CaptureCallback,我们将其重定义,用于对数据进行处理:
#define SPEED 0.34bool is_mesuring = false;int up_edge_timestamp=0,down_edge_timestamp=0;struct{ int integer; int floating;}distance={ .integer=0, .floating=0};void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){ if((htim==&htim1) && ((htim->Channel)==HAL_TIM_ACTIVE_CHANNEL_4)){ up_edge_timestamp=HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_3); down_edge_timestamp=HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_4); distance.integer=(int)(((down_edge_timestamp-up_edge_timestamp)*SPEED)/2.0); distance.floating=(int)(((((down_edge_timestamp-up_edge_timestamp)*SPEED)/2.0)-distance.integer)*100);//保留两位小数 is_mesuring=false; return; }}在死循环中实现向HC-SR04发送脉冲以测距,以及将测距结果显示在OLED屏幕上:
char sendBuffer[20]="";while (1){ if (is_mesuring==false){ HAL_GPIO_WritePin(Trigger_GPIO_Port, Trigger_Pin, GPIO_PIN_SET); HAL_Delay(1); HAL_GPIO_WritePin(Trigger_GPIO_Port, Trigger_Pin, GPIO_PIN_RESET); __HAL_TIM_SET_COUNTER(&htim1, 0); is_mesuring=true; } OLED_NewFrame(); sprintf(sendBuffer,"distance:%d.%d",distance.integer,distance.floating); OLED_PrintString(0, 0, sendBuffer, &font16x16, OLED_COLOR_NORMAL); OLED_ShowFrame();}TIP在发送脉冲后,使用
__HAL_TIM_SET_COUNTER(&htim1, 0);立即将计数器归零,可以防止下降沿数值比上升沿数值小。
总结
相关函数
HAL_TIM_IC_Start(TIM_HandleTypeDef *htim, uint32_t Channel);//输入捕获模式启动HAL_TIM_IC_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel);//输入捕获模式启动(中断模式)HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim);//输入捕获中断回调函数输入捕获模式
在输入捕获模式下,当边沿来临时,可以将计数器的数值记录到捕获寄存器当中,记录边沿的发生时刻。
部分信息可能已经过时





