STM32串口通信學習總結

                                                                         STM32串口通信學習總結

1.概述

1.1學習目的

通過基於AWA5812平臺,學習STM32F767芯片的串口通信程序開發。本人學習串口通信比較曲折,一開始使用的芯片時STM32新開發出來的一塊STM32L496ZG的板子,這塊板子的優點時低功耗,性能在M4系列中也比較強大,滿足了公司對現有產品升級的需求,而對於我這個新入手不到一個月的職場小白來說,這塊板子時相對的不友好了,所先從資料來說除了其芯片手冊,參考手冊,數據手冊,STM32官網包括論壇就幾乎沒有其他資料,而且全是英文,曾看到論壇的人在喊說大家一起來翻譯中文版吧,一人一段,看似很令人興奮的事,可這也說明現在是別想指望由中文版的了,所以只有硬着頭皮上吧;其次STM32官方給的例程在板子上沒跑通,這就奇了怪了,例程能錯嘛?堅持了2周我果斷實現了從入門到放棄的過程。可工作要求實在沒辦法,煎熬了一週,果斷向正點原子爸爸靠攏,花了千元買了塊阿波羅F767開發板,毫無疑問,正點原子爸爸給視頻給例程還給中文參考手冊,手把手教你編程,百度以下所遇到的問題,只應證了一點,你經歷的別人都經歷過。好的話不多說,來講講我的STM32串口通信的學習歷程吧。

1.2.學習過程

接下來我將從以下幾個方面介紹我學習過程

1、物理層

2、通用同步異步收發器

3、STM32串口通信過程

4、串口配置的一般步驟及代碼分析

5、問題總結

1.3參考文檔

《STM32F767xx數據手冊》

《STM32F4開發指南 v1.1 HAL庫版本》

《RM0385參考手冊》

  1. 物理層

2.1通訊標準說明

串口通訊(Serial Communication)是一種設備間非常常用的串行通訊方式,因爲它簡單便捷,大部分電子設備都支持該通訊方式,我們在調試設備時也經常使用該通訊方式輸出調試信息。

串口通信的物理層主要在兩設備間,主要用的標準是RS-232標準,它規定了信號的用途、通訊接口及信號的電平水平。

2.2 DB9接口中的公頭及母頭的各引腳示意圖

2.3 ST-Link/v2接口說明

2.3.1 LED狀態說明:

閃爍紅色:ST-LINK/V2連接到計算機後,第一次USB枚舉過程

紅色:ST-LINK/V2與計算機已建立連接

閃爍綠色/紅色:目標板和計算機在進行數據交換

綠色:通訊完成

橙色(紅色+綠色):通訊失敗

2.3.2 STM8接口定義

仿真端口

連接目標板

功能

1、VDD

MCU VCC

連接STM8目標板的電源VCC

2、DATA

MCU SWIM

連接STM8目標板的SWIM PIN

3、GND

GND

連接STM8目標板的電源GND

4、RESET

MCU RESET PIN

連接STM8目標板的RESET PIN

排列示意圖如下

2.3.3 STM32接口定義

仿真器端口

連接目標板

功能

1. TVCC

MCU電源VCC

連接STM32目標板的電源VCC

2. TVCC

MCU電源VCC

連接STM32目標板的電源VCC

3. TRST

GND

GROUND

4. UART-RX

GND

GROUND

5. TDI

TDI

連接STM32的JTAG TDI

6. UART-TX

GND

GROUND

7. TMS, SWIO

TMS, SWIO

連接STM32的JTAG的TMS, SWD的SW IO

8. BOOT0

GND

GROUND

9. TCK, SWCLK

TCK, SWCLK

連接STM32的JTAG的TCK, SWD的SW CLK

10. SWIM

GND

GROUND

11. NC

NC

Unused

12. GND

GND

GROUND

13. TDO

TDO

連接STM32的JTAG TDO

14. SWIM-RST

GND

GROUND

15. STM32-RESET

RESET

連接STM32目標板的RESET端口

16. KEY

NC

GROUND

17. NC

NC

Unused

18. GND

GND

GROUND

19. VDD

NC

VDD (3.3V)

20. GND

GND

GROUN

排列示意圖

  1. 通用同步異步收發器

