UART簡介
UART(Universal Asynchronous Receiver/Transmitter)通用異步收發傳輸器,UART 作為異步串口通信協議的一種,工作原理是將傳輸數據的每個字符一位接一位地傳輸。是在應用程序開發過程中使用頻率最高的數據總線。
UART串口的特點是將數據一位一位地順序傳送,只要2根傳輸線就可以實現雙向通信,一根線發送數據的同時用另一根線接收數據。UART 串口通信有幾個重要的參數,分別是波特率、起始位、數據位、停止位和奇偶檢驗位,對于兩個使用 UART 串口通信的端口,這些參數必須匹配,否則通信將無法正常完成。UART 串口傳輸的數據格式如下圖所示:
起始位:表示數據傳輸的開始,電平邏輯為 “0” 。
數據位:可能值有 5、6、7、8、9,表示傳輸這幾個 bit 位數據。一般取值為 8,因為一個 ASCII 字符值為 8 位。
奇偶校驗位:用于接收方對接收到的數據進行校驗,校驗 “1” 的位數為偶數 (偶校驗) 或奇數(奇校驗),以此來校驗數據傳送的正確性,使用時不需要此位也可以。
停止位: 表示一幀數據的結束。電平邏輯為 “1”。
波特率:串口通信時的速率,它用單位時間內傳輸的二進制代碼的有效位 (bit) 數來表示,其單位為每秒比特數 bit/s(bps)。常見的波特率值有 4800、9600、14400、38400、115200 等,數值越大數據傳輸的越快,波特率為 115200 表示每秒鐘傳輸 115200 位數據。
訪問串口設備
#define SAMPLE_UART_NAME "uart1"
static rt_device_t serial;
serial = rt_device_find(SAMPLE_UART_NAME);
打開串口設備
通過設備句柄,應用程序可以打開和關閉設備,打開設備時,會檢測設備是否已經初始化,沒有初始化則會默認調用接口初始化設備。
rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflags);
一般情況下,會選擇使用發送阻塞模式以及接收非阻塞模式來進行開發。
rt_device_open(dev,RT_DEVICE_FLAG_RX_NON_BLOCKING|RT_DEVICE_FLAG_TX_BLOCKING)
硬件工作模式選擇
由于用戶層使用串口時,只關心應用層操作模式,不再關心硬件工作模式,使得應用層開發變得更加便捷,也增加了應用程序的可移植性。倘若用戶開發時比較關心硬件具體的工作模式,那么應該對其工作模式如何選擇?
串口外設的遵循如下規則:
- 模式優先級:DMA>中斷>輪詢,當有DMA配置時,默認使用DMA模式,以此類推。
- 串口默認配置接收和發送緩沖區
- 默認使用阻塞發送、非阻塞接收模式
V1版本
通過設備句柄,應用程序可以打開和關閉設備,打開設備時,會檢測設備是否已經初始化,沒有初始化則會默認調用初始化接口初始化設備。通過如下函數打開設備:
oflags 參數支持下列取值 (可以采用或的方式支持多種取值):
#define RT_DEVICE_FLAG_STREAM 0x040 /* 流模式 */
/* 接收模式參數 */
#define RT_DEVICE_FLAG_INT_RX 0x100 /* 中斷接收模式 */
#define RT_DEVICE_FLAG_DMA_RX 0x200 /* DMA 接收模式 */
/* 發送模式參數 */
#define RT_DEVICE_FLAG_INT_TX 0x400 /* 中斷發送模式 */
#define RT_DEVICE_FLAG_DMA_TX 0x800 /* DMA 發送模式 */
串口數據接收和發送數據的模式分為三種:中斷模式、輪詢模式、DMA模式。
在使用的時候,這 3 種模式只能選其一,若串口的打開參數 oflags 沒有指定使用中斷模式或者 DMA 模式,則默認使用輪詢模式。
DMA(Direct Memory Access)即直接存儲器訪問。 DMA 傳輸方式無需 CPU 直接控制傳輸,也沒有中斷處理方式那樣保留現場和恢復現場的過程,通過 DMA 控制器為 RAM 與 I/O 設備開辟一條直接傳送數據的通路,這就節省了 CPU 的資源來做其他操作。使用 DMA 傳輸可以連續獲取或發送一段信息而不占用中斷或延時,在通信頻繁或有大段信息要傳輸時非常有用。
控制串口設備
通過控制接口,應用程序可以對串口設備進行配置,如波特率、數據位、校驗位、接收緩沖區大小、停止位等參數的修改。
rt_err_t rt_deivce_control(rt_device_t dev, rt_uint8_t cmd, void *arg);
struct serial_configure
{rt_uint32_t baud_rate; /* 波特率 */rt_uint32_t data_bits :4; /* 數據位 */rt_uint32_t stop_bits :2; /* 停止位 */rt_uint32_t parity :2; /* 奇偶校驗位 */rt_uint32_t bit_order :1; /* 高位在前或者低位在前 */rt_uint32_t invert :1; /* 模式 */rt_uint32_t bufsz :16; /* 接收數據緩沖區大小 */rt_uint32_t reserved :4; /* 保留位 */
};
接收緩沖區:當串口使用中斷接收模式打開時,串口驅動框架會根據 RT_SERIAL_RB_BUFSZ 大小開辟一塊緩沖區用于保存接收到的數據,底層驅動接收到一個數據,都會在中斷服務程序里面將數據放入緩沖區。
設置發送完成回調函數
rt_err_t rt_device_set_tx_complete(rt_device_t dev, rt_err_t (*tx_done)(rt_device_t dev,void *buffer));
設置接收回調函數
rt_err_t rt_device_set_rx_indicate(rt_device_t dev, rt_err_t (*rx_ind)(rt_device_t dev,rt_size_t size));
DMA接收及輪詢發送
當串口收到一批數據后,會調用接收回調函數,接收回調函數會把此時緩沖區的數據大小通過消息隊列發送給等待的數據處理線程。線程獲取到消息后被激活,并讀取數據。一般情況下 DMA 接收模式會結合 DMA 接收完成中斷和串口空閑中斷完成數據接收。
#include <rtthread.h>#define SAMPLE_UART_NAME "uart3" /* 串口設備名稱 *//* 串口接收消息結構*/
struct rx_msg
{rt_device_t dev;rt_size_t size;
};
/* 串口設備句柄 */
static rt_device_t serial;
}
/* 消息隊列控制塊 */
static struct rt_messagequeue rx_mq;