第三節: 串口通信(用CubeMX學習STM32)


串口通信


《用CubeMX學習STM32》

注釋 點擊上面藍字進入完整專欄,這個系列所有文章都會整合到這個專欄


本篇博客中用的串口調試助手

鏈接:https://pan.baidu.com/s/1DN60ojns3Wu88frJ5pqSzA
提取碼:6exl
復制這段內容后打開百度網盤手機App,操作更方便哦

時間戳和白字黑字兩個比較雞肋的功能是沒有的


3、STM32串口通信

前言: STM32串口介紹

串行通信是單片機與外部設備或其他計算機交換信息的一個方式, 數據一位一位的按順序傳送, 其優點是只需要一條傳輸線, 協議簡單, 但是缺點就是傳送速度較慢。
串口是單片機上非常便捷的一個工具, 當寫程序需要調試的時候, 它可以很方便的提供調試方法, 只要在一些關鍵代碼執行的地方, 通過串口給串口調試助手發送相關信息, 就可以使我們很方便的查看代碼在這個位置的執行情況。

下面看一下我所使用的單片機上串口的原理圖接線
在這里插入圖片描述

外部的發送端TXD就是單片機串口的接收端USART_RX,   外部接收端RXD就是單片機串口的發送端USART_TX
TXD : Transmit(TX) Data(D)  Receive(RX) Data(D))

USART就是Universal Synchronous/Asynchronous Receiver/Transmitter(通用同步/異步串行接收/發送器)的縮寫 就是一個全雙工的收發器

CH340是串口芯片, 當單片機用一根USB串口線接到電腦的時候, TXD就是指電腦通過數據線給單片機發送數據,對應單片機要接收數據, 因此單片機對應引腳就是RX(接收)

(電腦端發送) TXD -----> USART_RX(單片機接收)

(單片機發送) USART_TX-----> RXD (電腦端接收)

單片機上用跳線帽將PA10, PA9和USART1_RX, USART1_TX連接起來了, 所以我們只需對PA10, PA9配置即可
在這里插入圖片描述

PA9就是USART1_TX, PA10就是USART1_RX
跳線帽將PA9和CH340的RXD, PA10和CH340的TXD連接起來了

下面開始Cube配置+IAR編程


3.1 操作簡介

   使用異步串口通信, 分別以輪詢、中斷、DMA方式使用串口發送數據進行與電腦的通信。 電腦端使用串口調試助手接收單片機發送的信息


3.2 輪詢方式串口通信

單片機會不斷查詢串口對應引腳, 有通信需求就進行處理, 這樣比較浪費CPU資源, 前面在中斷里面也講過, 中斷可以很好地彌補這個。 這里先演示輪詢方式


Step1 : Cube配置

新建一個工程, 同時也加入LED和按鍵等對應引腳的配置, 用以配合串口通信

  • (1) RCC和SYS配置
    在這里插入圖片描述

  • (2)USART1串口1配置
    在這里插入圖片描述

注釋 :

關於異步傳送(Asynchronous)和同步傳送(Synchronous)

1、同步發送 : 發送方和接收方以同一個時鍾源控制發送和接收。 就是當發送方發出數據后, 等待接收方發回響應后才發下一個數據包。

2、異步傳送 : 數據在線路上是以一個字為單位傳送, 各個字符之間可以是接連傳送也可以是間斷傳送, 這完全由發送方根據需要來決定。 發送和接收雙方分別用自己的餓時鍾源來控制發送和接收。   也就是說發送方發出數據后, 不等待接收方回應, 隨時可以發送下一組數據

  • (3) 按鍵和LED引腳配置[Pinout & Configuration]
    在這里插入圖片描述

   跟第二篇博客寫的按鍵的配置一樣的 點擊下方藍字快速回到第二篇博客
   第一節補充: 按鍵操作(CubeMX加HAL庫學STM32系列)

  • (4) 時鍾樹配置[Clock Configuration]
    在這里插入圖片描述

  • (5) 工程配置[Project Manager]
    在這里插入圖片描述

  • (6) 生成代碼 (Generate)
    在這里插入圖片描述