通用同步異步收發器是一個串行通信設備,可以靈活的與外部設備進行全雙工數據交換。有別與USART,還有一個UART,它在USART基礎上裁剪掉了同步通信功能,只有異步通信。簡單區分同步和異步就是看通信時需不需要對外提供時鐘輸出,我們平時用的串口通信基本都是 UART因此在不考慮同步通信時,USART與UART沒有太大差別
串口通信一般是以幀格式傳輸數據,即一幀一幀傳輸,每幀包含有起始信號、數據信息、停止信息,可能還有校驗信息。
USART滿足外部設備對工業標準 NRZ 異步串行數據格式的要求,並且使用了小數波特率發生器,可以提供多種波特率,使得它的應用更加廣泛。USART 支持同步單向通信和半雙工單線通信;還支持局域互連網絡 LIN、智能卡(SmartCard)協議與 lrDA(紅外線數據協會) SIR ENDEC規範。
USART支持使用 DMA,可實現高速數據通信。

以下時USART的框圖:

注:fCK 可以是 fLSE、fHSI、fPCLK、fSYS.

 

由框圖我將其分爲四部分來學習:

  • 功能引腳
  • 寄存器
  • 控制器
  • 波特率生成

3.1 功能引腳

引腳

功能

TX

發送數據輸出引腳。

RX

接收數據輸出引腳

nRTS

請求以發送,n表示低電平有效。如果使能 RTS 流控制,當USART接收器準備好接收新數據時就會將nRTS變成低電平;當接收寄存器已滿時,nRTS將被設置爲高電平。該引腳只適用於硬件流控制。

nCTS

清除以發送(Clear To Send),n表示低電平有效。如果使能 CTS流控制,發送器在發送下一幀數據之前會檢測 nCTS 引腳,如果爲低電平,表示可以發送數據,如果爲高電平則在發送完當前數據幀之後停止發送。該引腳只適用於硬件流控制

SCLK

發送器時鐘輸出引腳。這個引腳僅適用於同步模式。

3.2數據寄存器

USART說數據寄存器(USART_DR)只有低 9 位有效,並且第 9 位數據是否有效要取決於USART 控制寄存器 1(USART_CR1)的 M 位設置,當 M 位爲 0 時表示 8 位數據字長,當 M位爲 1 表示 9 位數據字長,我們一般使用 8位數據字長。
USART_DR包含了已發送的數據或者接收到的數據。USART_DR實際是包含了兩個寄存器,一個專門用於發送的可寫 TDR,一個專門用於接收的可讀 RDR。當進行發送操作時,往 USART_DR寫入數據會自動存儲在 TDR內;當進行讀取操作時,向 USART_DR讀取數據會自動提取 RDR 數據。
TDR和RDR都是介於系統總線和移位寄存器之間。串行通信是一個位一個位傳輸的,發送時把 TDR 內容轉移到發送移位寄存器,然後把移位寄存器數據每一位發送出去,接時把接收到的每一位順序保存在接收移位寄存器內然後才轉移到 RDR。
USART 支持 DMA 傳輸,可以實現高速數據傳輸。

3.3 控制器

USART有專門控制發送的發送器、控制接收的接收器,還有喚醒單元、中斷控制等。
使用USART之前需要向USART_CR1寄存器的UE位置1使能USART,UE位用於開啓供給串口的時鐘。發送或者接收數據字長可選8或9位,由USARTT_CR1的M位控制。

3.3.1發送器

當USART_CR1寄存器的發送使能位TE置1時,啓動數據發送,發送移位寄存器的數據會在TX引腳輸出,低位在前,高位在後。如果是同步模式SCLK也輸出時鐘信號。
一個字符幀發送需要3部分:起始位、數據幀、停止位。起始位是一個位週期的低電平,位週期就是每一位佔用的時間;數據幀就是我們要發送的7或8或9位數據,數據是最低位開始傳輸的;停止位是一定時間週期的高電平。
停止位的時間長短可以通過USART控制寄存器2(USART_CR2)的STOP[1:0]位控制,可選0.5個、1個、1.5個、2個停止位。默認使用1個停止位。2個停止位適用於正常USART模式、單線模式和調制解調器模式。0.5和1.5個停止位用於智能卡模式。
當發使能位TE置1之後,發送器開始會發送一個空閒幀(一個數據幀長度的高電平),接下來就可以往USART_DR寄存器寫入要發送的數據。在寫入最後一個數據後,需等待USART狀態寄存器(USART_SR)的TC位爲1,表示數據傳輸完成。USART_CR1寄存器的TCIE位置1,則產生中斷。
發送數據時,幾個重要的標誌位如下:
TE:發送使能。
TXE:發送寄存器爲空,發送單個字節時使用。
TC:發送完成,發送多個字節數據時候使用。
TXIE:發送完成中斷使能。


