【嵌入式系統】STM32串口通信的四種方法(基于RTOS)

目錄

  • 1、串行通信的基本參數
  • 2、輪詢方式代碼效果
  • 3、中斷方式代碼效果
  • 4、中斷加上時間戳方式代碼及效果
  • 5、DMA空閑中斷方式接收數據

1、串行通信的基本參數

串行端口的通信方式是將字節拆分成一個接一個的位再傳輸出去,接收方再將此一個一個的位組合成原來的字符,如此形成一個字節的完整傳輸,在數據傳輸時,應在通信端口的初始化時設置幾個通信參數。

1)波特率,即傳送數據的速度。波特率的意思就是在一秒中可以傳輸的數據位數,單位是bps。如果采用波特率4800bps進行傳輸,那么每秒可以傳輸600個byte。
2)數據位,當接收設備收到起始位后,緊接著就會收到數據位,數據位的個數可以是5、6、7或者8位。在字符數據傳輸的過程中,數據位從最低有效位開始傳輸。
3)起始位,在串口線上,沒有數據傳輸時處于邏輯"1"狀態,當發送設備要發送一個字符數據時,首先發出一個邏輯“0"信號,這個邏輯低電平就是起始位。
4)停止位,是一個字符數據的結束標志,它可以是1位、1.5位或者2位。
5)奇偶校驗位,數據位發送完之后,就可以發送奇偶校驗位。奇偶校驗用于有限差錯校驗,通信雙方在通信時約定一致的奇偶校驗方式。

在這里插入圖片描述

2、輪詢方式代碼效果

在這里插入圖片描述

char ch;
/* Infinite loop */
for(;;)
{
if(HAL_UART_Receive(&huart1,(uint8_t*)&ch,1,100) == HAL_OK)printf("%c",ch);//osDelay(1);
}

在這里插入圖片描述
輪詢方式不適合接收一大段的數據,否則會卡死,如上圖。

3、中斷方式代碼效果

在這里插入圖片描述

#define MAX_RECV_LEN 128							//定義的一次最多接收字節的位數
uint8_t rx1_buff[MAX_RECV_LEN] = {0};	//串口接收數據緩沖
uint8_t *pBuf;												//當前接收字節存放的位置指針
uint8_t line_flag = 0;								//一行數據接收結束標志

在這里插入圖片描述

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; // 已接收一個字節數據,當前存儲位置指針后移 if(pBuf == rx1_buff + MAX_RECV_LEN) // 如果指針已移出數組邊界 pBuf = rx1_buff; 									// 重新指向數組開頭 else if(*(pBuf - 1) == '\n') // 如果之前接收到‘\n’換行符,則表示接收完成 {line_flag = 1;		// 行接收標志置1*pBuf = '\0';			// 添加字符串末尾結束符pBuf = rx1_buff;	// 重新指向數組開頭}__HAL_UNLOCK(UartHandle); 								// 解鎖串口HAL_UART_Receive_IT(UartHandle, pBuf, 1); // 重新開啟接收中斷} 
}

缺點:由于中斷接收是以換行符為標準的,這里我們按下兩次發送鍵才將4個數字全部發送。
在這里插入圖片描述

4、中斷加上時間戳方式代碼及效果

