赞
踩
USART是一种串行通信协议,广泛应用于微控制器和计算机之间的通信。USART支持异步和同步模式,因此它可以在没有时钟信号的情况下(异步模式)或有时钟信号的情况下(同步模式)进行通信。
ESP32-S3有两个全功能的USART通道,USART0和USART1,USART2,支持异步通信(RS232 和 RS485)和 IrDA,通信速率可达到 5 Mbps。
UART 基本架构图
UART 模块工作在两个时钟域:APB_CLK 时钟域和 Core 时钟域。UART Core 有三个时钟源:80-MHz APB_CLK、RC_FAST_CLK 以及晶振时钟 XTAL_CLK ,可以通过配置 UART_SCLK_SEL 来选择时钟源。分频器用于对时钟源进行分频,然后产生时钟信号来驱动 UARTCore 模块。
更加详细的介绍,可以去看看官方的文档:
ESP32S3官方文档
需要注意一点
ESP32-S3的USART引脚映射是可配置的,这是因为ESP32-S3使用了一个称为GPIO矩阵的特性。GPIO矩阵是ESP32-S3硬件的一部分,它允许将内部信号路由到任何GPIO引脚。这意味着,我们可以将USART的发送(TX)和接收(RX)信号连接到你选择的任何可用GPIO引脚。
发送(TX) | 接收(RX) | |
---|---|---|
UART0 | IO43 | IO44 |
UART1 | IO17 / 任意IO | IO18 / 任意IO |
UART2 | 任意IO | 任意IO |
printf()
函数在ESP-IDF中,printf()
函数默认使用的是USART0。这是因为在ESP32-S3的启动代码中,USART0被初始化为默认的调试控制台。因此,当我们在代码中使用printf()
函数来打印信息时,这些信息将会被发送到USART0,并且可以通过串行接口(如USB转串口适配器)在计算机的串行监视器上看到。
在ESP32-S3上使用USART的基本步骤:
#include "driver/uart.h" void app_main(void) { // -------------1. 配置USART选项----------------------- 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 // 流控 }; // --------------2. 初始化USART------------------------ // UART_NUM_1:UART端口号 // &uart_config:指向uart_config_t结构体的指针 uart_param_config(UART_NUM_1, &uart_config); // --------------3. 安装驱动程序------------------------ // UART_NUM_1:UART端口号 // 1024 * 2:接收缓冲区大小 // 0:发送缓冲区大小 // 0:队列长度 // NULL:队列句柄(如果不使用队列,可以设置为NULL) // 0:中断分配标志(通常设置为0) uart_driver_install(UART_NUM_1, 1024 * 2, 0, 0, NULL, 0); // 4.---------------4. 发送数据-------------------------- // UART_NUM_1:UART端口号 // "Hello, world!":要发送的数据 // 13:要发送的数据的长度 uart_write_bytes(UART_NUM_1, "Hello, world!", 13); // ------------------5. 读取数据----------------------- uint8_t data[128]; // 数据缓冲区 int length = 0; // 读取的数据长度 // UART_NUM_1:UART端口号 // data:数据缓冲区 // sizeof(data):要读取的最大数据长度 // 1000 / portTICK_RATE_MS:读取超时时间(以RTOS tick为单位) length = uart_read_bytes(UART_NUM_1, data, sizeof(data), 1000 / portTICK_RATE_MS); if (length > 0) { // 如果读取到数据,处理数据 // ... } }
前面提到过ESP32-S3的USART引脚映射是可配置的,所以我们可以使用uart_set_pin()
来自定义TX和RX
#include "driver/uart.h"
void app_main(void)
{
// 设置UART1的TX引脚为GPIO10,RX引脚为GPIO9
uart_set_pin(UART_NUM_1, 10, 9, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
}
这里uart_set_pin()
函数的最后两个参数是RTS(请求发送)和CTS(清除发送),我没有使用所以将它们设置为UART_PIN_NO_CHANGE
串口UART_NUM_1接收数据,并分别在串口UART_NUM_0和串口UART_NUM_1返回
这次我们依旧使用面向对象的方法来编写驱动,驱动API接口参考Arduino的格式
/** * @file USART.h * @author 宁子希 (1589326497@qq.com) * @brief 串口初始化类 * @version 0.1 * @date 2024-03-12 * * @copyright Copyright (c) 2024 * */ #ifndef _USART_H_ #define _USART_H_ #include <string.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/uart.h" #include "driver/uart_select.h" #include "driver/gpio.h" #ifdef __cplusplus extern "C" { #endif class Uart { public: // 构造函数,接收UART端口号和TX、RX引脚作为参数 Uart(uart_port_t uart_num, int tx_pin, int rx_pin); // 发送数据,接收一个字符数组和长度作为参数 void write(const char* data, int len); // 接收数据,接收一个字符数组和长度作为参数,返回实际接收的长度 int read(uint8_t* buf, int len); private: uart_port_t _uart_num; // UART端口号 int _tx_pin; // TX引脚 int _rx_pin; // RX引脚 }; #ifdef __cplusplus } #endif #endif
/** * @file USART.cpp * @author 宁子希 (1589326497@qq.com) * @brief 串口初始化类 * @version 0.1 * @date 2024-03-12 * * @copyright Copyright (c) 2024 * */ #include "USART.h" // 构造函数 Uart::Uart(uart_port_t uart_num, int tx_pin, int rx_pin) : _uart_num(uart_num), _tx_pin(tx_pin), _rx_pin(rx_pin) { // 配置UART参数 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, // 流控制 }; // 配置UART参数 uart_param_config(uart_num, &uart_config); // 设置UART引脚 // 设置UART的TX和RX引脚 uart_set_pin(uart_num, tx_pin, rx_pin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); // 安装UART驱动程序 // 安装UART驱动程序 uart_driver_install(uart_num, 1024 * 2, 0, 0, NULL, 0); } // 发送数据 void Uart::write(const char* data, int len) { // 调用ESP-IDF库函数来发送数据 uart_write_bytes(_uart_num, data, len); } // 接收数据 int Uart::read(uint8_t* buf, int len) { // 调用ESP-IDF库函数来接收数据 return uart_read_bytes(_uart_num, buf, len, 1000 / portTICK_PERIOD_MS); }
/** * @file main.cpp * @author 宁子希 (1589326497@qq.com) * @brief 串口通信实验 * @version 0.1 * @date 2024-03-13 * * @copyright Copyright (c) 2024 * */ #include <iostream> #include <string> #include "USART.h" using namespace std; extern "C" void app_main(void){ // 创建一个Uart对象使用UART_NUM_1 TX:8 RX:9 Uart uart1(UART_NUM_1, 8, 9); // 发送数据 uart1.write("Hello, ESP32!", 13); while(true){ // 接收数据 uint8_t buf[128]; int len = uart1.read(buf, sizeof(buf)); // 处理接收到的数据 if (len > 0) { // 假设我们只是简单地将接收到的数据打印出来 for (int i = 0; i < len; i++) { printf("%c", buf[i]); } printf("\n"); // 然后我们可以再次发送处理后的数据 uart1.write((const char*)buf, len); } } }
更加详细的内容可以去看看官方的资料:
ESP32S3 USART 官方手册
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。