ESP32——串口官方例程改写为主机扫描接收方式

本文介绍如何将原基于从机的UART_events例程修改为支持主机模式,使用GPIO19发送,GPIO18接收,并实现发送数据后等待应答的超时重发功能。内容涉及UART_master.c和.h文件的修改,以及初始化、任务创建和错误处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1  改写原因

原例程为“uart_events”。

例程是基于从机方式的,即接收响应的,打算实现一个基于主机方式的,即发送等待应答(带超时处理,失败自动重发2次)。

2  改写内容

硬件上:将串口改为串口2,发送脚GPIO19,接收脚GPIO18。

将例程中串口内容,复制并做部分修改移植到新建的“uart_master.c”和“uart_master.h”文件中。

“uart_master.c”文件内容如下:

#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/uart.h"
#include "esp_log.h"
#include "uart_master.h"

static const char *TAG = "uart_events";

static QueueHandle_t rx_queue;
static uint8_t send_buf[1024]={1,2,3,4,5,6,7,8};
static uint8_t ack_ok = 0;

static void uart_rx_task(void *pvParameters)
{
    uart_event_t event;

    uint8_t* dtmp = (uint8_t*) malloc(1024);
    for(;;) {
        //Waiting for UART event.
        if(xQueueReceive(rx_queue, (void * )&event, (portTickType)portMAX_DELAY)) {
            bzero(dtmp, 1024);
            ESP_LOGI(TAG, "uart[%d] event:", UART_NUM_2);
            switch(event.type) {
                //Event of UART receving data
                /*We'd better handler data event fast, there would be much more data events than
                other types of events. If we take too much time on data event, the queue might
                be full.*/
                case UART_DATA:
                    ESP_LOGI(TAG, "[UART DATA]: %d", event.size);
                    uart_read_bytes(UART_NUM_2, dtmp, event.size, portMAX_DELAY);
                    ESP_LOGI(TAG, "[DATA EVT]:");
                    uart_write_bytes(UART_NUM_2, (const char*) dtmp, event.size);
                    ack_ok = 1;//置应答标志
                    break;
                //Event of HW FIFO overflow detected
                case UART_FIFO_OVF:
                    ESP_LOGI(TAG, "hw fifo overflow");
                    // If fifo overflow happened, you should consider adding flow control for your application.
                    // The ISR has already reset the rx FIFO,
                    // As an example, we directly flush the rx buffer here in order to read more data.
                    uart_flush_input(UART_NUM_2);
                    xQueueReset(rx_queue);
                    break;
                //Event of UART ring buffer full
                case UART_BUFFER_FULL:
                    ESP_LOGI(TAG, "ring buffer full");
                    // If buffer full happened, you should consider encreasing your buffer size
                    // As an example, we directly flush the rx buffer here in order to read more data.
                    uart_flush_input(UART_NUM_2);
                    xQueueReset(rx_queue);
                    break;
                //Event of UART RX break detected
                case UART_BREAK:
                    ESP_LOGI(TAG, "uart rx break");
                    break;
                //Event of UART parity check error
                case UART_PARITY_ERR:
                    ESP_LOGI(TAG, "uart parity error");
                    break;
                //Event of UART frame error
                case UART_FRAME_ERR:
                    ESP_LOGI(TAG, "uart frame error");
                    break;
                // case UART_RXFIFO_TOUT_INT://串口接收超时未找到相关事件,暂不通过此方式实现帧结束的判断
                //     ESP_LOGI(TAG, "uart frame end");
                //     break;
                //Others
                default:
                    ESP_LOGI(TAG, "uart event type: %d", event.type);
                    break;
            }
        }
    }
    free(dtmp);
    dtmp = NULL;
    vTaskDelete(NULL);
}

int sendData(const uint8_t* data,uint16_t len)
{
    const int txBytes = uart_write_bytes(UART_NUM_2, data, len);
    // ESP_LOGI(UART_NUM_0, "Wrote %d bytes", txBytes);
    return txBytes;
}

static void uart_tx_task(void *arg)
{
    static const char *TX_TASK_TAG = "TX_TASK";
    esp_log_level_set(TX_TASK_TAG, ESP_LOG_INFO);
    while (1) {
        
        for(int i=0;i<3;i++)//最多重发3次
        {
            vTaskDelay(10 / portTICK_PERIOD_MS);//发送间隔10ms
            uart_write_bytes(UART_NUM_2, send_buf, 6);
            ack_ok = 0;
            for(int t=0;t<500;t++)//最多等待5秒
            {
                vTaskDelay(10 / portTICK_PERIOD_MS);
                if(ack_ok) break;//每10毫秒判断收到应答则退出循环
            }
            if(ack_ok) break;//收到应答则退出循环不进行重发
        } 
        //进行应答成功或失败的相关处理       
        if(ack_ok)
        {
            ESP_LOGI(TAG, "ACK: OK");
        }
        else
        {
            ESP_LOGI(TAG, "ACK: ERROR");
        }        
    }
}

esp_err_t uart2_init(int baud,int bufSize)
{
    esp_log_level_set(TAG, ESP_LOG_INFO);

    /* Configure parameters of an UART driver,
     * communication pins and install the driver */
    uart_config_t uart_config = {
        .baud_rate = baud,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_APB,
    };
    //Install UART driver, and get the queue.
    uart_driver_install(UART_NUM_2, bufSize * 2, bufSize * 2, 20, &rx_queue, 0);
    uart_param_config(UART_NUM_2, &uart_config);

    //Set UART log level
    esp_log_level_set(TAG, ESP_LOG_INFO);
    //Set UART pins 
    uart_set_pin(UART_NUM_2, 19, 18, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

    //Reset the pattern queue length to record at most 20 pattern positions.
    uart_pattern_queue_reset(UART_NUM_2, 20);

    uart_enable_rx_intr(UART_NUM_2);
    //创建发送和接收任务
    xTaskCreate(uart_rx_task, "uart_rx_task", bufSize*2, NULL, configMAX_PRIORITIES-2, NULL);
    xTaskCreate(uart_tx_task, "uart_tx_task", bufSize*2, NULL, configMAX_PRIORITIES-1, NULL);   
    return ESP_OK; 
}

“uart_master.h”文件内容如下:

#pragma once

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>


#ifdef __cplusplus
extern "C" {
#endif

esp_err_t uart2_init(int baud,int bufSize);


#ifdef __cplusplus
}
#endif

修改“uart_events_example_main.c”文件

/* UART Events Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/uart.h"
#include "esp_log.h"

#include "uart_master.h"


void app_main(void)
{
    uart2_init(19200,1024);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值