3.3.2 接收器
將CR1寄存器的RE位置1,使能USART接收,使得接收器在RX線開始搜索起始位。在確定起始位後,就根據RX線電平狀態把數據存放在接收移位寄存器內。接收完成後就把接收移位寄存器的數據移到PDR內,並把USART_SR寄存器的RXNE位置。如果USART_CR2寄存器的RXNEIE置1可以產生中斷。
接收數據時,幾個重要的標誌位如下:
RE: 接收使能。
RXNE:讀數據寄存器非空。
RXNEIE:發送完成中斷使能。

 

3.4 波特率生產

 

接收器和發送器(Rx和Tx)的波特率設置爲USARTx_BRR寄存器中編程的相同值。

公式1;適用於標準USART(包括SPI模式)的波特率(OVER8=0或1)

16倍過採樣時的公式爲;

8倍過採樣時的公式爲:

如何從USARTx_BRR寄存器中獲取USARTDIV呢?

如本次實驗的要通過獲取115200波特率。

16倍過採樣時:

USARTDIV=8000000/115200

BRR=USARTDIV=69d=0x45

16倍過採樣時:

USARTDIV=2*8000000/115200

USARTDIV=138.89(139d=8Bh)

BRR[3:0]=Bh>>1=1h

BRR=0x8B

 

3.5 總結

UART異步通信方式特點:

  1. 全雙工異步通信
  2. 小數波特率發送器系統,提供精準的波特率
  3. 可配置的16倍過採樣或8倍過採樣,因此爲速度容差與時間容差的靈靈活配置提供了可能
  4. 可編碼的數據字長度(8位或者9位)
  5. 可配置的停止位(支持1或者2位停止位)
  6. 可配置的適用DMA多緩存器通信
  7. 單獨的發送器和接收器使能位
  8. 檢測標誌:1.接收緩存器2.發送緩衝器3.傳輸結束標誌
  9. 多個帶標誌的中斷源,觸發中斷。
  10. 其他:校驗控制,四個錯誤檢測標誌

4、STM32串口通信過程

 

USAT異步通信方式引腳(STM32F767IGT6)

串口號

USART_RX

USART_TX

USART1

PA10(PB7)

PA9(PB6)

USART2

PA3(PD6)

PA2(PD5)

USART3

PB11(PC11)(PD9)

PB10(PC10)(PD8)

UART4

PA1(PC11)

PA0(PC10)

UART5

PD2

PC12

USART6

PC7(PG9)

PC6(PG14)

5、串口配置的一般步驟及代碼分析

步驟

使用代碼

  • 串口時鐘使能

RCC_APBxPeriphClockCmd();

GPIO時鐘使能

RCC_AHB1PeriphClockCmd();

  • 引腳復位映射

GPIO_PinAFConfig();

  • GPIO端口模式設置

GPIO_Init();模式設置爲GPIO_MoDe_AF

  • 串口參數初始化

USART_Init();

  • 開啓中斷並初始化NVIC

NVIC_Init();

 

USART_ITConfig();

  • 使能串口

USART_Cmd;

  • 編寫中斷處理函數

USARTx_IRQHandler();

  • 串口數據收發

Void USART SentDate();//發送數據到串口

 

Uint16_t USART_ReceiveDate();//接收數據

  • 串口傳輸狀態獲取

FlagStatus USART_GetFlagStatus();

 

Void USART_ClearITPendingBit();

 

5.1代碼分析

5.1.1 USART初始化結構體

