基於STM32之UART串口通信協議(二)發送

来源:https://www.cnblogs.com/ChurF-Lin/archive/2019/05/05/10798193.html
-Advertisement-
Play Games

一、前言 1、簡介 在上一篇UART詳解中,已經有了關於UART的詳細介紹了,也有關於如何使用STM32CubeMX來配置UART的操作了,而在該篇博客,主要會講解一下如何實現UART串口的發送功能。 2、UART簡介 嵌入式開發中,UART串口通信協議是我們常用的通信協議之一,全稱叫做通用非同步收發 ...


一、前言

1、簡介

  在上一篇UART詳解中,已經有了關於UART的詳細介紹了,也有關於如何使用STM32CubeMX來配置UART的操作了,而在該篇博客,主要會講解一下如何實現UART串口的發送功能。

2、UART簡介

  嵌入式開發中,UART串口通信協議是我們常用的通信協議之一,全稱叫做通用非同步收發傳輸器(Universal Asynchronous Receiver/Transmitter)。

3、準備工作

  在UART詳解中已經有了詳細的說明,在這裡就不說明瞭。

註:

  建議每次編寫好一個相關功能且測試功能成功使用後,保存並壓縮成一份Demo常式,方便日後有需要的時候可以直接使用。

  例如:

 

二、CubeMx配置及函數說明

說明:

  這篇用到的配置跟UART詳解里的配置都相同,可以按照UART詳解來配置好時鐘、UART即可。

  所以在進行下一步之前,先確保已經按照UART詳解的配置步驟配置好了,然後再進行後面的操作。

1、CubeMx配置

  按照上一篇UART詳解來配置

2、函數說明

1)CubeMX生成的UART初始化(在usart.c中)

  
 1 UART_HandleTypeDef huart1;
 2 
 3 /* USART1 init function */
 4 
 5 void MX_USART1_UART_Init(void)
 6 {
 7 
 8   huart1.Instance = USART1;
 9   huart1.Init.BaudRate = 115200;
10   huart1.Init.WordLength = UART_WORDLENGTH_8B;
11   huart1.Init.StopBits = UART_STOPBITS_1;
12   huart1.Init.Parity = UART_PARITY_NONE;
13   huart1.Init.Mode = UART_MODE_TX_RX;
14   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
15   huart1.Init.OverSampling = UART_OVERSAMPLING_16;
16   if (HAL_UART_Init(&huart1) != HAL_OK)
17   {
18     Error_Handler();
19   }
20 
21 }
22 
23 void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
24 {
25 
26   GPIO_InitTypeDef GPIO_InitStruct = {0};
27   if(uartHandle->Instance==USART1)
28   {
29   /* USER CODE BEGIN USART1_MspInit 0 */
30 
31   /* USER CODE END USART1_MspInit 0 */
32     /* USART1 clock enable */
33     __HAL_RCC_USART1_CLK_ENABLE();
34   
35     __HAL_RCC_GPIOA_CLK_ENABLE();
36     /**USART1 GPIO Configuration    
37     PA9     ------> USART1_TX
38     PA10     ------> USART1_RX 
39     */
40     GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
41     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
42     GPIO_InitStruct.Pull = GPIO_PULLUP;
43     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
44     GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
45     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
46 
47   /* USER CODE BEGIN USART1_MspInit 1 */
48 
49   /* USER CODE END USART1_MspInit 1 */
50   }
51 }
52 
53 void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
54 {
55 
56   if(uartHandle->Instance==USART1)
57   {
58   /* USER CODE BEGIN USART1_MspDeInit 0 */
59 
60   /* USER CODE END USART1_MspDeInit 0 */
61     /* Peripheral clock disable */
62     __HAL_RCC_USART1_CLK_DISABLE();
63   
64     /**USART1 GPIO Configuration    
65     PA9     ------> USART1_TX
66     PA10     ------> USART1_RX 
67     */
68     HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
69 
70   /* USER CODE BEGIN USART1_MspDeInit 1 */
71 
72   /* USER CODE END USART1_MspDeInit 1 */
73   }
74 } 
USART init