利用時間戳來輔助判斷接收空閑,實現了分段發送。

 for(;;){if(recv_tick>0 && (osKernelGetTickCount()-recv_tick)>=20){*pBuf = '\0';	//添加字符串末尾結束符printf("%s",rx1_buff);recv_tick=0;pBuf = rx1_buff;//重新指向數組開頭}}
//加了時間戳的完善代碼
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle) 
{ if (UartHandle->Instance == USART1) { ++ pBuf; // 已接收一個字節數據,當前存儲位置指針后移 if(pBuf == rx1_buff + MAX_RECV_LEN) // 如果指針已移出數組邊界 pBuf = rx1_buff; 									// 重新指向數組開頭 recv_tick = osKernelGetTickCount();__HAL_UNLOCK(UartHandle); 								// 解鎖串口HAL_UART_Receive_IT(UartHandle, pBuf, 1); // 重新開啟接收中斷} 
}

在這里插入圖片描述

5、DMA空閑中斷方式接收數據

步驟總結:

1、開啟串口DMA接收
2、串口收到數據,DMA不斷傳輸數據到接收緩沖
3、一幀數據發送完畢,串口暫時空閑,觸發串口空閑中斷
4、在串口中斷函數中,計算剛才收到的數據長度
5、復制接收緩沖數據,清除標志位,開始下一幀接收

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

//添加串口數據緩沖、DMA數據緩沖、接收標志
uint8_t data_buff[MAX_BUFF_LEN] = {0};	//串口接收數據緩沖
uint8_t dma_buff[MAX_BUFF_LEN] = {0};		//DMA數據緩沖
uint32_t recv_len = 0;			//接收數據長度

在這里插入圖片描述

#define MAX_BUFF_LEN 512
extern uint8_t data_buff[MAX_BUFF_LEN];
extern uint8_t dma_buff[MAX_BUFF_LEN];
extern uint32_t recv_len;
extern void UART_IDLE_Callback(UART_HandleTypeDef *huart);

在這里插入圖片描述

void UART_IDLE_Callback(UART_HandleTypeDef *huart)
{if (__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET &&huart->Instance == USART1){__HAL_UART_CLEAR_IDLEFLAG(huart);HAL_UART_DMAStop(huart);recv_len = MAX_BUFF_LEN - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);if (recv_len < MAX_BUFF_LEN - 1){memcpy(data_buff, dma_buff, recv_len);data_buff[recv_len] = '\0';}else{recv_len = 0;}__HAL_UNLOCK(huart);HAL_UART_Receive_DMA(huart, dma_buff, MAX_BUFF_LEN);}
}

在這里插入圖片描述

void USART1_IRQHandler(void)
{/* USER CODE BEGIN USART1_IRQn 0 *//* USER CODE END USART1_IRQn 0 */HAL_UART_IRQHandler(&huart1);/* USER CODE BEGIN USART1_IRQn 1 */UART_IDLE_Callback(&huart1);/* USER CODE END USART1_IRQn 1 */
}

在這里插入圖片描述

void StartTaskUsart(void *argument)
{/* USER CODE BEGIN StartTaskUsart */__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);		//使能idle中斷HAL_UART_Receive_DMA(&huart1,dma_buff,MAX_BUFF_LEN);//打開DMA接收,數據存入dma_buff數組中/* Infinite loop */for(;;){if(recv_len>0){printf("%s",(char *)data_buff);recv_len=0;}}osDelay(1);/* USER CODE END StartTaskUsart */
}

這種方法效果極其有效:
使用串口調試助手軟件,定時每隔20ms發送總共100個字節的多行字符串對STM32串口接收功能進行測試。
如圖所示,發送數據個數超過50000字節后停止發送,接收到的STM32回送數據個數與發送數據個數相同。
在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/377737.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/377737.shtml
英文地址,請注明出處:http://en.pswp.cn/news/377737.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

大數據 java 代碼示例_Java變量類型與示例

大數據 java 代碼示例Java變量 (Java variables) Variables are the user-defined names of the memory blocks, and their values can be changed at any time during program execution. They play an important role in a class/program as they help in to store, retrieve…

畢業設計

位置跟蹤系統工作原理&#xff08;博聞網&#xff09; http://science.bowenwang.com.cn/location-tracking.htm Azuma是這樣定義增強現實的 :虛實結合 ,實時交互 ,三維注冊 環境搭建&#xff1a; http://cvchina.net/thread-173-1-1.html http://blog.csdn.net/jdh99/article/…

十五、聚類的評估

一、Given Label 均一性homogeneity&#xff1a;一個簇中只包含一個類別樣本&#xff0c;Precision 完整性completeness&#xff1a;同類別樣本被歸到同一個簇中&#xff0c;Recall 將均一性h和完整性c進行結合(二者加權平均)得到V-Measure&#xff0c;&#xff0c;β為權重 …

SQL SERVER作業的Schedules淺析

SQL SERVER作業的計劃&#xff08;Schedules&#xff09;&#xff0c;如果你沒仔細研究過或沒有應用一些復雜的計劃&#xff08;Schedules&#xff09;&#xff0c;那么你覺得SQL SERVER作業的計劃(Schedules)非常好用&#xff0c;也沒啥問題&#xff0c;但是我要告訴你一個“殘…

leetcode 51. N 皇后 思考分析

目錄題目思考AC代碼題目 n 皇后問題研究的是如何將 n 個皇后放置在 nn 的棋盤上&#xff0c;并且使皇后彼此之間不能相互攻擊。 思考 首先以N4為例&#xff0c;畫出解空間樹的一部分&#xff1a; 根據模板&#xff1a; void backtracking(參數) {if(終止條件){存放結果…

Django實戰(18):提交訂單

前面的內容已經基本上涵蓋了Django開發的主要方面&#xff0c;我們從需求和界面設計出發&#xff0c;創建模型和修改模型&#xff0c;并通過scaffold作為開發的起點&#xff1b;在scaffold的基礎上重新定制模板&#xff0c;并且通過Model類和Form類對用戶輸入的數據進行校驗。我…

No module named ‘tensorflow.examples‘解決方案

想從tensorflow中導入mnist手寫數字數據集&#xff0c;結果報錯 from tensorflow.examples.tutorials.mnist import input_data import tensorflow.compat.v1 as tf tf.disable_v2_behavior()my_mnist input_data.read_data_sets("MNIST_data_bak/", one_hotTrue)&…

julia example_使用Julia中的Example的sign()函數

julia exampleJulia| sign()函數 (Julia | sign() function) sign() function is a library function in Julia programming language, it returns the sign of the given value in the form of -1/1. sign()函數是Julia編程語言中的庫函數&#xff0c;它以-1 / 1的形式返回給…

