一、概述
通用異步收發(fā)送器(UART)是一種硬件特性,它使用廣泛適應(yīng)的異步串行通信接口(如RS 232、RS 422、RS 485)來處理通信(即時序要求和數(shù)據(jù)幀)。UART提供了一種廣泛采用和廉價的方法來實現(xiàn)不同設(shè)備之間的全雙工或半雙工數(shù)據(jù)交換。
ESP32芯片有三個UART控制器(UART 0、UART 1和UART 2),它們具有一組相同的寄存器,以便于編程和靈活性。
每個UART控制器都是獨立配置的,參數(shù)包括波特率、數(shù)據(jù)比特長度、位序、停止位數(shù)、奇偶校驗位等。所有控制器都與不同廠商的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ā)板串口一默認的是GPIO9和GPIO10,現(xiàn)在將TX、RX映射到GPIO4和GPIO5上。
三、編程流程
3.1 設(shè)置通信參數(shù)
如設(shè)置波特率、數(shù)據(jù)位、停止位等
在結(jié)構(gòu)體中進行配置:
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ā)板串口一默認的是GPIO9和GPIO10,現(xiàn)在將TX、RX映射到GPIO4和GPIO5上。
請調(diào)用函數(shù)uart_set_pin()并指定驅(qū)動程序應(yīng)將Tx,Rx,RTS和CTS信號路由至的GPIO引腳號。
如果要為特定信號保留當前分配的管腳號,請傳遞宏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ū)的大小
事件隊列句柄和大小
分配中斷的標志
該功能將為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 運行UART通信
串行通信由每個UART控制器的有限狀態(tài)機(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ā)送
準備好要傳輸?shù)臄?shù)據(jù)后,調(diào)用該函數(shù)uart_write_bytes()并將數(shù)據(jù)緩沖區(qū)的地址和數(shù)據(jù)長度傳遞給該函數(shù)。該函數(shù)將數(shù)據(jù)復(fù)制到Tx環(huán)形緩沖區(qū)(立即或在有足夠空間可用之后),然后退出。當Tx FIFO緩沖區(qū)中有可用空間時,中斷服務(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é)束時添加了一個串行中斷信號。意味著它會在發(fā)送完數(shù)據(jù)之后,設(shè)置TX低電平一段時間(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ū)的另一個功能是uart_tx_chars()。不像uart_write_bytes(),此功能在可用空間之前不會阻塞。相反,它將寫入可立即放入硬件Tx FIFO中的所有數(shù)據(jù),然后返回已寫入的字節(jié)數(shù)。
有一個“陪伴”功能uart_wait_tx_done(),可監(jiān)視Tx FIFO緩沖區(qū)的狀態(tài)并在其為空時返回。
// 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ù)進行讀出uart_read_bytes()。,這個函數(shù)會阻塞待在那里,直到讀滿需要的字節(jié),或是超時。
在讀取數(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);} 五、串口隊列接收 /********************************************************************* * 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學習筆記(5)——WiFi接口使用(STA和AP模式)
下一篇:ESP32學習筆記(3)——高分辨率定時器接口使用
推薦閱讀最新更新時間:2025-06-30 17:45


![[nrf52832][nrf52840][nrf52810][nrf52820][bsp_<font color='red'>uart</font>] <font color='red'>UART</font>配置和<font color='red'>使用</font>](https://6.eewimg.cn/news/statics/images/loading.gif)
設(shè)計資源 培訓(xùn) 開發(fā)板 精華推薦
- Microchip 升級數(shù)字信號控制器(DSC)產(chǎn)品線 推出PWM 分辨率和 ADC 速度業(yè)界領(lǐng)先的新器件
- 意法半導(dǎo)體STM32MP23x:突破成本限制的工業(yè)AI應(yīng)用核心
- 意法半導(dǎo)體推出用于匹配遠距離無線微控制器STM32WL33的集成的匹配濾波芯片
- ESP32開發(fā)板連接TFT顯示屏ST7789跳坑記
- 如何讓ESP32支持analogWrite函數(shù)
- LGVL配合FreeType為可變字體設(shè)置字重-ESP32篇
- 使用樹莓派進行 ESP32 Jtag 調(diào)試
- ESP32怎么在SPIFFS里面存儲html,css,js文件,以及網(wǎng)頁和arduino的通訊
- ESP32 freeRTOS使用測試
- LTC1871、4.5V 至 15V 輸入、12.0V/2A 輸出 SEPIC 轉(zhuǎn)換器
- AMSRL-7815-NZ 15V 高達 7.5 瓦 DC-DC 開關(guān)穩(wěn)壓器的典型應(yīng)用
- CY8C5888AXI-LP096 CY8C58LP PSoC 5LP 可編程片上系統(tǒng)的典型應(yīng)用
- AM1D-0512S-RZ 12V 1 瓦 DC/DC 轉(zhuǎn)換器的典型應(yīng)用
- DER-526 - 18W非調(diào)光非隔離降壓-升壓LED驅(qū)動器
- 使用 Richtek Technology Corporation 的 RT8011APQW 的參考設(shè)計
- 使用 Analog Devices 的 LT1317IS8 的參考設(shè)計
- AM1D-1505SH30-RZ 5V 1W DC-DC 轉(zhuǎn)換器的典型應(yīng)用
- LTC4089 的典型應(yīng)用,全功能鋰離子電池充電器
- 使用 ON Semiconductor 的 NUD4022 的參考設(shè)計
- 南芯科技推出高集成度多口移動電源解決方案,助力充電寶市場穩(wěn)健發(fā)展
- 英飛凌推出具有超低導(dǎo)通電阻的CoolSiC? MOSFET 750 V G2,適用于汽車和工業(yè)功率電子應(yīng)用
- DigiKey 慶祝 B 站賬號粉絲突破 10 萬,贈送驚喜禮包
- 碳化硅企業(yè) Wolfspeed 啟動破產(chǎn)重組,預(yù)計 2025 年三季度末完成司法重整
- 蘋果被曝考慮放棄自研模型 轉(zhuǎn)而與Anthropic或OpenAI合作
- ?百度文心4.5來襲!英特爾Day0即支持端側(cè)部署
- 【廣瀨電機】關(guān)于中國發(fā)明專利侵權(quán)訴訟達成和解的公告
- 英飛凌BMS解決方案推動電動汽車創(chuàng)新
- 地平線的L3判斷與實踐路徑
- 汽車網(wǎng)絡(luò)升級攻略:CAN-CAN FD-車載以太網(wǎng)
- STM32中斷優(yōu)先級和開關(guān)總中斷(很老很經(jīng)典)
- 自主品牌的優(yōu)勢:數(shù)字化駕駛艙領(lǐng)先全球
- 特斯拉最新發(fā)布“待命模式”,隨時等待被“召喚”
- stm32之 GPIO_Remap_SWJ_Disable之后無法使用swd下載程序解決方法
- 歐陽明高團隊破解鋰離子動力電池燃燒機理
- 韓國半導(dǎo)體出口額猛增,2017總出口額創(chuàng)60年最高記錄
- Diodes 公司推出輸入電壓范圍寬廣的超低靜態(tài)電流穩(wěn)壓器
- 富昌電子中國區(qū)官網(wǎng)全新上線
- 亞系外資:挖礦需求帶動臺積電Q1營收,貢獻全年5%營收
- 三星今年計劃銷售3.2億部智能機、500萬部可穿戴設(shè)備