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

文章目录[隐藏]

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);

}

版权声明:本文为CSDN博主「tslids」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/tsliuch/article/details/121690947

生成海报
点赞 0

tslids

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

ESP32学习记录<四>ADC和DAC

ESP32学习记录ADC和DAC 前言 ADC和DAC是单片机比较常用的,ESP32具有12位的ADC和8位的DAC。今天我就简单地记录它们的使用。 一、ADC ADC也就是我们通常所说的模数转换,模拟信号

ESP32_IDF学习(2)--GPIO

简介 ESP32 芯片有 40 个物理 GPIO pad。每个 pad 都可用作一个通用 IO,或连接一个内部的外设信号。IO_MUX、RTC IO_MUX 和 GPIO 交换矩阵用于将信号从外设传输至 GPIO pad。这些模块

PCM开发板模块指令详解--功能指令4

25         MODBUS RTU指令 编号         指令名          参数1    参数2    参数3   参数4    参数5       说明 1          modbusrtum       K