串口設備使用示例
中斷接收及輪詢發送
示例代碼的主要步驟如下所示:
-
首先查找串口設備獲取設備句柄。
-
初始化回調函數發送使用的信號量,然后以讀寫及中斷接收方式打開串口設備。
-
設置串口設備的接收回調函數,之后發送字符串,並創建讀取數據線程。
-
讀取數據線程會嘗試讀取一個字符數據,如果沒有數據則會掛起並等待信號量,當串口設備接收到一個數據時會觸發中斷並調用接收回調函數,此函數會發送信號量喚醒線程,此時線程會馬上讀取接收到的數據。
-
此示例代碼不局限於特定的 BSP,根據 BSP 注冊的串口設備,修改示例代碼宏定義 SAMPLE_UART_NAME 對應的串口設備名稱即可運行。
運行序列圖如下圖所示:

/* * 程序清單:這是一個 串口 設備使用例程 * 例程導出了 uart_sample 命令到控制終端 * 命令調用格式:uart_sample uart2 * 命令解釋:命令第二個參數是要使用的串口設備名稱,為空則使用默認的串口設備 * 程序功能:通過串口輸出字符串"hello RT-Thread!",然后錯位輸出輸入的字符 */
1 #include <rtthread.h> 2 3 #define SAMPLE_UART_NAME "uart2" 4 5 /* 用於接收消息的信號量 */ 6 static struct rt_semaphore rx_sem; 7 static rt_device_t serial; 8 9 /* 接收數據回調函數 */ 10 static rt_err_t uart_input(rt_device_t dev, rt_size_t size) 11 { 12 /* 串口接收到數據后產生中斷,調用此回調函數,然后發送接收信號量 */ 13 rt_sem_release(&rx_sem); 14 15 return RT_EOK; 16 } 17 18 static void serial_thread_entry(void *parameter) 19 { 20 char ch; 21 22 while (1) 23 { 24 /* 從串口讀取一個字節的數據,沒有讀取到則等待接收信號量 */ 25 while (rt_device_read(serial, -1, &ch, 1) != 1) 26 { 27 /* 阻塞等待接收信號量,等到信號量后再次讀取數據 */ 28 rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
//接收不到信號量就一直在這里等,等到之后就返回1,然后再進入while判斷,判斷不通過就進入rt_device_write() 29 } 30 /* 讀取到的數據通過串口錯位輸出 */ 31 ch = ch + 1; 32 rt_device_write(serial, 0, &ch, 1); 33 } 34 } 35 36 static int uart_sample(int argc, char *argv[]) 37 { 38 rt_err_t ret = RT_EOK; 39 char uart_name[RT_NAME_MAX]; 40 char str[] = "hello RT-Thread!\r\n"; 41 42 if (argc == 2) 43 { 44 rt_strncpy(uart_name, argv[1], RT_NAME_MAX); 45 } 46 else 47 { 48 rt_strncpy(uart_name, SAMPLE_UART_NAME, RT_NAME_MAX); 49 } 50 51 /* 查找系統中的串口設備 */ 52 serial = rt_device_find(uart_name); 53 if (!serial) 54 { 55 rt_kprintf("find %s failed!\n", uart_name); 56 return RT_ERROR; 57 } 58 59 /* 初始化信號量 */ 60 rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO); 61 /* 以中斷接收及輪詢發送模式打開串口設備 */ 62 rt_device_open(serial, RT_DEVICE_FLAG_INT_RX); 63 /* 設置接收回調函數 */ 64 rt_device_set_rx_indicate(serial, uart_input); 65 /* 發送字符串 */ 66 rt_device_write(serial, 0, str, (sizeof(str) - 1)); 67 68 /* 創建 serial 線程 */ 69 rt_thread_t thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 25, 10); 70 /* 創建成功則啟動線程 */ 71 if (thread != RT_NULL) 72 { 73 rt_thread_startup(thread); 74 } 75 else 76 { 77 ret = RT_ERROR; 78 } 79 80 return ret; 81 } 82 /* 導出到 msh 命令列表中 */ 83 MSH_CMD_EXPORT(uart_sample, uart device sample);
翻譯 朗讀 復制 正在查詢,請稍候…… 重試 朗讀 復制 復制 朗讀 復制 via 谷歌翻譯(國內)譯