初始化結構體的定義在stm32f7xx_hal_uart.h中,初始化庫函數定義在stm32f7xx_hal_uart.c中。

  1. Instance:串口選擇
  2. USART_BaudRate:波特率設置。標準庫函數會根據設定值計算得到USARTDIV值,從而設置USART_BRR的寄存器值,我們通常設置爲115200。
  3. USART_WordLength:.數據幀字長,它設定USART_CR1寄存器M位的值。如果沒有使能奇偶位校驗控制,一般使用8數據位。
  4. USART_StopBits停止位設置。停止位有1、1.5、2三種,通常有一個停止位
  5. USART_Parity:奇偶校驗控制選擇。通常選擇無奇偶校驗。
  6. USART_Mode:USART模式選擇有USART_Mode_Rx和USART_Mode_Tx,允許使用邏輯或運算選擇兩個,它設定 USART_CR1寄存器的 RE 位和 TE位。所以通常設置爲收發模式
  7. USART_HardwareFlowControl:硬件流控制選擇,只有在硬件流控制模式下才有效,可選有,使能RTS、使能CTS、同時使能RTS和CTS、不使用硬件流。
  8. HAL_UART_Init:初始化設置並使能USART6後調用HAL_UART_MspInit()函數。
  9. HAL_USART_Receive:該函數會開啓接收中斷,標誌位UART_IT_RXNE,並且設置接收緩衝以及接收緩衝接收最大數據量

5.1.2 UART底層初始化,時鐘使能,引腳配置,中斷配置

HAL_UART_MspInit()函數會被HAL_UART_Init()函數調用,在stm32f7xx_hal_uart.c中可看見一個__weak void HAL_UART_MspInit(UART_HandleTypeDef *huart)函數,weak即爲弱定義,如果其他地方定義了,則執行定義的,不會出現重定義錯誤,如果其他地方未定義,只有這個弱定義,則執行此弱定義。

  • GPIO_InitTypeDef  GPIO_Initure:句柄定義
  • If條件語句:判斷是否時串口x,此處可以將6個串口的GPIO配置都寫入,自建庫,以後就可直接調用
  • _HAL_RCC_GPIOC_CLK_ENABLE():使能GPIOC時鐘
  • __HAL_RCC_USART6_CLK_ENABLE():使能USART6時鐘
  • GPIO_Initure:GPIO初始化配置,包括工作模式、輸出模式、輸出速度、複用功能
  • HAL_GPIO_Init:初始化GPIO結構體
  • HAL_NVIC_EnableIRQ:使能USART6中斷通道
  • HAL_NVIC_SetPriority:設置中斷優先級,搶佔優先級3,子優先級3

5.1.3 接收器

HAL_UART_RxCpltCallback(huart)函數在使用時,就調用HAL_UART_RxCpltCallback函數進行數據的接收。數據從串口接收端接收,並在使能情況下,自動寫入接收數據寄存器。在定義中已定義USART_RX_STA標誌位,bit15位爲接收完成標誌,即接收到0x0a,bit14位爲接收到0x0d,bit13~bit0位接收到的有效字節數目,因此,本代碼主要判斷數據結尾是否到0x0d0a.

5.1.4中斷服務程序

本中斷服務程序主要處理超時處理

5.1.5 發送器

發送器位於主循環中,主要是判斷已接收到標誌位0x0a0d後,將接收寄存器的值賦給發送寄存器,而發送寄存器向串口發送數據。

4.1.6 實驗結果

6、問題總結

6.1 調試中遇到的問題

1.無論PC發什麼,stm32都沒有迴應?

調試過程:把初始化的程序與網上衆多程序員寫的初始化程序做了比較,沒有發現不一樣的地方。覺得可能是是程序的問題,因此dubug了一下,發現在我設置的接收數組中,是有值寫入的,也就是接收寄存器能夠接收到PC端發送的值,按程序的運行,接下來應該是將接收數組賦值給發送寄存器,可問題就在於發送寄存器中沒有收到賦值。檢查程序後發現賦值處是有問題的,於是進行修改

  1. 無論PC端發送什麼都亂碼?

調試過程:在確定了軟件上能過接收到PC端發來的信號,並且能發送出去的前提下,

PC窗口卻出現亂碼現象,判斷軟件上是沒有問題的,於是用示波器去測量硬件數據,發現PC接收端與STM32F767芯片之間的一塊控壓芯片存在虛焊。發現問題不要一味認爲是軟件問題,需要軟硬件兼顧的區考慮。

3.stm32發回來的內容與PC發送的不一致?

調試過程:用示波器觀測數據,發現收發的數據都是正確的,但電平寬度不一致,由此得知兩者的波特率不一致,進一步計算得知是stm32的串口波特率不對,後發現程序默認時鐘用的MSI內部時鐘,而波特率固定的四個時鐘中沒有MSI,因此修改使用外部高速時鐘HSE,其時鐘頻率爲8MHz。

需說明的是,配置時鐘需要了解時鐘樹如何區配置,建議利用STM32CubeMX來學習,如果不會編寫其時鐘代碼,可用其生成程序。