2)HAL庫函數HAL_UART_Transmit(在stm32f4xx_hal_uart.c中)

說明:

  該函數能夠通過huart串口發送Size位pData數據。

參數說明:

  • huart    :選擇用來發送的UART串口

  • pData   :指向將要發送的數據的指針

  • Size      :發送數據的大小

  • Timeout:超時時間

  
 1 /**
 2   * @brief  Sends an amount of data in blocking mode.
 3   * @param  huart  Pointer to a UART_HandleTypeDef structure that contains
 4   *                the configuration information for the specified UART module.
 5   * @param  pData Pointer to data buffer
 6   * @param  Size Amount of data to be sent
 7   * @param  Timeout Timeout duration
 8   * @retval HAL status
 9   */
10 HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
11 {
12   uint16_t *tmp;
13   uint32_t tickstart = 0U;
14 
15   /* Check that a Tx process is not already ongoing */
16   if (huart->gState == HAL_UART_STATE_READY)
17   {
18     if ((pData == NULL) || (Size == 0U))
19     {
20       return  HAL_ERROR;
21     }
22 
23     /* Process Locked */
24     __HAL_LOCK(huart);
25 
26     huart->ErrorCode = HAL_UART_ERROR_NONE;
27     huart->gState = HAL_UART_STATE_BUSY_TX;
28 
29     /* Init tickstart for timeout managment */
30     tickstart = HAL_GetTick();
31 
32     huart->TxXferSize = Size;
33     huart->TxXferCount = Size;
34     while (huart->TxXferCount > 0U)
35     {
36       huart->TxXferCount--;
37       if (huart->Init.WordLength == UART_WORDLENGTH_9B)
38       {
39         if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
40         {
41           return HAL_TIMEOUT;
42         }
43         tmp = (uint16_t *) pData;
44         huart->Instance->DR = (*tmp & (uint16_t)0x01FF);
45         if (huart->Init.Parity == UART_PARITY_NONE)
46         {
47           pData += 2U;
48         }
49         else
50         {
51           pData += 1U;
52         }
53       }
54       else
55       {
56         if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
57         {
58           return HAL_TIMEOUT;
59         }
60         huart->Instance->DR = (*pData++ & (uint8_t)0xFF);
61       }
62     }
63 
64     if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK)
65     {
66       return HAL_TIMEOUT;
67     }
68 
69     /* At end of Tx process, restore huart->gState to Ready */
70     huart->gState = HAL_UART_STATE_READY;
71 
72     /* Process Unlocked */
73     __HAL_UNLOCK(huart);
74 
75     return HAL_OK;
76   }
77   else
78   {
79     return HAL_BUSY;
80   }
81 }
HAL_UART_Transmit

 

三、代碼部分:實現UART發送

1、直接發送

1)在main主函數中定義一個數組

1   /* USER CODE BEGIN 1 */
2     unsigned char uTx_Data[5] = {0x41, 0x42, 0x43, 0x44, 0x45};    //數組內十六進位代表“ABCDE”
3   /* USER CODE END 1 */

2)在main主函數中的while迴圈中調用HAL庫UART發送函數

/* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
        /* UART發送 */
      HAL_UART_Transmit(&huart1, uTx_Data, sizeof(uTx_Data), 0xffff);
        /* 延遲1s */
        HAL_Delay(1000);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

