图13.3.1.1 UART实验程序流程图
针对本章的实验要求,需要将串口发送引脚配置成复用推挽输出模式,而串口接收引脚配置成上拉输入模式。
13.3.2 UART函数解析
ESP-IDF提供了一套API来配置串口。要使用串口功能,需要导入必要的头文件:
#include "driver/uart.h"
接下来,作者将介绍一些常用的UART函数,这些函数的描述及其作用如下:
1,配置UART端口
该函数用来设置指定UART端口的通信参数,该函数原型如下所示:
esp_err_t uart_param_config(uart_port_t uart_num,
const uart_config_t *uart_config)
该函数的形参描述如下表所示:
| |
| UART外设端口号 例如:UART_NUM_0、UART_NUM_1等(在uart.h文件中有定义) |
| 指向uart_config_t结构体的指针,包含了UART的参数配置信息, 需自行定义,并根据UART的参数配置填充结构体中的成员变量 |
表13.3.2.1 函数uart_param_config()形参描述
返回值:ESP_OK表示设置成功,ESP_FAIL表示设置失败。
该函数使用uart_config_t类型的结构体变量传入uart外设的配置参数,该结构体的定义如下所示:
| 参数1 | |
| .baud_rate: 它代表串口的波特率,即数据传输速率,具体指的是每秒传输的位数。 | |
.data_bits: 数据位的数量,也就是每个字节中的位数。 | UART_DATA_5_BITS |
UART_DATA_6_BITS |
UART_DATA_7_BITS |
UART_DATA_8_BITS |
| UART_PARITY_DISABLE: 禁用校验位 |
|
|
| UART_STOP_BITS_1: 1 个停止位 |
UART_STOP_BITS_1_5: 1.5 个停止位,仅适用于 5 数据位 |
UART_STOP_BITS_2: 2 个停止位 |
| UART_HW_FLOWCTRL_DISABLE: 禁用流控制 |
UART_HW_FLOWCTRL_RTS: 只启用 RTS 信号流控制 |
UART_HW_FLOWCTRL_CTS: 只启用 CTS 信号流控制 |
| |
|
UART_SCLK_XTAL: 选择XTAL作为时钟源 |
UART_SCLK_DEFAULT: 选择APB时钟源为默认选项 |
.rx_flow_ctrl_thresh: 硬件控制流阈值 | |
表13.3.2.2 uart_config_t结构体参数值描述
完成上述结构体参数配置之后,可以将结构传递给 uart_param_config () 函数,用以实例化串口并返回串口句柄。
2,配置UART引脚
该函数设置某个管脚的中断服务函数,该函数原型如下所示:
esp_err_t uart_set_pin(uart_port_t uart_num,
int tx_io_num,
int rx_io_num, int rts_io_num,
int cts_io_num);
该函数的形参描述如下表所示:
函数的形参描述如下表所示:
| |
| UART外设端口号例如:UART_NUM_0、UART_NUM_1等(在uart.h文件中有定义) |
| UART发送引脚的GPIO号。若不需要此功能,可将此参数设为-1。 |
| UART接收引脚的GPIO号。若不需要此功能,可将此参数设为-1。 |
| UART请求发送(RTS)引脚的GPIO号。若不需要此功能,可将此参数设为-1,例如:UART_PIN_NO_CHANGE = -1 |
| UART 清除发送(CTS)引脚的GPIO号。若不需要此功能,可将此参数设为-1,例如:UART_PIN_NO_CHANGE = -1 |
表13.3.2.3 uart_set_pin()函数形参描述
返回值:ESP_OK表示设置成功,ESP_FAIL表示设置失败。
该函数可以将UART的发送、接收、RTS以及CTS引脚与指定的GPIO引脚进行连接。
3,安装驱动程序
该函数用于安装UART驱动程序,并指定发送和接收缓冲区的大小,其函数原型如下所示:
esp_err_t uart_driver_install(uart_port_t uart_num,
int rx_buffer_size,
int tx_buffer_size,
int event_queue_size,
QueueHandle_t *uart_queue,
int intr_alloc_flags)
该函数的形参描述,如下表所示:
| |
| UART外设端口号例如:UART_NUM_0、UART_NUM_1等(在uart.h文件中有定义)。 |
| UART 接收环形缓冲区大小,用于存储接收到的数据。 |
| UART发送环形缓冲区大小,用于存储有待发送的数据。 |
| UART 驱动程序内部缓冲队列的大小,用于存储待处理的接收和发送数据。 |
| 指向用户定义的用于接收数据的队列句柄,在接收数据时,接收到的数据会存储在这个队列中。 |
| |
表13.3.2.4 函数uart_driver_install()形参描述
返回值:ESP_OK表示设置成功,ESP_FAIL表示设置失败。
使用 uart_driver_install ()函数可以方便地初始化 UART,并且指定相应的缓冲区和队列大小以及其他参数。
4,获取数据长度
该函数用于获取接收环形缓冲区中缓存的数据长度,其函数原型如下所示:
esp_err_t uart_get_buffered_data_len(uart_port_t uart_num, size_t* size);
该函数的形参描述,如下表所示:
| |
| UART外设端口号例如:UART_NUM_0、UART_NUM_1等 |
| |
表13.3.2.5 函数uart_get_buffered_data_len ()形参描述
返回值:ESP_OK表示设置成功,ESP_FAIL表示设置失败。
5,接收数据
该函数从UART 接收缓冲区中读取数据,其函数原型如下所示:
int uart_read_bytes(uart_port_t uart_num,
void *buf,
uint32_t length,
tickType_t ticks_to_wait) 该函数的形参描述,如下表所示:
表13.3.2.6 函数uart_read_bytes ()形参描述
返回值:ESP_OK表示设置成功,ESP_FAIL表示设置失败。
6,发送数据
该函数将指定的数据写入到 UART 发送缓冲区,并触发数据的发送,其函数原型如下所示:
int uart_write_bytes(uart_port_t uart_num, const void *src, size_t size)
该函数的形参描述,如下表所示:
| |
| UART外设端口号 例如:UART_NUM_0、UART_NUM_1等 |
| |
| |
表13.3.2.7 函数uart_write_bytes ()形参描述
返回值:ESP_OK表示设置成功,ESP_FAIL表示设置失败。
在使用uart_write_bytes()函数发送数据时,重要的是要理解该函数的执行机制:数据首先被复制到UART发送缓冲区,随后函数会返回,并不会等待数据完全发送完成。因此,若需确保数据完整无误地发送成功,应当调用uart_wait_tx_done()函数进行同步等待,直至发送过程完全结束。在确认UART已成功初始化,并且已经配置了正确的波特率及其他相关参数之后,即可调用uart_write_bytes()函数,将数据准确无误地发送至UART设备。
13.3.3 UART驱动解析
在IDF版的04_uart例程中,作者在04_uart \components\BSP路径下新增了一个UART文件夹,用于存放uart.c和uart.h这两个文件。其中,uart.h文件负责声明UART相关的函数和变量,而uart.c文件则实现了UART的驱动代码。下面,我们将详细解析这两个文件的实现内容。
1,uart.h文件
/* 引脚和串口定义 */
#define USART_UX UART_NUM_0
#define USART_TX_GPIO_PIN GPIO_NUM_43
#define USART_RX_GPIO_PIN GPIO_NUM_44
/* 串口接收相关定义 */
#define RX_BUF_SIZE 1024 /* 环形缓冲区大小 */
2,uart.c文件
/**
* @param baudrate: 波特率, 根据自己需要设置波特率值 * @NOTE 注意: 必须设置正确的时钟源, 否则串口波特率就会设置异常. * @retval 无
*/
void usart_init(uint32_t baudrate)
{
uart_config_t uart_config; /* 串口配置句柄 */
uart_config.baud_rate = baudrate; /* 波特率 */
uart_config.data_bits = UART_DATA_8_BITS; /* 字长为8位数据格式 */
uart_config.parity = UART_PARITY_DISABLE; /* 无奇偶校验位 */
uart_config.stop_bits = UART_STOP_BITS_1; /* 一个停止位 */
uart_config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE; /* 无硬件控制流 */
uart_config.source_clk = UART_SCLK_APB; /* 配置时钟源 */
uart_config.rx_flow_ctrl_thresh = 122; /* 硬件控制流阈值 */
uart_param_config(USART_UX, &uart_config); /* 配置uart端口 */
/* 配置uart引脚 */
uart_set_pin(USART_UX,
USART_TX_GPIO_PIN,
USART_RX_GPIO_PIN,
UART_PIN_NO_CHANGE,
UART_PIN_NO_CHANGE);
/* 安装串口驱动 */
uart_driver_install(USART_UX,
RX_BUF_SIZE * 2,
RX_BUF_SIZE * 2,
20,
NULL,
0);
}
uart_config是结构体uart_config_t类型的全局变量,关于uart_config_t结构体成员的含义以及可选陪的参数请回到本章节的13.3.2小节进行回顾。波特率我们通过传参的方式,赋值给uart_config.baud_rate这个成员,其他成员也可以通过相应的步骤进行配置。接着,在配置UART0作为串口通信端口,并且将IO44与IO43引脚作为收发引脚后,调用安装串口驱动函数,便完成了UART的初始化配置。
ESP32-S3的串口通讯驱动不需要为UART0编写中断回调函数,因为在ESP32-S3 IDF库中已经封装了数据读写函数。UART0通过函数获取RX环形缓冲区缓存的数据长度,并判断该数据长度非空后,将其逐一通过读写函数进行操作。
13.3.4 CMakeLists.txt文件
打开本实验BSP下的CMakeLists.txt文件,其内容如下所示:
set(src_dirs
USART
LED)
set(include_dirs
USART
LED)
set(requires
driver)
idf_component_register(SRC_DIRS ${src_dirs}
INCLUDE_DIRS ${include_dirs} REQUIRES ${requires})
component_compile_options(-ffast-math -O3 -Wno-error=format=-Wno-format)
上述的红色USART驱动需要由开发者自行添加,以确保USART驱动能够顺利集成到构建系统中。这一步骤是必不可少的,它确保了USART驱动的正确性和可用性,为后续的开发工作提供了坚实的基础。
13.3.5 实验应用代码
打开main/main.c文件,该文件定义了工程入口函数,名为app_main,该函数代码如下:
/**
* @brief 程序入口
* @param 无
* @retval 无
*/
void app_main(void)
{
esp_err_t ret;
uint8_t len = 0;
uint16_t times = 0;
unsigned char data[RX_BUF_SIZE] = {0};
ret = nvs_flash_init(); /* 初始化NVS */
if (ret == ESP_ERR_NVS_NO_FREE_PAGES ||
ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
{
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
led_init(); /* 初始化LED */
usart_init(115200); /* 初始化串口 */
while(1)
{
/* 获取环形缓冲区数据长度 */
uart_get_buffered_data_len(USART_UX, (size_t*) &len);
if (len > 0) /* 判断数据长度 */
{
memset(data, 0, RX_BUF_SIZE); /* 对缓冲区清零 */
printf("\n您发送的消息为:\n");
uart_read_bytes(USART_UX, data, len, 100); /* 读数据 */
uart_write_bytes(USART_UX,
(const char*)data,
strlen((const char*)data)); /* 写数据 */
}
else
{
times++;
if (times % 5000 == 0)
{
printf("\n正点原子 ATK-DNESP32-S3 开发板 串口实验\n");
printf("正点原子@ALIENTEK\n\n\n");
}
if (times % 200 == 0)
{
printf("请输入数据,以回车键结束\n");
}
if (times % 30 == 0)
{
LED_TOGGLE();
}
vTaskDelay(10);
}
}
}
本实验的实验代码很简单,在完成初始化后,就不断地通过串口通信驱动提供的数据接收并判断数据长度大小,若还未完成数据接收,则每间隔一段时间就使用printf函数通过UART0打印一段提示信息,若数据接收完毕,则将数据原原本本地使用printf函数通过UART0打印出去,实现数据的回显功能。
13.4 下载验证
在完成编译和烧录操作后,需要将开发板的USB UART接口与PC的USB接口通过具有数据传输功能的数据线进行连接,并保证13.2.3小节中指示跳线帽已正确安装。接着打开PC上的ATK-XCOM串口调试助手软件,选择好正确的COM端口和相关的配置后,就能看到串口调试助手上每间隔一段时间就打印一次“请输出数据,以回车键结束”,接下来就可以根据提示通过串口调试助手发送一段任意的数据(以回车换行结束),随后立马就能看到串口调试助手上显示发送出去的数据,这就是本实验实现的数据回显功能。