Step2 : IAR或Keil編程

  • (1) 重定向printf函數
在學習C語言的時候, 大家肯定都用過printf這個函數, printf可以將指定字符打印到電腦的顯示器上。
但是, 單片機要使用這個就要把他打印的方向改一下, 不是打印在電腦的命令行中, 而是打印到串口里面,傳輸到串口調試助手. 因此我們需要重定向printf函數。
重定向后我們要將調試信息打印到USART1中, 需要對printf所依賴的打印函數fputc()重定向

在usart.c里面添加如下代碼
在這里插入圖片描述

#include "stdio.h"

/******************************************************************
*@brief  Retargets the C library printf  function to the USART.
*@param  None 
*@retval None
******************************************************************/

#ifdef __GNUC__
	#define PUTCHAR_PROTOTYPE int _io_putchar(int ch)
#else 
	#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__*/
	
PUTCHAR_PROTOTYPE
{
	HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
	return ch;
}

上面除了重定向的代碼, 還包含了一個標准庫頭函數, 最好加上這個, 因為printf函數就是這個庫里面的, 不加的話有時候會出錯或者警告

   Tips : HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF); 是通過串口1傳輸一個字符, ch為字符的地址, 0XFFFF表示超時時間 下面是這個函數的定義 Go to definition進入 stm32f4xx_hal_uart.c可以看這個函數定義
   關於串口通信的其他接口函數都可以在 stm32f4xx_hal_uart.h文件里面找到聲明

在這里插入圖片描述

   在stm32f4xx_hal_uart.h里面的一些串口通信相關功能函數
在這里插入圖片描述

  • (2) 主函數
    由於我們CubeMX配置了串口, 所以主函數里面也自動添加了串口初始化函數
    在這里插入圖片描述

    • 下面添加測試printf的代碼
      在這里插入圖片描述
/* USER CODE BEGIN 3 */
// 在while(1)里面循環掃描, 判斷讀取的按鍵引腳狀態
// 判斷 WK_UP 按鍵是否按下  
if (HAL_GPIO_ReadPin(WKUP_GPIO_Port, WKUP_Pin) == GPIO_PIN_SET)
{
    HAL_Delay(10);	// 延時10ms, 做一個軟件的消抖, 防止因抖動而檢測到按鍵按下
    if (HAL_GPIO_ReadPin(WKUP_GPIO_Port, WKUP_Pin) == GPIO_PIN_SET)         // 如果確實按下了
    {
        while(HAL_GPIO_ReadPin(WKUP_GPIO_Port, WKUP_Pin) == GPIO_PIN_SET);	// 松手檢測, 即當這個按鍵松開后才進行下面的程序, 下同
        printf("key WK_UP was pressed \r\n");
    }
}

// 判斷 KEY0 按鍵是否按下 
if (HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin) == GPIO_PIN_RESET)
{
    HAL_Delay(10);	// 延時10ms, 軟件消抖
    if (HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin) == GPIO_PIN_RESET)
    {
        while(HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin) == GPIO_PIN_RESET);
        printf("key KEY0 was pressed \r\n");
    }
}
  /* USER CODE END 3 */
  • (3) 編譯下載
    在這里插入圖片描述

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

改錯

在主函數里面包含一個標准庫即可
#include "stdio.h"  

在這里插入圖片描述
注 : 養成習慣, 代碼寫在規范的位置

因為 printf是C語言標准庫里面的函數, 所以我們要使用就最好加上這個, 當然不加也沒事, 主要是加上比較完美

0 error(s) , 0 warning(s)

在這里插入圖片描述

  • (4) 實際效果展示
    在這里插入圖片描述

3.3 中斷方式串口通信

操作簡介 : 通過中斷方式傳輸指定長度的數據


Step1 : CubeMX配置

與3.1的輪詢方式配置幾乎都是一樣的, 只需要在串口的配置里面勾選使能串口中斷即可
先退出IAR或者Keil, 然后更改配置再重新Generate Code

