HAL库通过一个定时器实现多个超声波(HC-SR04)测距
Posted 小材大用
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HAL库通过一个定时器实现多个超声波(HC-SR04)测距相关的知识,希望对你有一定的参考价值。
环境:
1.STM32 CUBEMX
2.超声波模块HC-SR04
3.STM32F103C8T6最小系统板
实现功能:
选用两个超声波实现实时测距,并测得的距离在串口1显示。
思路:使用定时器2实现检测,但不使用定时器中断,然后通过循环检测超声波返回脉冲的形式实现距离测量。
STM32F103C8T6最小系统板
超声波模块HC-SR04
超声波原理介绍:
接线表:
超声波模块引脚 | STM32最小系统板引脚 | 设置模式 |
VCC | +5V | |
GND | GND | |
Trig1 | PA1 | 推挽输出模式 |
Echo1 | PA0 | 输入模式 |
Trig2 | PA3 | 推挽输出模式 |
Echo2 | PA6 | 输入模式 |
- | PA9 | USART1_TX |
- | PA10 | USART1_RX |
注:这里的引脚可以随便选择都可实现超声波检测
步骤1:STM32CUBEMX配置
TIM2设置的是1S溢出一次。
步骤2:功能实现
超声波1代码实现:
uint16_t SR04Distance(void)
{
uint16_t Distance;
int32_t outTime = 0;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
delay_us(15);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) != 1)
{
outTime++;
if(outTime > 100000)
{
break;
}
}
htim2.Instance->CNT = 0;
__HAL_TIM_ENABLE(&htim2);
outTime = 0;
while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) != 0)
{
outTime++;
if(outTime > 100000)
{
break;
}
}
__HAL_TIM_DISABLE(&htim2);
Distance = (uint16_t)(htim2.Instance->CNT*340/20.0);
//sprintf(str,"V1=%d\\r\\n",Distance);
//while(HAL_OK != HAL_UART_Transmit(&huart1, (uint8_t *)str, strlen(str), 5000));
return Distance;
}
超声波2代码实现,和超声波1实现效果一致
uint16_t SR04Distance2(void)
{
uint16_t Distance;
int32_t outTime = 0;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_SET);
delay_us(15);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);
while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6) != 1)
{
outTime++;
if(outTime > 100000)
{
break;
}
}
htim2.Instance->CNT = 0;
__HAL_TIM_ENABLE(&htim2);
outTime = 0;
while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6) != 0)
{
outTime++;
if(outTime > 100000)
{
break;
}
}
__HAL_TIM_DISABLE(&htim2);
Distance = (uint16_t)(htim2.Instance->CNT*340/20.0);
//sprintf(str,"V2=%d\\r\\n",Distance);
//while(HAL_OK != HAL_UART_Transmit(&huart1, (uint8_t *)str, strlen(str), 5000));
return Distance;
}
为了保证模块突发问题,我在检测高低电平的地方增加超时检测,防止程序死循环,保证程序的合理性:
while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6) != 0)
{
outTime++;
if(outTime > 100000)
{
break;
}
}
接下来实现两个超声波测距:
void UltrasonicRanging(void)
{
uint16_t Distance[10];
uint16_t Distance2[10];
uint16_t max1 = 0;
uint16_t min1 = 0;
uint16_t max2 = 0;
uint16_t min2 = 0;
int i;
SR04DistanceGlobal1 = 0; // 超声波1测得的距离清0
SR04DistanceGlobal2 = 0; // 超声波2测得的距离清0
for(i = 0;i<5;i++)
{
Distance[i] = SR04Distance();
Distance2[i] = SR04Distance2();
}
max1 = Distance[0];
max2 = Distance2[0];
min1 = Distance[0];
min2 = Distance2[0];
for(i = 0;i<5;i++)
{
if(max1 < Distance[i])
{
max1 = Distance[i];
}
if(max2 < Distance2[i])
{
max2 = Distance2[i];
}
if(min1 > Distance[i])
{
min1 = Distance[i];
}
if(min2 > Distance2[i])
{
min2 = Distance2[i];
}
SR04DistanceGlobal1 = SR04DistanceGlobal1 + Distance[i];
SR04DistanceGlobal2 = SR04DistanceGlobal2 + Distance2[i];
}
SR04DistanceGlobal1 = (uint16_t)((SR04DistanceGlobal1-max1-min1)/3);
SR04DistanceGlobal2 = (uint16_t)((SR04DistanceGlobal2-max2-min2)/3);
}
这里增加了测距的稳定性,一下测量了5次,也可以测量更多次,去除最大值和最小值,目的是防止超声波突发测距不准问题,或魔鬼值问题。
主函数中代码:
int main(void)
{
/* USER CODE BEGIN 1 */
/* 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_TIM2_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
delay_init(72);
while(HAL_OK != HAL_UART_Transmit(&huart1, "wantin", 7, 5000));
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
UltrasonicRanging();
sprintf(str,"V1=%d\\r\\n",SR04DistanceGlobal1);
while(HAL_OK != HAL_UART_Transmit(&huart1, (uint8_t *)str, strlen(str), 5000));
sprintf(str2,"V2=%d\\r\\n",SR04DistanceGlobal2);
while(HAL_OK != HAL_UART_Transmit(&huart1, (uint8_t *)str2, strlen(str2), 5000));
//HAL_Delay(20);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
将测量的结果在串口显示,显示效果如下:
具体代码实现可链接下载:
以上是关于HAL库通过一个定时器实现多个超声波(HC-SR04)测距的主要内容,如果未能解决你的问题,请参考以下文章
基于STM32F103C8T6(HAL库)的HC-SR501红外人体传感及HC-SR04超声波测距
基于STM32F103C8T6(HAL库)的HC-SR501红外人体传感及HC-SR04超声波测距