ESP32学习(5):ESP32-S3上串口收发

 系列文章目录

ESP32学习(1):ESP-IDF基于Visual Studio Code环境

ESP32学习(2):ESP32-S3上运行hello world

ESP32学习(3):ESP32上运行ILI9341驱动LCD

ESP32学习(4):ESP32-S3上实现ILI9488驱动LCD的显示

前言

一、串口初始化

二、串口发送

三、串口接收

四、其他任务中处理串口接收数据

总结



前言

提示:串口收发是常用的功能,这里先整理记录一下。主要包含初始化,发送数据,接收数据,任务建立与消息队列。

一、串口初始化

串口1初始化,主要初始化管脚,接收缓冲区大小,波特率等常用参数。

#include "driver/uart.h"
#define TXD_PIN (GPIO_NUM_14) //串口1发送管脚
#define RXD_PIN (GPIO_NUM_13) //串口1接收管脚


static const int RX_BUF_SIZE = 1024;  //串口接收缓冲区大小


void init_uart(void)        
{
    const uart_config_t uart_config = {
        .baud_rate = 115200,
        .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,
    };


    uart_driver_install(UART_NUM_1, RX_BUF_SIZE * 2, 0, 0, NULL, 0);
    uart_param_config(UART_NUM_1, &uart_config);
    uart_set_pin(UART_NUM_1, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
}

二、串口发送

串口发送,主要调用库里面的函数

int uart_write_bytes(uart_port_t uart_num, const void *src, size_t size)

 例如发送版本号,如下:

#define SOFT_VER  "Ver: 4.7.5"
static void send_ver(void)
{
    const char *data = SOFT_VER;
    const int len = strlen(data);
    uart_write_bytes(UART_NUM_1, data, len);
}

发送8个字节具体的数据,如下:

static void send_info(uint8_t flag_info,uint8_t s0_info,uint16_t s1_info, uint16_t s2_info)
{
    uint8_t buf_tx[8];
    const int len = 8;
    buf_tx[0] = 0x23;
    buf_tx[1] = 0x66;
    buf_tx[2] = flag_info; 
    buf_tx[3] = s0_info ;
    buf_tx[4] = s1_info;
    buf_tx[5] = s1_info >> 8;
    buf_tx[6] = s2_info;
    buf_tx[7] = s2_info >> 8;
    uart_write_bytes(UART_NUM_1, &buf_tx[0], len);
}

三、串口接收

串口接收,主要调用uart_read_bytes函数:

int uart_read_bytes(uart_port_t uart_num, void *buf, uint32_t length, TickType_t ticks_to_wait)

可以通过建立单独的任务来接收数据。

static void rx_task(void *arg)
{
    msg_uart_rdata_t msg_uart_rdata;
    static const char *RX_TASK_TAG = "RX_TASK";
    esp_log_level_set(RX_TASK_TAG, ESP_LOG_INFO);
    uint8_t* udata = (uint8_t*) malloc(RX_BUF_SIZE+1);
    while (1) {
        const int rxBytes = uart_read_bytes(UART_NUM_1, udata, RX_BUF_SIZE, 100 / portTICK_PERIOD_MS);
        if (rxBytes > 0 ) {
            udata[rxBytes] = 0;

             //这里可以把接收的数据发送回串口1
            //uart_write_bytes(UART_NUM_1, udata, rxBytes); 

            msg_uart_rdata.u_rdata_len = rxBytes;
            msg_uart_rdata.u_rdata = (uint8_t*)malloc(rxBytes);
            for (int tmp_i = 0; tmp_i < rxBytes; tmp_i++)
            {
                /* 提取接收的数据,通过消息队列发送给其他任务来处理 */
                msg_uart_rdata.u_rdata[tmp_i] = udata[tmp_i];
            }      
            if (xQueueSend(message_queue_uart, (void *)&msg_uart_rdata, (TickType_t)300) != pdTRUE)        //消息队列发送
            {
                free(msg_uart_rdata.u_rdata);
            }
            else
            {
                /* 消息队列发送成功,同时可以发送事件组标志位 */
                xEventGroupSetBits(spi_event_group, EVENTBIT4_uart1);  
                vTaskDelay(pdMS_TO_TICKS(50));
                free(msg_uart_rdata.u_rdata);
            }                 
        }
            vTaskDelay(pdMS_TO_TICKS(20));
    }
    free(udata);
}

四、其他任务中处理串口接收数据

串口接收任务,负责接收数据,通过消息队列发送出去,同时发送事件组标志。

其他任务循环中通过查询事件组标志,判断有串口数据到来,然后接收串口消息队列中数据。

事件标志组
#define EVENTBIT0 (1 << 0)
#define EVENTBIT1 (1 << 1)
#define EVENTBIT2 (1 << 2)
#define EVENTBIT3_key (1 << 3) // 按键按下
#define EVENTBIT4_uart1 (1 << 4) // 串口接收
#define EVENTBIT5_i2c (1 << 5)   // I2C总线
#define EVENTBIT6_bmq (1 << 6) // adc采样数据发送事件组


EventGroupHandle_t spi_event_group; // 事件标志组句柄
typedef struct
{
    uint8_t *u_rdata;
    uint16_t u_rdata_len;
} msg_uart_rdata_t; // 串口队列消息缓存
static QueueHandle_t message_queue_uart;  //串口消息队列

while(1)
{ 
 uxBits = xEventGroupWaitBits(spi_event_group, EVENTBIT4_uart1 | EVENTBIT2 | EVENTBIT3_key | EVENTBIT4_am | EVENTBIT5_i2c | EVENTBIT6_adc, pdTRUE, pdFALSE, 10);
       
 if ((uxBits & EVENTBIT4_uart1) != 0)
        {
            msg_uart_rdata_t msg_uart_rdata;  //串口初始化部分有定义
            if (xQueueReceive(message_queue_uart, &msg_uart_rdata, (TickType_t)20) != pdPASS)
            {
                vTaskDelay(pdMS_TO_TICKS(100));
            }
            else
            {
                temp_rdata_len = msg_uart_rdata.u_rdata_len;
                for (int tmp_i = 0; tmp_i < temp_rdata_len; tmp_i++)
                {
                    /* 提取消息队列中的数据 */
                    udata[tmp_i] = msg_uart_rdata.u_rdata[tmp_i];
                }
                /* 接下来的程序可以处理接收过来的数据udata[] */
            }
        }
}

总结

串口接收和发送,主要是函数调用,相对比较简单,这里贴出来,方便以后调用,不用重新编写了。

  • 27
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值