一、概述
通用異步收發(fā)送器(UART)是一種硬件特性,它使用廣泛適應(yīng)的異步串行通信接口(如RS 232、RS 422、RS 485)來處理通信(即時(shí)序要求和數(shù)據(jù)幀)。UART提供了一種廣泛采用和廉價(jià)的方法來實(shí)現(xiàn)不同設(shè)備之間的全雙工或半雙工數(shù)據(jù)交換。
ESP32芯片有三個(gè)UART控制器(UART 0、UART 1和UART 2),它們具有一組相同的寄存器,以便于編程和靈活性。
每個(gè)UART控制器都是獨(dú)立配置的,參數(shù)包括波特率、數(shù)據(jù)比特長度、位序、停止位數(shù)、奇偶校驗(yàn)位等。所有控制器都與不同廠商的UART支持設(shè)備兼容,還可以支持紅外數(shù)據(jù)關(guān)聯(lián)協(xié)議(IRDA)。
ESP-IDF 編程指南——UART
二、API說明
以下 UART 接口位于 driver/include/driver/uart.h。
2.1 uart_param_config
2.2 uart_driver_install
2.3 uart_read_bytes
2.4 uart_write_bytes
2.5 uart_set_pin
ESP32的串口是支持引腳映射的,比如我的開發(fā)板串口一默認(rèn)的是GPIO9和GPIO10,現(xiàn)在將TX、RX映射到GPIO4和GPIO5上。
三、編程流程
3.1 設(shè)置通信參數(shù)
如設(shè)置波特率、數(shù)據(jù)位、停止位等
在結(jié)構(gòu)體中進(jìn)行配置:
typedef struct {
int baud_rate; /*!< UART baud rate*/
uart_word_length_t data_bits; /*!< UART byte size*/
uart_parity_t parity; /*!< UART parity mode*/
uart_stop_bits_t stop_bits; /*!< UART stop bits*/
uart_hw_flowcontrol_t flow_ctrl; /*!< UART HW flow control mode (cts/rts)*/
uint8_t rx_flow_ctrl_thresh; /*!< UART HW RTS threshold*/
union {
uart_sclk_t source_clk; /*!< UART source clock selection */
bool use_ref_tick __attribute__((deprecated)); /*!< Deprecated method to select ref tick clock source, set source_clk field instead */
};} uart_config_t;
3.2 設(shè)置通信引腳
ESP32的串口是支持引腳映射的,比如我的開發(fā)板串口一默認(rèn)的是GPIO9和GPIO10,現(xiàn)在將TX、RX映射到GPIO4和GPIO5上。
請調(diào)用函數(shù)uart_set_pin()并指定驅(qū)動程序應(yīng)將Tx,Rx,RTS和CTS信號路由至的GPIO引腳號。
如果要為特定信號保留當(dāng)前分配的管腳號,請傳遞宏UART_PIN_NO_CHANGE。
應(yīng)該為不使用的引腳指定相同的宏。
// Set UART pins(TX: IO17 (UART2 default), RX: IO16 (UART2 default), RTS: IO18, CTS: IO19)ESP_ERROR_CHECK(uart_set_pin(UART_NUM_2, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, 18, 19));
3.3 驅(qū)動程序安裝
設(shè)置好通信引腳后,通過調(diào)用安裝驅(qū)動程序uart_driver_install()并指定以下參數(shù):
Tx環(huán)形緩沖區(qū)的大小
Rx環(huán)形緩沖區(qū)的大小
事件隊(duì)列句柄和大小
分配中斷的標(biāo)志
該功能將為UART驅(qū)動程序分配所需的內(nèi)部資源。
// Setup UART buffered IO with event queueconst int uart_buffer_size = (1024 * 2);QueueHandle_t uart_queue;// Install UART driver using an event queue hereESP_ERROR_CHECK(uart_driver_install(UART_NUM_2, uart_buffer_size,
uart_buffer_size, 10, &uart_queue, 0));
3.4 運(yùn)行UART通信
串行通信由每個(gè)UART控制器的有限狀態(tài)機(jī)(FSM)控制。
發(fā)送數(shù)據(jù)的過程涉及以下步驟:
將數(shù)據(jù)寫入Tx FIFO緩沖區(qū)
FSM序列化數(shù)據(jù)
FSM將數(shù)據(jù)發(fā)送出去
接收數(shù)據(jù)的過程類似,但是步驟相反:
FSM處理傳入的串行流并將其并行化
FSM將數(shù)據(jù)寫入Rx FIFO緩沖區(qū)
從Rx FIFO緩沖區(qū)讀取數(shù)據(jù)
因此,應(yīng)用程序?qū)⒈幌拗茷榉謩e使用uart_write_bytes()和從相應(yīng)的緩沖區(qū)寫入和讀取數(shù)據(jù)uart_read_bytes(),而FSM將完成其余的工作。
3.4.1 發(fā)送
準(zhǔn)備好要傳輸?shù)臄?shù)據(jù)后,調(diào)用該函數(shù)uart_write_bytes()并將數(shù)據(jù)緩沖區(qū)的地址和數(shù)據(jù)長度傳遞給該函數(shù)。該函數(shù)將數(shù)據(jù)復(fù)制到Tx環(huán)形緩沖區(qū)(立即或在有足夠空間可用之后),然后退出。當(dāng)Tx FIFO緩沖區(qū)中有可用空間時(shí),中斷服務(wù)程序(ISR)將數(shù)據(jù)從Tx環(huán)形緩沖區(qū)移至后臺的Tx FIFO緩沖區(qū)。下面的代碼演示了此功能的用法。
// Write data to UART.char* test_str = 'This is a test string.n';uart_write_bytes(uart_num, (const char*)test_str, strlen(test_str));
該功能uart_write_bytes_with_break()類似于uart_write_bytes()但在傳輸結(jié)束時(shí)添加了一個(gè)串行中斷信號。意味著它會在發(fā)送完數(shù)據(jù)之后,設(shè)置TX低電平一段時(shí)間(RTOS任務(wù)節(jié)拍為單位)。
// Write data to UART, end with a break signal.uart_write_bytes_with_break(uart_num, 'test breakn',strlen('test breakn'), 100);
將數(shù)據(jù)寫入Tx FIFO緩沖區(qū)的另一個(gè)功能是uart_tx_chars()。不像uart_write_bytes(),此功能在可用空間之前不會阻塞。相反,它將寫入可立即放入硬件Tx FIFO中的所有數(shù)據(jù),然后返回已寫入的字節(jié)數(shù)。
有一個(gè)“陪伴”功能uart_wait_tx_done(),可監(jiān)視Tx FIFO緩沖區(qū)的狀態(tài)并在其為空時(shí)返回。
// Wait for packet to be sentconst int uart_num = UART_NUM_2;ESP_ERROR_CHECK(uart_wait_tx_done(uart_num, 100)); // wait timeout is 100 RTOS ticks (TickType_t)
3.4.2 接收
UART接收到數(shù)據(jù)并將其保存在Rx FIFO緩沖區(qū)后,需要使用函數(shù)進(jìn)行讀出uart_read_bytes()。,這個(gè)函數(shù)會阻塞待在那里,直到讀滿需要的字節(jié),或是超時(shí)。
在讀取數(shù)據(jù)之前,您可以調(diào)用來檢查Rx FIFO緩沖區(qū)中可用的字節(jié)數(shù)uart_get_buffered_data_len(),然后再讀取相應(yīng)的內(nèi)容,這樣就不會造成不必要的阻塞。下面給出了使用這些功能的示例。
// Read data from UART.const int uart_num = UART_NUM_2;uint8_t data[128];int length = 0;ESP_ERROR_CHECK(uart_get_buffered_data_len(uart_num, (size_t*)&length));length = uart_read_bytes(uart_num, data, length, 100);
如果不再需要Rx FIFO緩沖區(qū)中的數(shù)據(jù),則可以通過調(diào)用清除緩沖區(qū)uart_flush()。
四、串口回環(huán)輸出
這里我將GPIO4、GPIO5改成了GPIO23、GPIO18
#include * This is an example which echos any data it receives on UART1 back to the sender, * with hardware flow control turned off. It does not use UART driver event queue. * * - Port: UART1 * - Receive (Rx) buffer: on * - Transmit (Tx) buffer: off * - Flow control: off * - Event queue: off * - Pin assignment: see defines below */#define ECHO_TEST_TXD (GPIO_NUM_23)#define ECHO_TEST_RXD (GPIO_NUM_18)#define ECHO_TEST_RTS (UART_PIN_NO_CHANGE)#define ECHO_TEST_CTS (UART_PIN_NO_CHANGE)#define BUF_SIZE (1024)static void echo_task(void *arg){ /* Configure parameters of an UART driver, * communication pins and install the driver */ 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, BUF_SIZE * 2, 0, 0, NULL, 0); uart_param_config(UART_NUM_1, &uart_config); uart_set_pin(UART_NUM_1, ECHO_TEST_TXD, ECHO_TEST_RXD, ECHO_TEST_RTS, ECHO_TEST_CTS); // Configure a temporary buffer for the incoming data uint8_t *data = (uint8_t *) malloc(BUF_SIZE); while (1) { // Read data from the UART int len = uart_read_bytes(UART_NUM_1, data, BUF_SIZE, 20 / portTICK_RATE_MS); // Write data back to the UART uart_write_bytes(UART_NUM_1, (const char *) data, len); }}void app_main(void){ xTaskCreate(echo_task, 'uart_echo_task', 1024, NULL, 10, NULL);} 五、串口隊(duì)列接收 /********************************************************************* * INCLUDES */#include * LOCAL VARIABLES */static QueueHandle_t s_uart0Queue;static const char *TAG = 'board_uart';/********************************************************************* * PUBLIC FUNCTIONS *//** @brief 串口驅(qū)動初始化 @param 無 @return 無 */void UART_Init(void){ // Configure parameters of an UART driver, // communication pins and install the driver 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_param_config(UART_NUM_0, &uart_config); // 配置串口0參數(shù) uart_set_pin(UART_NUM_0, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);// 配置串口0引腳 // Install UART driver, and get the queue. uart_driver_install(UART_NUM_0, BUF_SIZE * 2, BUF_SIZE * 2, 100, &s_uart0Queue, 0); // 安裝UART驅(qū)動程序 // Create a task to handler UART event from ISR xTaskCreate(uartEventTask, 'uartEventTask', 2048, NULL, 12, NULL); }/********************************************************************* * LOCAL FUNCTIONS */static void uartEventTask(void *pvParameters){ uart_event_t event; uint8_t *pTempBuf = (uint8_t *)malloc(UART_MAX_NUM_RX_BYTES); for(;;) { // Waiting for UART event. if(xQueueReceive(s_uart0Queue, (void *)&event, (portTickType)portMAX_DELAY)) { bzero(pTempBuf, UART_MAX_NUM_RX_BYTES); switch(event.type) { // Event of UART receving data // We'd better handler data event fast, there would be much more data events than // other types of events. If we take too much time on data event, the queue might be full. case UART_DATA: // ESP_LOGI(TAG, '[UART DATA]: %d', event.size); uart_read_bytes(UART_NUM_0, pTempBuf, event.size, portMAX_DELAY); uart_write_bytes(UART_NUM_0, (const char *)pTempBuf, event.size); break; // Event of HW FIFO overflow detected case UART_FIFO_OVF: ESP_LOGI(TAG, 'hw fifo overflow'); // If fifo overflow happened, you should consider adding flow control for your application.
上一篇:ESP32學(xué)習(xí)筆記(5)——WiFi接口使用(STA和AP模式)
下一篇:ESP32學(xué)習(xí)筆記(3)——高分辨率定時(shí)器接口使用
推薦閱讀最新更新時(shí)間:2025-05-29 11:06





