0、前期準備
1、參考首篇文章搭建好esp32環境
2、準備好一塊esp32開發開發板(本作者使用了esp32c3作為開發平臺)
1、知識儲備
1.1 概述
? UART稱為通用異步收發器,可以進行全雙工/半雙工數據通訊數據通訊,通訊距離取決于上拉驅動能力、波特率,一般只在電路板上使用,如果需要長距離通訊可以外接RS232(最長通訊距離15M)、RS485電平轉換芯片,但是要注意如果外接的是RS485電平芯片,只能進行半雙工通訊,在理想情況下使用9600波特率,其通訊距離可達1200M。
1.2 功能架構
? 樂鑫EPS32C3帶有2個UART控制器,不僅可以用來進行數據通訊,還能來用驅動紅外發射管。(目前本文只用來作uart通訊)
1.3 uart配置流程介紹
LEDC的配置流程可分為以下3步
1、uart配置:設置波特率、數據位、停止位、奇偶校驗位和流控
2、引腳綁定:設置UART使用哪幾個引腳
3、 注冊uart中斷驅動(可選--建議進行該配置,本文給出例子就使用該方式)
1、uart配置
uart的配置主要是給 uart_config_t 結構體賦值,然后通過uart_param_config函數進行uart設置
以下對uart_config_t 結構體進行說明
typedef struct {
int baud_rate; //波特率
uart_word_length_t data_bits; //數據位
uart_parity_t parity; //奇偶校驗位
uart_stop_bits_t stop_bits; //停止位
uart_hw_flowcontrol_t flow_ctrl; //硬件流控
uint8_t rx_flow_ctrl_thresh; //硬件流控的RTS閾值
union {
uart_sclk_t source_clk; //時鐘源
bool use_ref_tick __attribute__((deprecated));
};
} uart_config_t;
例子:
// uart1配置
// 115200 8 1 無奇偶校驗位 無流控
uart_config_t uart_conf = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.stop_bits = UART_STOP_BITS_1,
.parity = UART_PARITY_DISABLE,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_APB,
};
uart_param_config(UART_NUM_1, &uart_conf);
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_num:串口編號 可查看uart.h,進行選擇
// tx_io_num:發送引腳編號,不需要可填:UART_PIN_NO_CHANGE
// rx_io_num: 接收引腳編號,不需要可填:UART_PIN_NO_CHANGE
// rts_io_num:rts引腳編號,不需要可填:UART_PIN_NO_CHANGE
// cts_io_num:cts引腳編號,不需要可填:UART_PIN_NO_CHANGE
例子:
// 引腳綁定
uart_set_pin(UART_NUM_1, TX_PIN, RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
3、 注冊uart中斷驅動(配置可選)
通過注冊uart中斷,可以不用開一個任務實時的去讀取串口,判斷串口有沒有數據發送過來,提高系統實時性。
中斷驅動uart_driver_install函數參數說明如下:
esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, QueueHandle_t *uart_queue, int intr_alloc_flags);
// 參數 :uart_num:串口編號 可查看uart.h,進行選擇
// rx_buffer_size:uart接收數組大小
// tx_buffer_size: uart發送數組大小
// queue_size: uart接收消息隊列大小,和新建的消息隊列大小一致
// uart_queue:uart接收消息隊列句柄
// intr_alloc_flags:中斷標志位
例子:
QueueHandle_t uart_queue = NULL;
uart_queue = xQueueCreate(8, 512);
uart_driver_install(UART_PORT, RX_BUFF_SIZE, RX_BUFF_SIZE, 8, &uart_queue, 0);
4、 其他函數
本文只介紹發送和接收兩個函數,更多函數可參考樂鑫官網
int uart_read_bytes(uart_port_t uart_num, void *buf, uint32_t length, TickType_t ticks_to_wait);
//參數 : uart_num:串口編號 可查看uart.h,進行選擇
// buf:接收數組名
// length:接收到的數據長度
// ticks_to_wait:讀取等待的RTOS 滴答個數
//返回 : -1:表示錯誤
// 其他:表示從uart的接收fifo讀取到的數據
int uart_write_bytes(uart_port_t uart_num, const void *src, size_t size);
//參數 : uart_num:串口編號 可查看uart.h,進行選擇
// src:發送數組名
// size:發送的數據長度
//返回 : -1:表示錯誤
// 其他:表示uart發送給發送fifo的數據
2、新建工程
idf.py create-project project_uart # 新建工程
cd project_uart
idf.py set-target esp32c3 # 設置工程使用的芯片
2、查看原理圖確定uart引腳
3、編寫程序
#include < freertos/FreeRTOS.h >
#include < freertos/queue.h >
#include < freertos/task.h >
#include < driver/gpio.h >
#include < driver/uart.h >
#include < esp_log.h >
#include < string.h >
#define LOG_EVENT_TAG "uart"
QueueHandle_t uart_queue = NULL;
#define RX_BUFF_SIZE 1024
#define UART_PORT UART_NUM_2
#define RX_PIN GPIO_NUM_1
#define TX_PIN GPIO_NUM_0
uint8_t uart_buff[RX_BUFF_SIZE];
void UartEventHandle(void* param);
void init_uart(void) {
uart_config_t uart_conf = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.stop_bits = UART_STOP_BITS_1,
.parity = UART_PARITY_DISABLE,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_APB,
};
uart_param_config(UART_PORT, &uart_conf);
uart_set_pin(UART_PORT, TX_PIN, RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
uart_queue = xQueueCreate(8, 512);
uart_driver_install(UART_PORT, RX_BUFF_SIZE, RX_BUFF_SIZE, 8, &uart_queue, 0);
xTaskCreate(UartEventHandle, "uart_event_hanle", 1024, NULL, 5, NULL);
}
void UartEventHandle(void* param) {
uart_event_t event;
memset(&uart_data, 0, sizeof(UartData));
uart_data.rx_status = pdFALSE;
while (pdTRUE) {
if (xQueueReceive(uart_queue, (void*)&event, portMAX_DELAY)) {
switch (event.type) {
case UART_DATA:
memset(&uart_data, 0, sizeof(UartData));
uart_data.rx_status = pdFALSE;
if (event.size <= sizeof(uart_data.buff)) {
uart_data.rx_status = pdTRUE;
uart_data.rx_uart_len = event.size;
uart_read_bytes(UART_PORT, uart_buff, event.size, portMAX_DELAY);
ESP_LOGI(LOG_EVENT_TAG, "uart_buff: %s", uart_buff);
}
break;
case UART_FIFO_OVF:
case UART_BUFFER_FULL:
uart_flush_input(UART_PORT);
xQueueReset(uart_queue);
break;
default:
ESP_LOGI(LOG_EVENT_TAG, "uart event type: %d", event.type);
break;
}
}
}
}
void app_main(void) {
init_uart();
while (1) {
vTaskDelay(1000 / portTICK_RATE_MS);
}
}