配置过程需要开中断,设置第四行为最大值。插线要检查,包括插线的正确性,与第二个超声波经常松动导致不能读取数据。第一个超声波是后加的,第二个对应车尾,第三个超声波对应车头
插线:
第一个超声波 TRIG A1 ; ECHO A0;
第二个超声波 TRIG C6 ; ECHO B10;
第三个超声波 TRIG B12 ; ECHO B6;

使用了三个超声波,分别对应TIM2 CH1 ; TIM2 CH3 ; TIM4 CH1。前两个放在一个任务中,最后一个单独任务。
void HC04(void const * argument)
{
/* USER CODE BEGIN HC04 */
TIM1_Init();
HC_SR04_Init(); // 初始化第一个超声波(TIM2_CH1)
HC_SR04_2_Init(); // 初始化第二个超声波(TIM2_CH3)
for (;;)
{
uint32_t d1 = HC_SR04_Read(); // 读取第一个传感器的距离
vTaskDelay(pdMS_TO_TICKS(60));
uint32_t d2 = HC_SR04_2_Read(); // 读取第二个传感器的距离
if (xSemaphoreTake(xDataMutex, portMAX_DELAY)) {
g_distance = d1;
g_distance2 = d2;
xSemaphoreGive(xDataMutex);
}
//vTaskDelay(pdMS_TO_TICKS(100)); // 一次完整测量后等一下
}
/* USER CODE END HC04 */
}
第二个任务:
void MYHC04_2(void const * argument)
{
/* USER CODE BEGIN MYHC04_2 */
HC_SR04_3_Init(); // 初始化第二个超声波(TIM2_CH3)
for (;;)
{
uint32_t d3 = HC_SR04_3_Read(); // 读取第二个传感器的距离
if (xSemaphoreTake(xDataMutex, portMAX_DELAY)) {
g_distance3 = d3;
xSemaphoreGive(xDataMutex);
}
vTaskDelay(pdMS_TO_TICKS(100)); // 一次完整测量后等一下
}
/* Infinite loop */
/* USER CODE END MYHC04_2 */
}
驱动函数:
#include "stm32f4xx_hal.h"
#include "hc_sr04-driver.h"
extern TIM_HandleTypeDef htim2; // 来自 main.c 或 tim.c
extern TIM_HandleTypeDef htim3;
extern TIM_HandleTypeDef htim4;
static uint32_t ic_val1 = 0;
static uint32_t ic_val2 = 0;
static uint8_t is_first_capture = 0;
static uint32_t distance = 0;
static uint8_t measure_done = 0;
static uint8_t is_first_capture_3 = 0;
static uint32_t ic_val5 = 0;
static uint32_t ic_val6 = 0;
static uint32_t measure_done_3 = 0;
static uint32_t distance3 = 0;
#define TRIG_GPIO_PORT GPIOA
#define TRIG_PIN GPIO_PIN_1
static uint8_t is_first_capture_2 = 0;
static uint32_t measure_done_2 = 0;
static uint32_t distance2 = 0;
static uint32_t ic_val3 = 0;
static uint32_t ic_val4 = 0;
void HC_SR04_Init(void)
{
// TRIG引脚配置(由CubeMX初始化也可以)
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = TRIG_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(TRIG_GPIO_PORT, &GPIO_InitStruct);
HAL_GPIO_WritePin(TRIG_GPIO_PORT, TRIG_PIN, GPIO_PIN_RESET);
// 启用输入捕获中断
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
}
void HC_SR04_Trigger(void)
{
HAL_GPIO_WritePin(TRIG_GPIO_PORT, TRIG_PIN, GPIO_PIN_SET);
delay_us(10);
HAL_GPIO_WritePin(TRIG_GPIO_PORT, TRIG_PIN, GPIO_PIN_RESET);
}
uint32_t HC_SR04_Read(void)
{
is_first_capture = 0;
measure_done = 0;
__HAL_TIM_SET_COUNTER(&htim2, 0); // 计数器清零
HC_SR04_Trigger();
// 等待完成(建议改为信号量方式,避免阻塞)
uint32_t timeout = 100000;
while (!measure_done && timeout--) {
delay_us(1);
}
return distance;
}
#define TRIG2_GPIO_PORT GPIOC
#define TRIG2_PIN GPIO_PIN_6
void HC_SR04_2_Init(void)
{
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = TRIG2_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(TRIG2_GPIO_PORT, &GPIO_InitStruct);
HAL_GPIO_WritePin(TRIG2_GPIO_PORT, TRIG2_PIN, GPIO_PIN_RESET);
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_3);
}
void HC_SR04_2_Trigger(void)
{
HAL_GPIO_WritePin(TRIG2_GPIO_PORT, TRIG2_PIN, GPIO_PIN_SET);
delay_us(10);
HAL_GPIO_WritePin(TRIG2_GPIO_PORT, TRIG2_PIN, GPIO_PIN_RESET);
}
uint32_t HC_SR04_2_Read(void)
{
is_first_capture_2 = 0;
measure_done_2 = 0;
__HAL_TIM_SET_COUNTER(&htim2, 0);
HC_SR04_2_Trigger();
uint32_t timeout = 100000;
while (!measure_done_2 && timeout--) {
delay_us(1);
}
return distance2;
}
#define TRIG3_GPIO_PORT GPIOB
#define TRIG3_PIN GPIO_PIN_12
void HC_SR04_3_Init(void)
{
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = TRIG3_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(TRIG3_GPIO_PORT, &GPIO_InitStruct);
HAL_GPIO_WritePin(TRIG3_GPIO_PORT, TRIG3_PIN, GPIO_PIN_RESET);
HAL_TIM_IC_Start_IT(&htim4, TIM_CHANNEL_1);
}
void HC_SR04_3_Trigger(void)
{
HAL_GPIO_WritePin(TRIG3_GPIO_PORT, TRIG3_PIN, GPIO_PIN_SET);
delay_us(10);
HAL_GPIO_WritePin(TRIG3_GPIO_PORT, TRIG3_PIN, GPIO_PIN_RESET);
}
uint32_t HC_SR04_3_Read(void)
{
is_first_capture_3 = 0;
measure_done_3 = 0;
__HAL_TIM_SET_COUNTER(&htim4, 0);
HC_SR04_3_Trigger();
uint32_t timeout = 100000;
while (!measure_done_3 && timeout--) {
delay_us(1);
}
return distance3;
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM2 && htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
if (is_first_capture == 0)
{
ic_val1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
__HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING);
is_first_capture = 1;
}
else
{
ic_val2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
__HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);
uint32_t diff = (ic_val2 > ic_val1) ? (ic_val2 - ic_val1) : (0xFFFF - ic_val1 + ic_val2);
distance = diff / 58; // us 转 cm
measure_done = 1;
}
}
if (htim->Instance == TIM2 && htim->Channel == HAL_TIM_ACTIVE_CHANNEL_3)
{
if (is_first_capture_2 == 0)
{
ic_val3 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_3);
__HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_3, TIM_INPUTCHANNELPOLARITY_FALLING);
is_first_capture_2 = 1;
}
else
{
ic_val4 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_3);
__HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_3, TIM_INPUTCHANNELPOLARITY_RISING);
uint32_t diff = (ic_val4 > ic_val3) ? (ic_val4 - ic_val3) : (0xFFFF - ic_val3 + ic_val4);
distance2 = diff / 58;
measure_done_2 = 1;
}
}
if (htim->Instance == TIM4 && htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
if (is_first_capture_3 == 0)
{
ic_val5 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
__HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING);
is_first_capture_3 = 1;
}
else
{
ic_val6 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
__HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);
uint32_t diff = (ic_val6 > ic_val5) ? (ic_val6 - ic_val5) : (0xFFFF - ic_val5 + ic_val6);
distance3 = diff / 58;
measure_done_3 = 1;
}
}
}
头文件
#ifndef INC_DRIVERS_HC_SR04_DRIVER_H_
#define INC_DRIVERS_HC_SR04_DRIVER_H_
#include <stdint.h>
void HC_SR04_Init(void);
void HC_SR04_Trigger(void);
uint32_t HC_SR04_Read(void);
void HC_SR04_2_Init(void);
void HC_SR04_2_Trigger(void);
uint32_t HC_SR04_2_Read(void);
void HC_SR04_3_Init(void);
void HC_SR04_3_Trigger(void);
uint32_t HC_SR04_3_Read(void);
#endif /* INC_DRIVERS_HC_SR04_DRIVER_H_ */
对应delay.c
#include "stm32f4xx.h"
#include "delay.h"
#include "FreeRTOS.h"
#include "task.h"
void TIM1_Init(void) {
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; // 使能DWT
DWT->CYCCNT = 0; // 清除计数器
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; // 启动计数器
}
void delay_us(uint32_t us) {
uint32_t cycles = (SystemCoreClock / 1000000) * us;
uint32_t start = DWT->CYCCNT;
while ((DWT->CYCCNT - start) < cycles);
}
void delay_ms(uint32_t ms) {
vTaskDelay(pdMS_TO_TICKS(ms));
}
delay.h
#ifndef INC_DRIVERS_DELAY_H_
#define INC_DRIVERS_DELAY_H_
void delay_us(uint32_t us);
void delay_ms(uint32_t ms);
void TIM1_Init(void);
#endif /* INC_DRIVERS_DELAY_H_ */
1026

被折叠的 条评论
为什么被折叠?