在這里插入圖片描述

Step2 : IAR或Keil編程

(1) 在main函數外面先增加兩個數組用作數據緩沖區

在這里插入圖片描述

/* USER CODE BEGIN PV */
uint8_t TX_Buffer[] = "\n********** 中斷方式串口通信 *********\n輸入十個字符 (注:一個漢字為兩個字符大小)\n";
uint8_t Rx_Buffer[20]; //接收數據20個字符

/* USER CODE END PV */
(2) main函數里面

添加個人代碼, 以及通過中斷將 TX_Buffer[]里面的數據發送到串口調試助手

並在while(1) 里面不斷等待接收數據

在這里插入圖片描述

while(1) 外面的是我們通過單片機打印到串口的, while(1)里面接收中斷發送的數據並顯示

/* USER CODE BEGIN 2 */
	printf("串口通信正常...\n\n");
	printf("****** Kevin_8_Lee 2020-1-2  ********\n");
	printf("        *****         *****         *\n");
	printf("      *********     *********       *\n");
	printf("    ************* *************     *\n");
	printf("   *****************************    *\n");
	printf("   *****************************    *\n");
	printf("   *****************************    *\n");
	printf("    ***************************     *\n");
	printf("      ***********************       *\n");
	printf("        *******************         *\n");
	printf("          ***************           *\n");
	printf("            ***********             *\n");
	printf("              *******               *\n");
	printf("                ***                 *\n");
	printf("                 *                  *\n");
	printf("*************************************\n");
	HAL_Delay(500); // 延時500ms, 等待下一步操作  
	
	/* 通過中斷發送指定長度數據 */
	HAL_UART_Transmit_IT(&huart1, (uint8_t *)TX_Buffer, sizeof(TX_Buffer));

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    HAL_UART_Receive_IT(&huart1, (uint8_t *)Rx_Buffer, 10);
			
  }
  /* USER CODE END 3 */
(3) 再回到main函數外面

在main函數外面添加中斷回調函數

在這里插入圖片描述

/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    /* Prevent unused argument(s) compilation warning */
    UNUSED(huart);
    printf("\n您發送的消息為: ");		// 提示你所發送的信息
    HAL_UART_Transmit(&huart1, (uint8_t *)Rx_Buffer, 10,0xFFFF);
}

/* USER CODE END 4 */

中斷回調函數把串口調試助手發送的數據再發送給串口調試助手, 然后顯示出來

(4) 編譯下載, 看一下實際效果

在這里插入圖片描述

關於上述所用到的函數, 大家可以Go to definition去看一下這個函數的定義, 不懂得英文直接谷歌翻譯, 問題不大

最后, 常見問題解決辦法

  • 1、串口調試助手打印不是一個心形, 而是顯示的比較亂
    • 解決辦法: 這個可能是由於不同的串口調試助手數據顯示的方法不同導致的, 如果你用的是原子的XCOM, 那就把以上所有 \n 這個換行符換為 \r\n 我會在下面把我的串口調試助手分享出來, 可以網盤下載使用
    • 本篇博客中用的串口調試助手(2020年2月2號更新,將調試助手程序修改完善了一部分)

鏈接:https://pan.baidu.com/s/1DN60ojns3Wu88frJ5pqSzA
提取碼:6exl
復制這段內容后打開百度網盤手機App,操作更方便哦

  • 2、上位機發送的字符並未顯示出來
    • 解決辦法: 這個有可能是由於你沒有發夠十個字符, 沒有觸發發送功能. 指定長度傳輸數據時, 你的函數里面設定的幾個字符就一定要發夠幾個字符, 否則發不出來, 發的多了只會顯示一部分, 但是發的少了可能不顯示

如果自己試驗的時候出現什么問題可以在博客下面評論或者私信我, 知無不言。


最怕一生碌碌無為, 還說平凡難能可貴! 加油吧
Author : 李光輝
date : Thu Jan 2 20:41:56 CST 2020
blog ID: Kevin_8_Lee
blog site : https://blog.csdn.net/Kevin_8_Lee


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM