ESP32 + ESP-IDF | 串口1 - 简单的串口回环测试

一、前言


在这里插入图片描述
测试串口外设最省事的方法是串口回环测试,因为串口回环测试不需要外部串口工具。本实验使用GPIO23作为UART1_TX,GPIO18作为UART1_RX,然后在电路上只需用一根杜邦线将GPIO23与GPIO18连接起来即可。

ESP-IDF打印的信息:
在这里插入图片描述
从Monitor反馈的logo可以看到,串口1接收到字符串“hello,world”,然后通过函数strlen( )获取收到的字符串的长度(长度是11)。

串口0(UART0)一般被用于下载与监控程序,所以最好不要用于开发功能。

二、VSCODE + ESP-IDF


2.1、快速创建项目

按照第一章节的方式创建一个sample_project的模版。ESP32 + ESP-IDF |GPIO 01 - 驱动外部两个LED灯,以每300ms的时间间隔闪烁

2.2、选择串口通道,ESP芯片型号

还是按照第一章节的方式来选择串口通道与ESP芯片信号

三、代码


官方文档:https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-reference/peripherals/uart.html

3.1、头文件

使用ESP32的串口外设时,需要包含头文件“driver/uart.h”.
在这里插入图片描述

3.2、全局变量

在这里插入图片描述

  • 数组msg_test[] :其实就是一个字符串,这个数组将被uart1发送出去,然后被uart1接收回来(回环测试)。
  • 数组buffer[UART1_RX_BUF_SIZE]:用于暂时存储uart1接收回来的字符串。
  • 结构体uart1_config:用于初始化uart1的功能(波特率,数据位的个数等)。

3.3、app_main( )函数

在这里插入图片描述

3.4、实验代码

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

#define UART1_TX_BUF_SIZE 256    /* 256个字节 */
#define UART1_RX_BUF_SIZE 256    /* 256个字节 */

static const char *TAG = "UART section0";
static uint8_t s_led_state = 0;

static char msg_test[] = "hello,world";  /* 测试使用的字符串 */
static char buffer[UART1_RX_BUF_SIZE];   /* 暂时存储从串口接收到的字符串 */

/* 串口1的配置 */
const uart_config_t uart1_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,           /* APB时钟 */
};


void app_main(void)
{
    
    
    ESP_LOGI(TAG, "Example configured to uart communication");

    /* 复位GPIO的状态 */
    gpio_reset_pin(26);

    /* 设置GPIO26为输出模式 */
    gpio_set_direction(26,GPIO_MODE_OUTPUT);

    /* 设置串口1的参数 */
    ESP_ERROR_CHECK(uart_param_config(UART_NUM_1,&uart1_config));

    /* 设置串口的gpio口,esp32支持gpio口动态设置,这一次先使用默认的串口gpio */
    ESP_ERROR_CHECK(uart_set_pin(UART_NUM_1,GPIO_NUM_23,GPIO_NUM_18,UART_PIN_NO_CHANGE,UART_PIN_NO_CHANGE));

    /* 启动串口1 */
    ESP_ERROR_CHECK(uart_driver_install(UART_NUM_1,         /* 串口1 */
                        UART1_TX_BUF_SIZE,  /* 发送FIFO的大小 */
                        UART1_RX_BUF_SIZE,  /* 接受FIFO的大小 */
                        0,                  /* 不使用queue */
                        NULL,               /* 因为不使用queue,所以NULL */
                        0)                  /* 不分配中断标志 */  
                    );                 

    while(1)
    {
    
    
        uart_write_bytes(UART_NUM_1,msg_test,strlen(msg_test));  /* 将字符串“hello,world"放入串口1的TX_FIFO */

        s_led_state = !s_led_state;     /* 将电平取反 */

        vTaskDelay(500 / portTICK_PERIOD_MS);   /* 延时300ms */

        gpio_set_level(26,s_led_state);   /* gpio输出电平 */

        int len = uart_read_bytes(UART_NUM_1,buffer,(UART1_RX_BUF_SIZE - 1), 20 / portTICK_PERIOD_MS);  /* 从串口1的RX_FIFO获取字符串 */

        /* 如果读到包的话 */
        if(len)
        {
    
    
            buffer[len] = '\0';  /* 在结尾加入字符'\0', */
            ESP_LOGI(TAG,"Recv str -> %s , and the length is:%d",buffer,strlen(buffer));  /* 打印logo */
            ESP_LOGI(TAG,"The size of buffer is %d,and ready to clear this buffer.",sizeof(buffer));  /* 打印logo */
            memset(buffer,0,sizeof(buffer));  /* 清空内存,等待下一次的串口保文。 */
        }
    }
}

四、相关API

4.1、uart_param_config( )

在这里插入图片描述

  • uart_num : 很简单,就是uart的端口号。这一次实验使用uart1,对应的宏是UART_NUM_1。
  • uart_config
    在这里插入图片描述
    从上图可以看到,结构体uart_config_t里的成员变量基本都是枚举类型,除了成员变量baud_rate与成员变量use_ref_tick。

4.2、uart_set_pin( )

在这里插入图片描述
有意思的是,esp32支持通过软件来设置uart的硬件引脚,真的非常方便!!

4.3、uart_driver_install( )

在这里插入图片描述
刚开始没有注意到笔记:Rx_buffer_size应该大于UART_FIFO_LEN。Tx_buffer_size应该为零或者大于UART_FIFO_LEN。导致程序编译不成功!!!
在这里插入图片描述
从上图可以看到,Rx_buffer_size应该大于128字节,Tx_buffer_size应该为零或者大于128字节。

4.4、uart_write_bytes( )

在这里插入图片描述
如果tx_buffer_size设置为0,那么uart_write_bytes将会“阻塞”程序(就是程序会卡在这个函数,直到所有数据都发送出去)。不管怎样,在我看来都不应该将tx_buffer_size设置为0而影响整个程序的实时性,毕竟ESP-IDF框架是基于freertos实时系统。

4.5、uart_read_bytes( )

在这里插入图片描述
函数很简单,值得注意的是uart_read_bytes( )接收完字符串后,最好在字符串的最后加入字符‘\0’,这是一个很好的C代码习惯(可以避免strlen等C标准库的一些bug)。详细可以阅读《C和指针》这本书。
还有另外一个好习惯就是使用memset( )函数清除整个buffer内存,避免影响下一次字符串读取与判断。

猜你喜欢

转载自blog.csdn.net/wallace89/article/details/124239314