USART—串口通訊


本章中主要講解的是串口異步通訊,異步通訊中由於沒有時鍾信號, 所以兩個通訊設備之間需要約定好波特率,即每個碼元的長度,以便對信號進行解碼 。

串口通訊的一個數據包從起始信號開始,直到停止信號結束。數據包的起始信號由一
個邏輯 0 的數據位表示,而數據包的停止信號可由 0.511.5 2 個邏輯 1 的數據位表示,
只要雙方約定一致即可。

STM32 芯片具有多個 USART 外設用於串口通訊,它是 Universal Synchronous
Asynchronous Receiver and Transmitter 的縮寫,即通用同步異步收發器可以靈活地與外部設
備進行全雙工數據交換。有別於 USART,它還有具有 UART 外設(Universal Asynchronous
Receiver and Transmitter),它是在 USART 基礎上裁剪掉了同步通信功能,只有異步通信。
簡單區分同步和異步就是看通信時需不需要對外提供時鍾輸出,我們平時用的串口通信基
本都是 UART

STM32 USART 輸出的是 TTL 電平信號,若需要 RS-232 標准的信號可使用
MAX3232 芯片進行轉換。

①功能引腳
TX:發送數據輸出引腳。
RX:接收數據輸入引腳。
SW_RX:數據接收引腳,只用於單線和智能卡模式,屬於內部引腳,沒有具體外部引
腳。
nRTS:請求以發送(Request To Send)n 表示低電平有效。如果使能 RTS 流控制,當
USART 接收器准備好接收新數據時就會將 nRTS 變成低電平;當接收寄存器已滿時,
nRTS 將被設置為高電平。該引腳只適用於硬件流控制。

nCTS:清除以發送(Clear To Send)n 表示低電平有效。如果使能 CTS 流控制,發送
器在發送下一幀數據之前會檢測 nCTS 引腳,如果為低電平,表示可以發送數據,如果為
高電平則在發送完當前數據幀之后停止發送。該引腳只適用於硬件流控制。
SCLK:發送器時鍾輸出引腳。這個引腳僅適用於同步模式。
USART 引腳在 STM32F429IGT6 芯片具體發布見表 20-3

 

應用型編程,先會使用,有需要再去解析內部實現:

int main(void)
{    
  /*初始化USART 配置模式為 115200 8-N-1,中斷接收*/
  Debug_USART_Config();
    
    /* 發送一個字符串 */
    Usart_SendString( DEBUG_USART,"這是一個串口中斷接收回顯實驗\n");
    printf("這是一個串口中斷接收回顯實驗\n");
    
  while(1)
    {    
        
    }    
}

 

void Debug_USART_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  USART_InitTypeDef USART_InitStructure;
        
  RCC_AHB1PeriphClockCmd(DEBUG_USART_RX_GPIO_CLK|DEBUG_USART_TX_GPIO_CLK,ENABLE);

  /* 使能 USART 時鍾 */
  RCC_APB2PeriphClockCmd(DEBUG_USART_CLK, ENABLE);
  
  /* GPIO初始化 */
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;  
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  
  /* 配置Tx引腳為復用功能  */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_PIN  ;  
  GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);

  /* 配置Rx引腳為復用功能 */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_PIN;
  GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
  
 /* 連接 PXx 到 USARTx_Tx*/
  GPIO_PinAFConfig(DEBUG_USART_RX_GPIO_PORT,DEBUG_USART_RX_SOURCE,DEBUG_USART_RX_AF);

  /*  連接 PXx 到 USARTx__Rx*/
  GPIO_PinAFConfig(DEBUG_USART_TX_GPIO_PORT,DEBUG_USART_TX_SOURCE,DEBUG_USART_TX_AF);
  
  /* 配置串DEBUG_USART 模式 */
  /* 波特率設置:DEBUG_USART_BAUDRATE */
  USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
  /* 字長(數據位+校驗位):8 */
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  /* 停止位:1個停止位 */
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  /* 校驗位選擇:不使用校驗 */
  USART_InitStructure.USART_Parity = USART_Parity_No;
  /* 硬件流控制:不使用硬件流 */
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  /* USART模式控制:同時使能接收和發送 */
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  /* 完成USART初始化配置 */
  USART_Init(DEBUG_USART, &USART_InitStructure); 
    
  /* 嵌套向量中斷控制器NVIC配置 */
    NVIC_Configuration();
  
    /* 使能串口接收中斷 */
    USART_ITConfig(DEBUG_USART, USART_IT_RXNE, ENABLE);
    
  /* 使能串口 */
  USART_Cmd(DEBUG_USART, ENABLE);
}

