基于 ESP8266_RTOS_SDK 驱动 HC-SR04

平台

芯片 ESP8266EX
模组 ESP-12F
开发板 NodeMCU
SDK ESP8266_RTOS_SDK
branch master
commit 83517ba1f5e26b9413f2ef6d2503dd73662b1272
PS HC-SR04旧版引脚5v,新版支持3.3v

code

使用内部timer调用HC-SR04,每秒测试一次距离并通过串口打印

/**
 * @brief 使用ESP8266_RTOS_SDK调用超声波测距模块HC-SR04
 * @date 2022/08/28
 * @version SDK基于 https://github.com/espressif/ESP8266_RTOS_SDK
 * @version branch master commit 83517ba1f5e26b9413f2ef6d2503dd73662b1272
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"

#include "esp_log.h"
#include "esp_system.h"

#include <string.h>
#include <sys/param.h>
#include <errno.h>

#include "FreeRTOS.h"
#include "task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_log.h"
#include "esp_netif.h"
#include "esp_event.h"
#include "esp_wifi.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "esp_spi_flash.h"
#include "lwip/err.h"
#include "lwip/sys.h"
#include "lwip/sockets.h"
#include <lwip/netdb.h>

#include "driver/gpio.h"
#include "driver/hw_timer.h"
#include "freertos/portmacro.h"

static xQueueHandle queue = NULL;

/**
 * @brief 定时器中断函数,1秒中断一次
 */
static void hw_callback(void *arg){
    gpio_set_level(GPIO_NUM_2, !gpio_get_level(GPIO_NUM_2));//LED闪烁
    uint32_t status = 0;
    xQueueSendFromISR(queue, &status, NULL);
}

/**
 * @brief 定时器初始化
 */
static void timer_init(void){
    hw_timer_init(hw_callback, NULL);
    hw_timer_set_reload(true);
    hw_timer_set_clkdiv(TIMER_CLKDIV_256);
    hw_timer_set_intr_type(TIMER_EDGE_INT);
    //80M/256 = 312500,即1秒需要31200tik;1/312500 = 0.0000032,即1tik0.0000032秒,3.2us
    hw_timer_set_load_data((TIMER_BASE_CLK >> hw_timer_get_clkdiv()));//源码限制load_data < 0x1000000
    hw_timer_enable(true);
}

/**
 * @brief IO中断函数,用于接收HC-SR04的Echo引脚反馈信号
 */
static void gpio_isr(void *arg){
    //上升沿记录count,下降沿结束记录
    switch(gpio_get_level(GPIO_NUM_5)){
        case 1:
            *(uint32_t *)arg = hw_timer_get_count_data();
            break;
        case 0:
            //观察得ESP8266内部tik使用降序,故使用减法,又因定时器1秒中断1次,即内部tik1秒清空1次,而HC-SR04最长38ms即返回,故正常情况不会出现两次计数位于两次中断周期中
            *(uint32_t *)arg -= hw_timer_get_count_data();
            uint32_t status = 1;
            xQueueSendFromISR(queue, &status, NULL);
            break;
        default:
            break;
    }
}
/**
 * @brief IO初始化
 * NodeMCU      HC-SR04
 * D1(GPIO5)    Echo
 * D2(GPIO4)    Trig
 * 3.3v         VCC
 * GND          GND
 */
static void gpio_init(){
    gpio_config_t io_conf;
    io_conf.intr_type = GPIO_INTR_DISABLE;
    io_conf.mode = GPIO_MODE_OUTPUT;
    io_conf.pin_bit_mask = 1 << GPIO_NUM_2;
    io_conf.pull_down_en = 0;
    io_conf.pull_up_en = 0;
    gpio_config(&io_conf);

    io_conf.intr_type = GPIO_INTR_ANYEDGE;//上升沿与下降沿均中断
    io_conf.mode = GPIO_MODE_INPUT;
    io_conf.pin_bit_mask = 1 << GPIO_NUM_5;
    io_conf.pull_down_en = 0;
    io_conf.pull_up_en = 0;
    gpio_config(&io_conf);

    io_conf.intr_type = GPIO_INTR_DISABLE;
    io_conf.mode = GPIO_MODE_OUTPUT;
    io_conf.pin_bit_mask = 1 << GPIO_NUM_4;

    gpio_config(&io_conf);
}

static void HC_SR04_task(void *arg)
{
    while(1){
        uint32_t status;
        xQueueReceive(queue, &status, portMAX_DELAY);
        switch(status){
            case 0:
                gpio_set_level(GPIO_NUM_4, 0);
                os_delay_us(2);
                gpio_set_level(GPIO_NUM_4, 1);
                os_delay_us(10);
                gpio_set_level(GPIO_NUM_4, 0);
                break;
            case 1:
                //tik为Echo反馈信号长度,声速0.34mm/us,实际距离除以2,3.2*0.34/2 = 0.544ms
                //本版本SDK不支持浮点数格式化输出
                printf("tik = %d length = %d um\n", *(uint32_t *)arg, *(uint32_t *)arg*544);
                break;
            default:
                break;
        }
    }
}

void app_main(void)
{
    printf("hello world!\n");

    timer_init();
    gpio_init();

    uint32_t tik = 0;//记录定时器tik次数,用于计算Echo信号长度
    queue = xQueueCreate(10, sizeof(uint32_t));
    xTaskCreate(HC_SR04_task, "HC-SR04_task", 2048, &tik, 10, NULL);

    //为GPIO5注册中断函数
    gpio_install_isr_service(0);
    gpio_isr_handler_add(GPIO_NUM_5, gpio_isr, &tik);


    // char arm_info[512] = { 0 };
    while(1) {
        printf("main is running\n");
        // vTaskList(arm_info);
        // printf("\nfree_heap = %d\n%s\n",esp_get_free_heap_size() ,arm_info);
        // memset(arm_info, 0, sizeof(arm_info));
        // vTaskGetRunTimeStats(arm_info);
        // printf("%s\n", arm_info);
        vTaskDelay(10000 / portTICK_PERIOD_MS);
    } 
}

使用CuteCom查看结果

[20:55:58:198] tik = 145 length = 7830 um␍␊
[20:55:59:198] tik = 144 length = 7776 um␍␊
[20:56:00:198] tik = 145 length = 7830 um␍␊
[20:56:01:199] tik = 154 length = 8316 um␍␊
[20:56:02:209] tik = 3337 length = 180198 um␍␊
[20:56:03:210] tik = 3185 length = 171990 um␍␊
[20:56:03:237] main is running␍␊
[20:56:04:210] tik = 3126 length = 168804 um␍␊
[20:56:05:210] tik = 3106 length = 167724 um␍␊
[20:56:06:299] tik = 31254 length = 1687716 um␍␊
[20:56:07:200] tik = 350 length = 18900 um␍␊
[20:56:08:201] tik = 342 length = 18468 um␍␊
[20:56:09:201] tik = 351 length = 18954 um␍␊
[20:56:10:201] tik = 352 length = 19008 um␍␊
[20:56:11:202] tik = 354 length = 19116 um␍␊
[20:56:12:202] tik = 355 length = 19170 um␍␊
[20:56:13:202] tik = 355 length = 19170 um␍␊
[20:56:13:240] main is running␍␊
[20:56:14:203] tik = 355 length = 19170 um␍␊
[20:56:15:203] tik = 364 length = 19656 um␍␊
[20:56:16:203] tik = 358 length = 19332 um␍␊
[20:56:17:204] tik = 358 length = 19332 um␍␊

posted @ 2022-08-28 21:03  新世纪摆烂战士  阅读(135)  评论(1编辑  收藏  举报