.NET通用基本權限系統

DEMO下載地址&#xff1a; http://download.csdn.net/detail/shecixiong/5372895 一、開發技術&#xff1a;B/S(.NET C# ) 1、Windows XP以上 (支援最新Win 8) 2、Microsoft Visual Studio 2010/2012 C#.NET 3、.NET Framework 4.0以上 (支援最新4.5版本) 4、SQL Server 2005以…

leetcode 37. 解數獨 思考分析

目錄題目核心思路的不斷細化1、核心框架2、考慮到每個位置的工作3、考慮到到達最后一列、該位置的數已經預置的情況4、判斷是否符合規則的函數5、確定遞歸終止條件確定函數返回值AC代碼題目 編寫一個程序&#xff0c;通過填充空格來解決數獨問題。 一個數獨的解法需遵循如下規…

快速完成兼職外包開發任務

做了很多年的開發相關的工作&#xff0c;做過兼職開發&#xff0c;也做過外包一些開發項目。 兼職人員角色時 正是經歷這些事情時&#xff0c;每次就要提前很費經的跟公司溝通&#xff0c;讓他們把公司內部的svn開發出去&#xff0c;但是就是很難&#xff0c;會涉及到安全各方的…

使用YOLOv5訓練NEU-DET數據集

一、下載YOLOv5源碼和NEU-DET(鋼材表面缺陷)數據集 YOLOv5源碼 NEU-DET(鋼材表面缺陷)數據集 這里的數據集已經經過處理了&#xff0c;下載即可 若通過其他途徑下載的原始數據集標簽為xml格式&#xff0c;需要轉化為txt格式XML轉txt格式腳本 二、數據集準備 NEU-DET(鋼材表…

kotlin獲取屬性_Kotlin程序獲取系統MAC地址

kotlin獲取屬性The task is to get system MAC address. 任務是獲取系統MAC地址。 package com.includehelpimport java.net.InetAddressimport java.net.NetworkInterface//Function to get System MACfun getSystemMac(): String? {return try {val OSName System.getProp…

帶分頁功能的SSH整合,DAO層經典封裝

任何一個封裝講究的是&#xff0c;使用&#xff0c;多狀態。Action&#xff1a;任何一個Action繼承分頁有關參數類PageManage&#xff0c;自然考慮的到分頁效果&#xff0c;我們必須定義下幾個分頁的參數。并根據這個參數進行查值。然后在繼承ServiceManage&#xff0c;Service…

在windows phone Mango中使用原生代碼開發程序

本文不討論創建可執行的exe程序,主要想說明怎么在silverlight程序里面調用由原生代碼所編寫的DLL(C / ARM). 原生代碼可以調用更多的API,但是這并不是說你就能隨意獲得那些你沒有權限的資源,比如,你可以使用CopyFile這個API,但是如果你試圖把文件Copy到\Windows文件夾,就會得到…

leetcode 198. 打家劫舍 思考分析

目錄1、題目2、求解思路3、代碼1、題目 你是一個專業的小偷&#xff0c;計劃偷竊沿街的房屋。每間房內都藏有一定的現金&#xff0c;影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統&#xff0c;如果兩間相鄰的房屋在同一晚上被小偷闖入&#xff0c;系統會自動…

找不到Windows照片查看器解決方法

桌面創建一個txt文本 復制這些命令&#xff0c;之后將后綴改為.reg&#xff0c;右擊管理員身份運行即可 Windows Registry Editor Version 5.00 ; Change Extensions File Type [HKEY_CURRENT_USER\Software\Classes\.jpg] "PhotoViewer.FileAssoc.Tiff" ; Change E…

數字拆分為斐波那契數列_檢查數字是否為斐波那契

數字拆分為斐波那契數列Description: 描述&#xff1a; We are often used to generate Fibonacci numbers. But in this article, we are going to learn about how to search Fibonacci numbers in an array? 我們經常被用來產生斐波那契數。 但是在本文中&#xff0c;我們…

伙伴分配器的一個極簡實現

提起buddy system相信很多人不會陌生&#xff0c;它是一種經典的內存分配算法&#xff0c;大名鼎鼎的Linux底層的內存管理用的就是它。這里不探討內核這么復雜實現&#xff0c;而僅僅是將該算法抽象提取出來&#xff0c;同時給出一份及其簡潔的源碼實現&#xff0c;以便定制擴展…

[USACO3.2.3 Spinning Wheels]

[關鍵字]&#xff1a;模擬 枚舉 [題目大意]&#xff1a;有5個輪子&#xff0c;每個輪子優r個缺口并且會按一定速度不停轉動&#xff0c;問什么時候可以使一條光線射過所有輪子。 // [分析]&#xff1a;從0到1000&#xff08;或其他的&#xff09;枚舉分鐘然后判斷&#xff0c;當…