設(shè)計(jì)資源 培訓(xùn) 開發(fā)板 精華推薦
- 意法半導(dǎo)體推出用于匹配遠(yuǎn)距離無線微控制器STM32WL33的集成的匹配濾波芯片
- ESP32開發(fā)板連接TFT顯示屏ST7789跳坑記
- 如何讓ESP32支持analogWrite函數(shù)
- LGVL配合FreeType為可變字體設(shè)置字重-ESP32篇
- 使用樹莓派進(jìn)行 ESP32 Jtag 調(diào)試
- ESP32怎么在SPIFFS里面存儲html,css,js文件,以及網(wǎng)頁和arduino的通訊
- ESP32 freeRTOS使用測試
- API調(diào)用小記(Touchdesigner和ESP32)
- 關(guān)于ESP32/8266使用async-mqtt-client庫的一些基本介紹
- WCT-15W1COILTX: 15 W單線圈無線充電發(fā)射器參考設(shè)計(jì)
- LTC6262HTS8 230 uA 電源電流運(yùn)算放大器的典型應(yīng)用
- 用于 FP/DFB 激光器的 SY88982L 3.3V、2.7Gbps 大電流、低功率激光驅(qū)動器的典型應(yīng)用
- 具有平均模式恒流控制的 HV9803 LED 驅(qū)動器 I 的典型應(yīng)用
- LTM4601-1,簡單地并聯(lián)多個(gè) DC/DC 模塊穩(wěn)壓器系統(tǒng)以實(shí)現(xiàn)更高的輸出電流
- 雙輸出降壓控制器產(chǎn)生 10% 準(zhǔn)確、高效和可靠的大電流軌
- 【涂鴉智能】智能溫濕度傳感器
- DC208A-B,用于具有固定輸出的 LTC1559 備用電池控制器的演示板
- 電梯控制器
- 降壓-升壓轉(zhuǎn)換器最大限度地減少了從極低輸出電流到高輸出電流的輸出電壓瞬變
- 智能輔助駕駛和智能駕駛的車輛架構(gòu)
- 意法半導(dǎo)體70W無線充電芯片組提升充電速度、能效和靈活性
- 基于51單片機(jī)wifi物聯(lián)網(wǎng)的澆花控制系統(tǒng)
- 吉時(shí)利:75年一直走在電源工程前沿
- 顯通科技推出面向可穿戴設(shè)備和大型顯示屏的超聲波觸控解
- 【STM32】CubeMX+HAL 點(diǎn)亮LED
- 零束科技與高通達(dá)成戰(zhàn)略合作 打造全新智能車數(shù)字化體驗(yàn)
- STM32進(jìn)階-紅外遙控器的應(yīng)用詳細(xì)步驟
- 永磁同步電機(jī)常用轉(zhuǎn)子結(jié)構(gòu)的電磁振動分析
- 優(yōu)異信號完整性的仿真和測量解決方案
- 芯原超低能耗NPU可為移動端大語言模型推理提供超40 TOPS算力
- 芯原AI-ISP芯片定制方案助力客戶智能手機(jī)量產(chǎn)出貨
- AI加持,安森美一站式服務(wù)推動助聽器市場持續(xù)進(jìn)步
- 意法半導(dǎo)體推出用于匹配遠(yuǎn)距離無線微控制器STM32WL33的集成的匹配濾波芯片
- 如何為您的應(yīng)用選擇光傳感器
- Samtec新型農(nóng)業(yè)漫談系列二 | 垂直農(nóng)業(yè)案列分享
- Samtec應(yīng)用科普 | C-V2X技術(shù)在汽車領(lǐng)域的應(yīng)用
- 尼得科運(yùn)動&能源事業(yè)本部在印度卡納塔克邦胡布利舉行新工廠竣工儀式
- 貿(mào)澤開售Qorvo適用于5G和mMIMO應(yīng)用的新型QPA9822線性5G高增益/高驅(qū)動放大器
- 邊緣計(jì)算網(wǎng)關(guān)工業(yè)物聯(lián)網(wǎng)應(yīng)用:空壓機(jī)遠(yuǎn)程運(yùn)維監(jiān)控管理
- 五款最具實(shí)力的商業(yè)服務(wù)機(jī)器人
- 服務(wù)機(jī)器人即將步入4.0時(shí)代
- 是德科技毫米波頻譜5G無線資源管理測試?yán)瓿墒状蜧CF驗(yàn)證
- Maxim發(fā)布調(diào)節(jié)器為超級電容備份電池提供最小尺寸和最高精度
- 意法半導(dǎo)體更新STM32Cube軟件包,可支持IOTA Chrysalis版本
- 純電動汽車如果淌水了是否會有漏電現(xiàn)象?
- 新能源汽車的電池技術(shù)淺析
- 純電動汽車和燃油車相比,它的優(yōu)勢在哪?
- 電動汽車的技術(shù)含量到底有多高?
- 電動汽車?yán)锏碾姵貕勖嵌嚅L時(shí)間?