本文源碼地址為:http://download.csdn.net/download/noticeable/9961054 ESP32上有三個(gè)UART通訊接口,設(shè)備號(hào),從0~2,即UART0,UART1,UART2。支持異步通訊,ESP32開(kāi)發(fā)板上micro USB 連接的即使UART0接口,通常使用該串口作為日志輸出,用于調(diào)試,另外兩個(gè)串口作為工作串口,可用來(lái)輸出和接收數(shù)據(jù)。 對(duì)于uart通訊,主要可以分為以下幾個(gè)部分: PART1:定義引腳 1 #ifndef size_t 2 #define size_t unsigned int 3 #endif 4 #define BUF_SIZE (1024) 5 #define ECHO_TEST_TXD (4) 6 #define ECHO_TEST_RXD (5) 7 #define ECHO_TEST_RTS (18) 8 #define ECHO_TEST_CTS (19) 定義引腳,這里TXD、RXD是串口輸出通常用到數(shù)據(jù)寫(xiě)出和讀入的引腳,關(guān)于RTS和CTS引腳 (注意:由于UART0已經(jīng)的引腳配置已經(jīng)固定默認(rèn)在BootLoader中了,不能更改,所以不能配置引腳也無(wú)需定義) RTS(Request To Send 請(qǐng)求發(fā)送):用于傳輸PC機(jī)發(fā)往串口Modem等設(shè)備的信號(hào),該信號(hào)表示PC機(jī)是否允許Modem發(fā)數(shù)據(jù)。 CTS:Clear to send,在計(jì)算機(jī)UART引腳中定義表示為允許發(fā)送。 下面說(shuō)一下這兩個(gè)引腳的作用; (1) 隱藏終端問(wèn)題被減輕了,因?yàn)殚L(zhǎng)data幀只有在信道預(yù)約后才能被發(fā)送; PART2:編寫(xiě)uart處理任務(wù)1 void uart_task(void *pvParameters) 2 { 3 int uart_num = (int) pvParameters; 4 uart_event_t event; 5 size_t buffered_size; 6 uint8_t* dtmp = (uint8_t*) malloc(BUF_SIZE); 7 for(;;) { 8 //Waiting for UART event. 9 if(xQueueReceive(uart0_queue, (void * )&event, (portTickType)portMAX_DELAY)) { 10 ESP_LOGI(TAG, "uart[%d] event:", uart_num); 11 switch(event.type) { 12 //Event of UART receving data 13 /*We'd better handler data event fast, there would be much more data events than 14 other types of events. If we take too much time on data event, the queue might 15 be full. 16 in this example, we don't process data in event, but read data outside.*/ 17 case UART_DATA: 18 uart_get_buffered_data_len(uart_num, &buffered_size); 19 ESP_LOGI(TAG, "data, len: %d; buffered len: %d", event.size, buffered_size); 20 break; 21 //Event of HW FIFO overflow detected 22 case UART_FIFO_OVF: 23 ESP_LOGI(TAG, "hw fifo overflow\n"); 24 //If fifo overflow happened, you should consider adding flow control for your application. 25 //We can read data out out the buffer, or directly flush the rx buffer. 26 uart_flush(uart_num); 27 break; 28 //Event of UART ring buffer full 29 case UART_BUFFER_FULL: 30 ESP_LOGI(TAG, "ring buffer full\n"); 31 //If buffer full happened, you should consider encreasing your buffer size 32 //We can read data out out the buffer, or directly flush the rx buffer. 33 uart_flush(uart_num); 34 break; 35 //Event of UART RX break detected 36 case UART_BREAK: 37 ESP_LOGI(TAG, "uart rx break\n"); 38 break; 39 //Event of UART parity check error 40 case UART_PARITY_ERR: 41 ESP_LOGI(TAG, "uart parity error\n"); 42 break; 43 //Event of UART frame error 44 case UART_FRAME_ERR: 45 ESP_LOGI(TAG, "uart frame error\n"); 46 break; 47 //UART_PATTERN_DET 48 case UART_PATTERN_DET: 49 ESP_LOGI(TAG, "uart pattern detected\n"); 50 break; 51 //Others 52 default: 53 ESP_LOGI(TAG, "uart event type: %d\n", event.type); 54 break; 55 } 56 } 57 } 58 free(dtmp); 59 dtmp = NULL; 60 vTaskDelete(NULL); 61 }
uart_task任務(wù)的作用為對(duì)接收到的數(shù)據(jù)進(jìn)行處理,并將結(jié)果通過(guò)日志的形式打印到串口調(diào)試助手上,最后在任務(wù)結(jié)束時(shí),將處理任務(wù)刪除掉。 PART3:編寫(xiě)uart0 配置函數(shù) 1 void uart_evt_test() 2 { 3 int uart_num = UART_NUM_0; 4 uart_config_t uart_config = { 5 .baud_rate = 115200, 6 .data_bits = UART_DATA_8_BITS, 7 .parity = UART_PARITY_DISABLE, 8 .stop_bits = UART_STOP_BITS_1, 9 .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, 10 .rx_flow_ctrl_thresh = 122, 11 }; 12 //Set UART parameters 13 uart_param_config(uart_num, &uart_config); 14 //Set UART log level 15 esp_log_level_set(TAG, ESP_LOG_INFO); 16 //Install UART driver, and get the queue. 17 uart_driver_install(uart_num, BUF_SIZE * 2, BUF_SIZE * 2, 10, &uart0_queue, 0); 18 //Set UART pins,(-1: default pin, no change.) 19 //For UART0, we can just use the default pins. 20 //uart_set_pin(uart_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); 21 //Set uart pattern detect function. 22 uart_enable_pattern_det_intr(uart_num, '+', 3, 10000, 10, 10); 23 //Create a task to handler UART event from ISR 24 xTaskCreate(uart_task, "uart_task", 2048, (void*)uart_num, 12, NULL); 25 //process data 26 uint8_t* data = (uint8_t*) malloc(BUF_SIZE); 27 do { 28 int len = uart_read_bytes(uart_num, data, BUF_SIZE, 100 / portTICK_RATE_MS); 29 if(len > 0) { 30 ESP_LOGI(TAG, "uart read : %d", len); 31 uart_write_bytes(uart_num, (const char*)data, len); 32 } 33 } while(1); 34 }
uart_event_test函數(shù),用來(lái)對(duì)uart進(jìn)行配置其中 PART4:編寫(xiě)uart1配置函數(shù) 1 void uart_echo_test() 2 { 3 int uart_num = UART_NUM_1; 4 uart_config_t uart_config = { 5 .baud_rate = 115200, 6 .data_bits = UART_DATA_8_BITS, 7 .parity = UART_PARITY_DISABLE, 8 .stop_bits = UART_STOP_BITS_1, 9 .flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS, 10 .rx_flow_ctrl_thresh = 122, 11 }; 12 //Configure UART1 parameters 13 uart_param_config(uart_num, &uart_config); 14 //Set UART1 pins(TX: IO4, RX: I05, RTS: IO18, CTS: IO19) 15 uart_set_pin(uart_num, ECHO_TEST_TXD, ECHO_TEST_RXD, ECHO_TEST_RTS, ECHO_TEST_CTS); 16 //Install UART driver( We don't need an event queue here) 17 //In this example we don't even use a buffer for sending data. 18 uart_driver_install(uart_num, BUF_SIZE * 2, 0, 0, NULL, 0); 19 20 uint8_t* data = (uint8_t*) malloc(BUF_SIZE); 21 while(1) { 22 //Read data from UART 23 int len = uart_read_bytes(uart_num, data, BUF_SIZE, 20 / portTICK_RATE_MS); 24 //Write data back to UART 25 uart_write_bytes(uart_num, (const char*) data, len); 26 } 27 }
對(duì)于uart1,其大致過(guò)程與uart0函數(shù)是相似的,但是不同點(diǎn)在與其通訊模式與uart0是不同的,第9行可以看出它是通過(guò)硬件流進(jìn)行通訊的。 PART5:app_main函數(shù) 1 void app_main() 2 { 3 //A uart read/write example without event queue; 4 xTaskCreate(uart_echo_test, "uart_echo_test", 1024, NULL, 10, NULL); 5 6 //A uart example with event queue. 7 uart_evt_test(); 8 }
通過(guò)app_main對(duì)兩個(gè)函數(shù)進(jìn)行調(diào)用。
實(shí)驗(yàn)現(xiàn)象:由于本人手上沒(méi)有硬件流相關(guān)的串口調(diào)試器,所以對(duì)于uart1的驗(yàn)證無(wú)法進(jìn)行了,這里只對(duì)uart0的結(jié)果進(jìn)行實(shí)驗(yàn)。 打開(kāi)串口調(diào)試助手,連接esp32(通過(guò)usb直接連接即可),發(fā)送數(shù)據(jù),可以得到如下結(jié)果。說(shuō)明串口數(shù)據(jù)發(fā)送成功。
相關(guān)知識(shí):UART相關(guān)API接口 |
|