整個main函數如下:

 1 int main(void)
 2 {
 3   /* USER CODE BEGIN 1 */
 4     unsigned char uTx_Data[5] = {0x41, 0x42, 0x43, 0x44, 0x45};    //數組內十六進位代表“ABCDE”
 5   /* USER CODE END 1 */
 6   
 7 
 8   /* MCU Configuration--------------------------------------------------------*/
 9 
10   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
11   HAL_Init();
12 
13   /* USER CODE BEGIN Init */
14 
15   /* USER CODE END Init */
16 
17   /* Configure the system clock */
18   SystemClock_Config();
19 
20   /* USER CODE BEGIN SysInit */
21 
22   /* USER CODE END SysInit */
23 
24   /* Initialize all configured peripherals */
25   MX_GPIO_Init();
26   MX_USART1_UART_Init();
27   /* USER CODE BEGIN 2 */
28 
29   /* USER CODE END 2 */
30 
31   /* Infinite loop */
32   /* USER CODE BEGIN WHILE */
33   while (1)
34   {
35         /* UART發送 */
36       HAL_UART_Transmit(&huart1, uTx_Data, sizeof(uTx_Data), 0xffff);
37         /* 延遲1s */
38         HAL_Delay(1000);
39     /* USER CODE END WHILE */
40 
41     /* USER CODE BEGIN 3 */
42   }
43   /* USER CODE END 3 */
44 }

3)編譯、下載燒寫

4)實現效果(在PC端串口助手中顯示發送成功)

2、字元串發送

說明:

  前面的發送方式,不僅要傳入句柄參數,還有數組、長度、超時時間參數。

  為了簡便發送,我們可以專門寫一個字元串發送函數,可以直接傳入一個數組即可發送,可以更簡便地實現字元串發送。

  優點是,發送數據更簡便,能夠一次性發送很長的數據數組。

  但缺點就是不能控制發送的長度,會將整個數據數組發出。

1)在Uart.c中添加vUser_UART_SendString函數

 1 /* USER CODE BEGIN 1 */
 2 void vUser_UART_SendString(UART_HandleTypeDef* uartHandle, unsigned char * uData)
 3 {
 4     /* -1- 判斷數據是否發送完畢 */
 5     while(*uData)        //若為空即發送完畢,若不為空則還有數據
 6     {
 7         /* -2- 發送1Byte */
 8         HAL_UART_Transmit(uartHandle, uData, 1, 0xffff);
 9         /* -3- 移至下1Byte */
10         uData++;
11     }
12 }
13 /* USER CODE END 1 */

2)在Uart.h中聲明一下vUser_UART_SendString函數(聲明後就可以在別的地方調用該函數)

1 /* USER CODE BEGIN Prototypes */
2 extern void vUser_UART_SendString(UART_HandleTypeDef* uartHandle, unsigned char * uData);
3 /* USER CODE END Prototypes */

3)在main主函數中定義一個數組

1   /* USER CODE BEGIN 1 */
2     unsigned char uTx_Data[] = "\r\n Hallo World! 你好,世界!";
3   /* USER CODE END 1 */

4)在main主函數的while迴圈中調用字元串發送函數

 1   /* Infinite loop */
 2   /* USER CODE BEGIN WHILE */
 3   while (1)
 4   {
 5         /* 字元串發送 */
 6       vUser_UART_SendString(&huart1, uTx_Data);
 7         /* 延遲1s */
 8         HAL_Delay(1000);
 9     /* USER CODE END WHILE */
10 
11     /* USER CODE BEGIN 3 */
12   }
13   /* USER CODE END 3 */

整個main函數如下:

 1 int main(void)
 2 {
 3   /* USER CODE BEGIN 1 */
 4     unsigned char uTx_Data[] = "\r\n Hallo World! 你好,世界!";
 5   /* USER CODE END 1 */
 6   
 7 
 8   /* MCU Configuration--------------------------------------------------------*/
 9 
10   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
11   HAL_Init();
12 
13   /* USER CODE BEGIN Init */
14 
15   /* USER CODE END Init */
16 
17   /* Configure the system clock */
18   SystemClock_Config();
19 
20   /* USER CODE BEGIN SysInit */
21 
22   /* USER CODE END SysInit */
23 
24   /* Initialize all configured peripherals */
25   MX_GPIO_Init();
26   MX_USART1_UART_Init();
27   /* USER CODE BEGIN 2 */
28 
29   /* USER CODE END 2 */
30 
31   /* Infinite loop */
32   /* USER CODE BEGIN WHILE */
33   while (1)
34   {
35         /* UART發送 */
36       vUser_UART_SendString(&huart1, uTx_Data);
37         /* 延遲1s */
38         HAL_Delay(1000);
39     /* USER CODE END WHILE */
40 
41     /* USER CODE BEGIN 3 */
42   }
43   /* USER CODE END 3 */
44 }

