0、前期準(zhǔn)備
1、參考首篇文章搭建好esp32環(huán)境
2、準(zhǔn)備好一塊esp32開(kāi)發(fā)開(kāi)發(fā)板(本作者使用了esp32c3作為開(kāi)發(fā)平臺(tái))
1、知識(shí)儲(chǔ)備
1.1 概述
? UART稱(chēng)為通用異步收發(fā)器,可以進(jìn)行全雙工/半雙工數(shù)據(jù)通訊數(shù)據(jù)通訊,通訊距離取決于上拉驅(qū)動(dòng)能力、波特率,一般只在電路板上使用,如果需要長(zhǎng)距離通訊可以外接RS232(最長(zhǎng)通訊距離15M)、RS485電平轉(zhuǎn)換芯片,但是要注意如果外接的是RS485電平芯片,只能進(jìn)行半雙工通訊,在理想情況下使用9600波特率,其通訊距離可達(dá)1200M。
1.2 功能架構(gòu)
? 樂(lè)鑫EPS32C3帶有2個(gè)UART控制器,不僅可以用來(lái)進(jìn)行數(shù)據(jù)通訊,還能來(lái)用驅(qū)動(dòng)紅外發(fā)射管。(目前本文只用來(lái)作uart通訊)
1.3 uart配置流程介紹
LEDC的配置流程可分為以下3步
1、uart配置:設(shè)置波特率、數(shù)據(jù)位、停止位、奇偶校驗(yàn)位和流控
2、引腳綁定:設(shè)置UART使用哪幾個(gè)引腳
3、 注冊(cè)u(píng)art中斷驅(qū)動(dòng)(可選--建議進(jìn)行該配置,本文給出例子就使用該方式)
1、uart配置
uart的配置主要是給 uart_config_t 結(jié)構(gòu)體賦值,然后通過(guò)uart_param_config函數(shù)進(jìn)行uart設(shè)置
以下對(duì)uart_config_t 結(jié)構(gòu)體進(jìn)行說(shuō)明
typedef struct {
int baud_rate; //波特率
uart_word_length_t data_bits; //數(shù)據(jù)位
uart_parity_t parity; //奇偶校驗(yàn)位
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; //時(shí)鐘源
bool use_ref_tick __attribute__((deprecated));
};
} uart_config_t;
例子:
// uart1配置
// 115200 8 1 無(wú)奇偶校驗(yàn)位 無(wú)流控
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、引腳綁定
設(shè)置UART使用哪幾個(gè)引腳
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);
// 參數(shù) :uart_num:串口編號(hào) 可查看uart.h,進(jìn)行選擇
// tx_io_num:發(fā)送引腳編號(hào),不需要可填:UART_PIN_NO_CHANGE
// rx_io_num: 接收引腳編號(hào),不需要可填:UART_PIN_NO_CHANGE
// rts_io_num:rts引腳編號(hào),不需要可填:UART_PIN_NO_CHANGE
// cts_io_num:cts引腳編號(hào),不需要可填:UART_PIN_NO_CHANGE
例子:
// 引腳綁定
uart_set_pin(UART_NUM_1, TX_PIN, RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
3、 注冊(cè)u(píng)art中斷驅(qū)動(dòng)(配置可選)
通過(guò)注冊(cè)u(píng)art中斷,可以不用開(kāi)一個(gè)任務(wù)實(shí)時(shí)的去讀取串口,判斷串口有沒(méi)有數(shù)據(jù)發(fā)送過(guò)來(lái),提高系統(tǒng)實(shí)時(shí)性。
中斷驅(qū)動(dòng)uart_driver_install函數(shù)參數(shù)說(shuō)明如下:
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);
// 參數(shù) :uart_num:串口編號(hào) 可查看uart.h,進(jìn)行選擇
// rx_buffer_size:uart接收數(shù)組大小
// tx_buffer_size: uart發(fā)送數(shù)組大小
// queue_size: uart接收消息隊(duì)列大小,和新建的消息隊(duì)列大小一致
// uart_queue:uart接收消息隊(duì)列句柄
// intr_alloc_flags:中斷標(biāo)志位
例子:
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、 其他函數(shù)
本文只介紹發(fā)送和接收兩個(gè)函數(shù),更多函數(shù)可參考樂(lè)鑫官網(wǎng)
int uart_read_bytes(uart_port_t uart_num, void *buf, uint32_t length, TickType_t ticks_to_wait);
//參數(shù) : uart_num:串口編號(hào) 可查看uart.h,進(jìn)行選擇
// buf:接收數(shù)組名
// length:接收到的數(shù)據(jù)長(zhǎng)度
// ticks_to_wait:讀取等待的RTOS 滴答個(gè)數(shù)
//返回 : -1:表示錯(cuò)誤
// 其他:表示從uart的接收f(shuō)ifo讀取到的數(shù)據(jù)
int uart_write_bytes(uart_port_t uart_num, const void *src, size_t size);
//參數(shù) : uart_num:串口編號(hào) 可查看uart.h,進(jìn)行選擇
// src:發(fā)送數(shù)組名
// size:發(fā)送的數(shù)據(jù)長(zhǎng)度
//返回 : -1:表示錯(cuò)誤
// 其他:表示uart發(fā)送給發(fā)送fifo的數(shù)據(jù)
2、新建工程
idf.py create-project project_uart # 新建工程
cd project_uart
idf.py set-target esp32c3 # 設(shè)置工程使用的芯片
2、查看原理圖確定uart引腳
3、編寫(xiě)程序
#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);
}
}