【嵌入式系统】STM32串口通信的四种方法(基于RTOS)
目錄
- 1、串行通信的基本參數(shù)
- 2、輪詢方式代碼效果
- 3、中斷方式代碼效果
- 4、中斷加上時間戳方式代碼及效果
- 5、DMA空閑中斷方式接收數(shù)據(jù)
1、串行通信的基本參數(shù)
串行端口的通信方式是將字節(jié)拆分成一個接一個的位再傳輸出去,接收方再將此一個一個的位組合成原來的字符,如此形成一個字節(jié)的完整傳輸,在數(shù)據(jù)傳輸時,應(yīng)在通信端口的初始化時設(shè)置幾個通信參數(shù)。
1)波特率,即傳送數(shù)據(jù)的速度。波特率的意思就是在一秒中可以傳輸?shù)臄?shù)據(jù)位數(shù),單位是bps。如果采用波特率4800bps進行傳輸,那么每秒可以傳輸600個byte。
2)數(shù)據(jù)位,當接收設(shè)備收到起始位后,緊接著就會收到數(shù)據(jù)位,數(shù)據(jù)位的個數(shù)可以是5、6、7或者8位。在字符數(shù)據(jù)傳輸?shù)倪^程中,數(shù)據(jù)位從最低有效位開始傳輸。
3)起始位,在串口線上,沒有數(shù)據(jù)傳輸時處于邏輯"1"狀態(tài),當發(fā)送設(shè)備要發(fā)送一個字符數(shù)據(jù)時,首先發(fā)出一個邏輯“0"信號,這個邏輯低電平就是起始位。
4)停止位,是一個字符數(shù)據(jù)的結(jié)束標志,它可以是1位、1.5位或者2位。
5)奇偶校驗位,數(shù)據(jù)位發(fā)送完之后,就可以發(fā)送奇偶校驗位。奇偶校驗用于有限差錯校驗,通信雙方在通信時約定一致的奇偶校驗方式。
2、輪詢方式代碼效果
char ch; /* Infinite loop */ for(;;) { if(HAL_UART_Receive(&huart1,(uint8_t*)&ch,1,100) == HAL_OK)printf("%c",ch);//osDelay(1); }
輪詢方式不適合接收一大段的數(shù)據(jù),否則會卡死,如上圖。
3、中斷方式代碼效果
#define MAX_RECV_LEN 128 //定義的一次最多接收字節(jié)的位數(shù) uint8_t rx1_buff[MAX_RECV_LEN] = {0}; //串口接收數(shù)據(jù)緩沖 uint8_t *pBuf; //當前接收字節(jié)存放的位置指針 uint8_t line_flag = 0; //一行數(shù)據(jù)接收結(jié)束標志 void StartTaskUsart(void *argument) {/* USER CODE BEGIN StartTaskUsart */printf("HELLO WORLD\n");pBuf = rx1_buff;HAL_UART_Receive_IT(&huart1,pBuf, 1); /* Infinite loop */for(;;){if(line_flag){printf("%s",rx1_buff);line_flag=0;}osDelay(1);}/* USER CODE END StartTaskUsart */ } void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle) { if (UartHandle->Instance == USART1) { ++ pBuf; // 已接收一個字節(jié)數(shù)據(jù),當前存儲位置指針后移 if(pBuf == rx1_buff + MAX_RECV_LEN) // 如果指針已移出數(shù)組邊界 pBuf = rx1_buff; // 重新指向數(shù)組開頭 else if(*(pBuf - 1) == '\n') // 如果之前接收到‘\n’換行符,則表示接收完成 {line_flag = 1; // 行接收標志置1*pBuf = '\0'; // 添加字符串末尾結(jié)束符pBuf = rx1_buff; // 重新指向數(shù)組開頭}__HAL_UNLOCK(UartHandle); // 解鎖串口HAL_UART_Receive_IT(UartHandle, pBuf, 1); // 重新開啟接收中斷} }缺點:由于中斷接收是以換行符為標準的,這里我們按下兩次發(fā)送鍵才將4個數(shù)字全部發(fā)送。
4、中斷加上時間戳方式代碼及效果
利用時間戳來輔助判斷接收空閑,實現(xiàn)了分段發(fā)送。
for(;;){if(recv_tick>0 && (osKernelGetTickCount()-recv_tick)>=20){*pBuf = '\0'; //添加字符串末尾結(jié)束符printf("%s",rx1_buff);recv_tick=0;pBuf = rx1_buff;//重新指向數(shù)組開頭}} //加了時間戳的完善代碼 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle) { if (UartHandle->Instance == USART1) { ++ pBuf; // 已接收一個字節(jié)數(shù)據(jù),當前存儲位置指針后移 if(pBuf == rx1_buff + MAX_RECV_LEN) // 如果指針已移出數(shù)組邊界 pBuf = rx1_buff; // 重新指向數(shù)組開頭 recv_tick = osKernelGetTickCount();__HAL_UNLOCK(UartHandle); // 解鎖串口HAL_UART_Receive_IT(UartHandle, pBuf, 1); // 重新開啟接收中斷} }5、DMA空閑中斷方式接收數(shù)據(jù)
步驟總結(jié):
1、開啟串口DMA接收
2、串口收到數(shù)據(jù),DMA不斷傳輸數(shù)據(jù)到接收緩沖
3、一幀數(shù)據(jù)發(fā)送完畢,串口暫時空閑,觸發(fā)串口空閑中斷
4、在串口中斷函數(shù)中,計算剛才收到的數(shù)據(jù)長度
5、復(fù)制接收緩沖數(shù)據(jù),清除標志位,開始下一幀接收
這種方法效果極其有效:
使用串口調(diào)試助手軟件,定時每隔20ms發(fā)送總共100個字節(jié)的多行字符串對STM32串口接收功能進行測試。
如圖所示,發(fā)送數(shù)據(jù)個數(shù)超過50000字節(jié)后停止發(fā)送,接收到的STM32回送數(shù)據(jù)個數(shù)與發(fā)送數(shù)據(jù)個數(shù)相同。
總結(jié)
以上是生活随笔為你收集整理的【嵌入式系统】STM32串口通信的四种方法(基于RTOS)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 颐和园哪个门可以寄存包
- 下一篇: 【嵌入式系统复习】嵌入式网络与协议栈