FREERTOS 超声波

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

插线:

第一个超声波 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_ */

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值