HAL实现多个超声波测距(输入捕获实现)
Posted 小材大用
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HAL实现多个超声波测距(输入捕获实现)相关的知识,希望对你有一定的参考价值。
超声波工作原理可参考博客:
(2条消息) HAL库实现定时器实现多个超声波(HC-SR04)测距_XiaoCaiDaYong的博客-CSDN博客
环境:
1.STM32 CUBEMX
2.超声波模块HC-SR04
3.STM32F103C8T6最小系统板
实现功能:
选用两个超声波实现实时测距,并测得的距离在串口1显示。
思路:使用定时器2实现输入捕获测距。
超声波模块引脚 | STM32最小系统板引脚 | 设置模式 |
VCC | +5V | |
GND | GND | |
Trig1 | PA1 | 推挽输出模式 |
Echo1 | PA0 | TIM2_CH1 |
Trig2 | PA3 | 推挽输出模式 |
Echo2 | PA6 | TIM3_CH1 |
- | PA9 | USART1_TX |
- | PA10 | USART1_RX |
CUBEMX配置:
功能实现:
void ch1_capture(void)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
delay_us(20);
//HAL_Delay(1);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
}
void ch3_capture(void)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_SET);
delay_us(20);
//HAL_Delay(1);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);
}
定时器中断回调:
/* USER CODE BEGIN 4 */
//定时器更新中断(计数溢出)中断处理回调函数, 该函数在HAL_TIM_IRQHandler中会被调用
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//更新中断(溢出)发生时执行
{
if(htim->Instance == htim2.Instance)
{
if((TIM2CH1_CAPTURE_STA&0X80)==0) //还未成功捕获上升沿
{
if(TIM2CH1_CAPTURE_STA&0X40) //已经捕获到高电平了
{
if((TIM2CH1_CAPTURE_STA&0X3F)==0X3F) //高电平太长了
{
TIM2CH1_CAPTURE_STA|=0X80; //标记成功捕获了一次
TIM2CH1_CAPTURE_VAL=0XFFFF;
}else TIM2CH1_CAPTURE_STA++;
}
}
}
if(htim->Instance == htim3.Instance)
{
if((TIM3CH1_CAPTURE_STA&0X80)==0) //还未成功捕获上升沿
{
if(TIM3CH1_CAPTURE_STA&0X40) //已经捕获到高电平了
{
if((TIM3CH1_CAPTURE_STA&0X3F)==0X3F) //高电平太长了
{
TIM3CH1_CAPTURE_STA|=0X80; //标记成功捕获了一次
TIM3CH1_CAPTURE_VAL=0XFFFF;
}else TIM3CH1_CAPTURE_STA++;
}
}
}
}
//定时器输入捕获中断处理回调函数,该函数在HAL_TIM_IRQHandler中会被调用
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//捕获中断发生时执行
{
if(htim->Instance == htim2.Instance)
{
if((TIM2CH1_CAPTURE_STA&0X80)==0) //还未成功捕获
{
if(TIM2CH1_CAPTURE_STA&0X40) //捕获到一个下降沿
{
TIM2CH1_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽
TIM2CH1_CAPTURE_VAL=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);//获取当前的捕获值.
TIM_RESET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1); //一定要先清除原来的设置!!
TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING);//配置TIM2通道1上升沿捕获
}else //还未开始,第一次捕获上升沿
{
TIM2CH1_CAPTURE_STA=0; //清空
TIM2CH1_CAPTURE_VAL=0;
TIM2CH1_CAPTURE_STA|=0X40; //标记捕获到了上升沿
__HAL_TIM_DISABLE(&htim2); //关闭定时器2
__HAL_TIM_SET_COUNTER(&htim2,0);
TIM_RESET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1); //一定要先清除原来的设置!!
TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);//定时器2通道1设置为下降沿捕获
__HAL_TIM_ENABLE(&htim2); //使能定时器2
}
}
}
if(htim->Instance == htim3.Instance)
{
if((TIM3CH1_CAPTURE_STA&0X80)==0) //还未成功捕获
{
if(TIM3CH1_CAPTURE_STA&0X40) //捕获到一个下降沿
{
TIM3CH1_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽
TIM3CH1_CAPTURE_VAL=HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1);//获取当前的捕获值.
TIM_RESET_CAPTUREPOLARITY(&htim3,TIM_CHANNEL_1); //一定要先清除原来的设置!!
TIM_SET_CAPTUREPOLARITY(&htim3,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING);//配置TIM2通道1上升沿捕获
}else //还未开始,第一次捕获上升沿
{
TIM3CH1_CAPTURE_STA=0; //清空
TIM3CH1_CAPTURE_VAL=0;
TIM3CH1_CAPTURE_STA|=0X40; //标记捕获到了上升沿
__HAL_TIM_DISABLE(&htim3); //关闭定时器2
__HAL_TIM_SET_COUNTER(&htim3,0);
TIM_RESET_CAPTUREPOLARITY(&htim3,TIM_CHANNEL_1); //一定要先清除原来的设置!!
TIM_SET_CAPTUREPOLARITY(&htim3,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);//定时器2通道1设置为下降沿捕获
__HAL_TIM_ENABLE(&htim3); //使能定时器2
}
}
}
}
/* USER CODE END 4 */
主函数实现:
int main(void)
{
/* USER CODE BEGIN 1 */
float len=0;
uint16_t dis = 0;
uint32_t time=0;
char str[20] ="";
char str3[20] ="";
float len3=0;
uint16_t dis3 = 0;
uint32_t time3=0;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_TIM2_Init();
MX_TIM3_Init();
/* USER CODE BEGIN 2 */
delay_init(72);
while(HAL_OK != HAL_UART_Transmit(&huart1, "wantin", 7, 5000));
HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1); //开启TIM5的捕获通道1,并且开启捕获中断
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1); //开启TIM5的捕获通道1,并且开启捕获中断
__HAL_TIM_ENABLE_IT(&htim2,TIM_IT_UPDATE); //使能更新中断
__HAL_TIM_ENABLE_IT(&htim3,TIM_IT_UPDATE); //使能更新中断
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
ch1_capture(); //
ch3_capture(); //
if(TIM2CH1_CAPTURE_STA&0X80) //成功捕获到了一次高电平
{
time=TIM2CH1_CAPTURE_STA&0X3F;
time*=65536; //溢出时间总和
time+=TIM2CH1_CAPTURE_VAL; //得到总的高电平时间
len=time*0.17;
dis = (uint16_t)len;
sprintf(str,"v1=%d\\r\\n",dis);
while(HAL_OK != HAL_UART_Transmit(&huart1, (uint8_t *)str, strlen(str), 5000));
TIM2CH1_CAPTURE_STA=0; //开启下一次捕获
}
if(TIM3CH1_CAPTURE_STA&0X80) //成功捕获到了一次高电平
{
time3=TIM3CH1_CAPTURE_STA&0X3F;
time3*=65536; //溢出时间总和
time3+=TIM3CH1_CAPTURE_VAL; //得到总的高电平时间
len3=time3*0.17;
dis3 = (uint16_t)len3;
sprintf(str3,"v2=%d\\r\\n",dis3);
while(HAL_OK != HAL_UART_Transmit(&huart1, (uint8_t *)str3, strlen(str3), 5000));
TIM3CH1_CAPTURE_STA=0; //开启下一次捕获
}
HAL_Delay(100);
}
/* USER CODE END 3 */
}
实现效果:
具体代码实现可链接下载:
(2条消息) HAL实现多个超声波测距(输入捕获实现)-C文档类资源-CSDN文库
以上是关于HAL实现多个超声波测距(输入捕获实现)的主要内容,如果未能解决你的问题,请参考以下文章
基于STM32F103C8T6(HAL库)的HC-SR501红外人体传感及HC-SR04超声波测距