105-ESP32_SDK开发-串口,485通信

<p><iframe name="ifd" src="https://mnifdv.cn/resource/cnblogs/LearnESP32" frameborder="0" scrolling="auto" width="100%" height="1500"></iframe></p>

 

说明

模块有3个串口,每个串口管脚可以设置到任意的gpio上

模组出厂默认使用GPIO1,GPIO3作为串口0引脚(日志打印);  GPIO17,GPIO16作为串口1引脚(AT指令)

 

 

 

开发板上也把串口1连接了485上.

 

 

说明2

每个串口都有一个128字节的FIFO缓存区,知道这个就可以.

 

 

 

设置串口1,带接收缓存,不带发送缓存区的方式(最简洁的方式)

设置GPIO17,GPIO16作为串口1引脚.

没有设置发送缓存,调用 uart_write_bytes 发送数据的时候是阻塞的.

 

 

 

#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "driver/timer.h"
#include "esp_timer.h"
#include "driver/uart.h"

#define TXD1_PIN (GPIO_NUM_17) //串口1的发送数据引脚
#define RXD1_PIN (GPIO_NUM_16) //串口1的接收数据引脚
#define BUF_SIZE (1024) //接收数据缓存大小,该大小需要大于内部FIFO大小:UART_FIFO_LEN(128)
/*串口任务*/
static void uart_task(void *arg)
{
    /*配置串口参数*/
    uart_config_t uart_config = {
        .baud_rate = 115200,//波特率
        .data_bits = UART_DATA_8_BITS,//数据位8位
        .parity    = UART_PARITY_DISABLE,//无奇偶校验
        .stop_bits = UART_STOP_BITS_1,//停止位1位
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,//不使用硬件流控
        .source_clk = UART_SCLK_APB,//串口使用的时钟
    };
    /*初始化串口1*/
    uart_driver_install(UART_NUM_1, 
        BUF_SIZE, //串口1接收缓存大小
        0, //不使用发送缓存(发送数据的时候便会阻塞发送)
        0, //队列大小为0;没有使用freertos内部缓存管理
        NULL, //不使用QueueHandle_t 内部缓存管理,设置为空
        0 //设置串口中断优先级,设置为0意味着让系统从1-3级中自动选择一个
    );
    /*设置串口参数*/
    uart_param_config(UART_NUM_1, &uart_config);
    /*设置串口的TX,RX,RTS,DTR引脚*/             //不使用RTS,DTR
    uart_set_pin(UART_NUM_1, TXD1_PIN, RXD1_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
    /*申请一块内存,用于临时存储接收的数据*/
    uint8_t *data = (uint8_t *) malloc(BUF_SIZE);
    while (1) {
        //接收串口数据                                         //每隔10ms判断一次,可以写成portMAX_DELAY(一直判断)
        int len = uart_read_bytes(UART_NUM_1, data, BUF_SIZE, 10 / portTICK_RATE_MS);
        //把接收的数据发送出去
        uart_write_bytes(UART_NUM_1, (const char *) data, len);
    }
}
void app_main(void)
{
    xTaskCreate(uart_task, "uart_task", 2048, NULL, 10, NULL);
}

 

下载程序到开发板以后可以通过串口测试

 

 

485接口默认连接串口1,也可以使用485进行通讯

 

 

发送什么数据将会返回什么数据

 

 

 

 

设置串口1,带接收缓存,带发送缓存区的方式

设置上发送缓存区以后,调用 uart_write_bytes 发送数据的时候,将不会阻塞在那里.

 

 

 

 

设置串口1,带接收缓存,带发送缓存区,并使用上freertos内部的缓存管理的方式

加上缓存管理

 

 

从缓存管理中获取数据

 

 

 

#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "driver/timer.h"
#include "esp_timer.h"
#include "driver/uart.h"

#define TXD1_PIN (GPIO_NUM_17) //串口1的发送数据引脚
#define RXD1_PIN (GPIO_NUM_16) //串口1的接收数据引脚
#define BUF_SIZE (1024) //接收数据缓存大小,该大小需要大于内部FIFO大小:UART_FIFO_LEN(128)

#define BUF_SEND_SIZE (1024) //发送数据缓存大小,该大小需要大于内部FIFO大小:UART_FIFO_LEN(128)


static QueueHandle_t QueueHandle_t_uart1;

/*串口任务*/
static void uart_task(void *arg)
{
    /*配置串口参数*/
    uart_config_t uart_config = {
        .baud_rate = 115200,//波特率
        .data_bits = UART_DATA_8_BITS,//数据位8位
        .parity    = UART_PARITY_DISABLE,//无奇偶校验
        .stop_bits = UART_STOP_BITS_1,//停止位1位
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,//不使用硬件流控
        .source_clk = UART_SCLK_APB,//串口使用的时钟
    };
    /*初始化串口1*/
    uart_driver_install(UART_NUM_1, 
        BUF_SIZE, //串口1接收缓存大小
        BUF_SEND_SIZE, //串口1发送缓存大小
        10, //队列大小为10
        &QueueHandle_t_uart1, //缓存管理
        0 //设置串口中断优先级,设置为0意味着让系统从1-3级中自动选择一个
    );
    /*设置串口参数*/
    uart_param_config(UART_NUM_1, &uart_config);
    /*设置串口的TX,RX,RTS,DTR引脚*/             //不使用RTS,DTR
    uart_set_pin(UART_NUM_1, TXD1_PIN, RXD1_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

    /*申请一块内存,用于临时存储接收的数据*/
    uint8_t *data = (uint8_t *) malloc(BUF_SIZE);
    uart_event_t event;
    while (1) {
        if(xQueueReceive(QueueHandle_t_uart1, (void * )&event, portMAX_DELAY))
        {
            switch(event.type) {
                case UART_DATA://接收到数据
                    //读取接收的数据
                    uart_read_bytes(UART_NUM_1, data, event.size, portMAX_DELAY);
                    //返回接收的数据
                    uart_write_bytes(UART_NUM_1, (const char*) data, event.size);
                    break;
                case UART_FIFO_OVF://FIFO溢出(建议加上数据流控制)
                    uart_flush_input(UART_NUM_1);
                    xQueueReset(QueueHandle_t_uart1);
                    break;
                case UART_BUFFER_FULL://接收缓存满(建议加大缓存 BUF_SIZE)
                    uart_flush_input(UART_NUM_1);
                    xQueueReset(QueueHandle_t_uart1);
                    break;
                case UART_BREAK://检测到接收数据中断
                    break;
                case UART_PARITY_ERR://数据校验错误
                    break;
                case UART_FRAME_ERR://数据帧错误
                    break;
                case UART_PATTERN_DET://接收到相匹配的字符(没用到)
                    break;
                default:
                    break;
            }
        }
    }
    free(data);
    data = NULL;
    vTaskDelete(NULL);
}
void app_main(void)
{
    xTaskCreate(uart_task, "uart_task", 2048, NULL, 10, NULL);
}

 

 

 

 

如果想配置串口0或者串口2

把以下变量的最后一个数字改为0或者2即可

 

 

 

 

关于模式匹配和485方向控制,参考

 

https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-reference/peripherals/uart.html?highlight=uart_pattern_det#

 

 

 

 

 

官方文档

 

posted on 2021-08-07 15:45  广源时代  阅读(2098)  评论(0编辑  收藏  举报

导航

支付宝 QQ群