5)編譯、下載燒寫

6)實現效果(在PC端串口助手顯示發送成功)

3、printf發送

說明:

  這種發送方式就是相當於編寫c語言的時候,在小黑框中列印自己想要列印的東西,我們也可以在串口助手上實現一樣的功能。

  由於篇幅長度有限,可能需要後續有空再補上這一發送方式,在這裡先不講解了。

 

四、結尾

1、總結

  這篇博客主要是以上一篇UART詳解為基礎,來實現使用UART來實現發送功能,在這裡簡單講解了兩種發送方式,而在後續如果有機會還會補上第三種printf發送方式的。

  如果大家還不清楚UART串口通信協議的,可以閱讀一下上一篇UART詳解。若還有對於此篇博客不懂之處,可在下方留言評論,我會儘快回覆。

2、回顧

3、後續

~

~

~

~

感謝閱讀~

 歡迎大家關註我的博客,一起分享嵌入式知識~


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • windows 文件操作命令 cd 切換文件目錄 dir 顯示文件目錄內容 md 創建文件夾 rd 刪除文件夾 copy 拷貝文件 move 移動文件 del 刪除文件 replace 替換文件 mklinnk 創建符號鏈接 attrib 查看或修改文件或目錄屬性 type 查看文件內容 more ...
  • @ "TOC" 1.首先下載虛擬機管理軟體(推薦使用VMware Workstation) 可以在這裡下載 https://blog.51cto.com/happynews/2285644 然後安裝 安裝完成後,打開時推薦使用右鍵,用管理員運行 2.下載你所需要的系統鏡像文件 其實不同版本的linu ...
  • 這裡以Centos7為例: 使用tree命令查看/目錄結構如下: 下麵我們主要探討如下主要目錄: /:根目錄不必多說,文件系統的最頂端,存放系統所有目錄。 bin:該目錄主要存放系統運行所需要的重要命令,和普通用戶可以使用的絕大部分命令。 sbin:主要存放系統管理員使用的系統管理的命令。 etc: ...
  • @ "TOC" quickLook插件是Mac上的快速瀏覽的一個功能,現在win10系統上也能安裝插件,這個插件可以快速瀏覽txt,doc,圖片,表格等文件如下圖: 我認為最方便的地方是你需要查看某一個文件內容不需要編輯的時候,又不想用wps打開時就可以用這個簡單的插件。 安裝方式也很簡單,但是需要 ...
  • 一、echo 1.顯示普通字元串: 這裡的雙引號可以省略。 2.顯示轉義字元: 3.顯示變數: read 命令從標準輸入中讀取一行,並把輸入行的每個欄位的值指定給 shell 變數 輸出: 4.顯示換行: 輸出: 5.顯示不換行: 輸出: 6.顯示定向至文件: 輸出: 7.原樣輸出字元串,不進行轉義 ...
  • [20190505]ts 命令在哪裡.txt--//在論壇問一下ts命令在哪裡?沒人解答,自己也google看了一下:https://unix.stackexchange.com/questions/272433/piping-into-moreutils-ts-with-nanosecond-pr ...
  • 一、sdhci core說明 1、sdhci說明 具體參考《host(第一章)——概述》 SDHC:Secure Digital(SD) Host Controller,是指一套sd host控制器的設計標準,其寄存器偏移以及意義都有一定的規範,並且提供了對應的驅動程式,方便vendor進行host ...
  • 由於linux最小單位為分,但是很多需求上需要按秒執行,如30秒請求一個URL地址之類的,思路很簡單就是修改計劃任務腳本用迴圈控制,代碼如下: 上述代碼中XXXXXX為你需要執行的URL地址 以上示例以寶塔下計劃任務為基礎所演示 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...