從上面的紅色部分我們可以知道,和往常一樣,開啟時鍾是第一步,尤其注意的是引腳復用調用的函數,注意是GPIO_Pinsource而不是GPIO_Pin.

在編寫程序的時候,首先參考官方固件庫,然后謹記編程要點,比如什么時鍾應該開啟,引腳功能如何配置,是否有復用模式,中斷是否需要配置。這需要我們熟悉外設掛載在哪個總線上,已及總線的最高時鍾,這些都知道以后,固件庫編程是很快速的。至於固件庫的具體實現,也是很有參考價值的,但是如果你手上還有很多需要學習的東西,可以暫時不管固件庫底層如何實現,先完成基本設計,再慢慢深入。這是一個長期累積的過程。

 串口調試助手,不勾選發送模式,默認是以字符的方式發送。

編程時需要用到的固件庫函數

要使用printf重定向,需要重寫fputc函數,並且在keil中勾選使用微庫。

 NOTE:

STM32默認就是小端模式:

The processor can access data words in memory in little-endian format or big-endian 
format. It always accesses code in little-endian format.
Note:
Little-endian is the default memory format for ARM processors.

 在發送一個字節8位模式時,是從高位開始向低位傳輸的:

但是,要是我們想要發送一個16位的數據,是先發送高8位呢還是低8位?通過參考歷程可以看出,是先發送的高8位,再發送低8位。

那么為什么要先發送高8位再發送底八位呢?

例如一個16位數據0x1234;在寄存器中是高位在前,低位在后的(stm32默認小端模式)。

二進制 0001  0010   0011   0100;

要想把這一串二進制以8位一次的方式發送,如果我們先發送低8位,再發送高8位,最后出來將會是0x3412,所以,我們應該先發送高位再發送低位。

重要寄存器,解釋為什么發送接收庫函數要那么去寫:

//接收庫函數

//發送庫函數

首先,這是中斷服務函數調用的,首先調用接收函數,能進接收中斷,所以肯定有數據發來單片機接收到了,此時把DR寄存器的值得低9位(在我們的歷程中使用的8位,到底是9位還是8位要看M的設置),這個值返回出來,確實應該是接收函數。但是,為什么像DR中寫入數據,就是發送了?剛開始我也不理解,但是參看參考手冊之后,發現,寫數據倒DR寄存器中會硬件觸發標志,這樣,內核可以知道你是接收還是發送。

發送端:

7. USART_DR 寄存器中寫入要發送的數據(該操作將清零 TXE 位)。為每個要在單緩
沖區模式下發送的數據重復這一步驟。
8. USART_DR 寄存器寫入最后一個數據后,等待至 TC=1。這表明最后一個幀的傳送已
完成。禁止 USART 或進入暫停模式時需要此步驟,以避免損壞最后一次發送

接收端:

 

 這樣,讀DR寄存器,會產生一些硬件標志置位,所以內核可以知道是否接收完成,向DR寄存器寫數據,也會產生一些硬件標志位,這樣內核就知道是否發送發送完成。

嵌入式開發,離不開和芯片手冊折騰,但是這又是必備技能,而且這里STMF4還是中文參考手冊,更多時候,我們開發是英文手冊,更加困難,所以,軟件程序員,必須熟練運用英語和數學。


免責聲明!

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



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