天天看點

stm32f407 6路序列槽dma如何配置_單片機序列槽共性問題序列槽分類(序列槽是啥)啥是UART?啥是USART?程式設計政策查詢發送/中斷接收模式:收發中斷模式DMA 模式

以下文章來源于嵌入式客棧 ,作者逸珺。

部分修改,

stm32f407 6路序列槽dma如何配置_單片機序列槽共性問題序列槽分類(序列槽是啥)啥是UART?啥是USART?程式設計政策查詢發送/中斷接收模式:收發中斷模式DMA 模式

序列槽分類(序列槽是啥)

通用異步收發器(UART)是用于異步串行通信的一種實體層标準,其中資料格式和傳輸速度是可配置的。 通用同步收發器(USART)是一種串行接口裝置,可以對其進行程式設計以進行異步或 同步通信。

stm32f407 6路序列槽dma如何配置_單片機序列槽共性問題序列槽分類(序列槽是啥)啥是UART?啥是USART?程式設計政策查詢發送/中斷接收模式:收發中斷模式DMA 模式

資料格式

線上空閑、無資料狀态為常高電平,故邏輯低定義為起始位。

  • 起始位:總是 1 位
  • 資料位:常見的有 8 位或 9 位。
  • 校驗位
    • 奇校驗
    • 偶校驗
    • 無校驗
  • 停止位:
    • 1 位
    • 2 位
  • 波特率:bit rate 就是位/秒的概念,就是 1 秒傳送多少位的概念。

常見的波特率有哪些呢?如下圖:

stm32f407 6路序列槽dma如何配置_單片機序列槽共性問題序列槽分類(序列槽是啥)啥是UART?啥是USART?程式設計政策查詢發送/中斷接收模式:收發中斷模式DMA 模式

注意:

應用電路設計的時候 RX-TX 相信,很多初學者容易在這裡踩坑!常見的傳輸位序為低有效位在前。對于波特率而言需要注意波特率發生器有可能帶來誤碼問題

一個有效位元組的傳輸時間算法

stm32f407 6路序列槽dma如何配置_單片機序列槽共性問題序列槽分類(序列槽是啥)啥是UART?啥是USART?程式設計政策查詢發送/中斷接收模式:收發中斷模式DMA 模式

計算公式

比如 9600 下,1 位起始位,8 位資料位,奇校驗,1 位停止位,則

stm32f407 6路序列槽dma如何配置_單片機序列槽共性問題序列槽分類(序列槽是啥)啥是UART?啥是USART?程式設計政策查詢發送/中斷接收模式:收發中斷模式DMA 模式

校驗位有用嗎?

當你的傳輸媒體處于一個有幹擾的場景下,校驗位就可以從實體層檢測出錯誤。

了解資料編碼方式有啥意義呢?

比如在調試中你可以利用邏輯分析直接去解析收發線上的資料封包。

啥是UART?啥是USART?

stm32f407 6路序列槽dma如何配置_單片機序列槽共性問題序列槽分類(序列槽是啥)啥是UART?啥是USART?程式設計政策查詢發送/中斷接收模式:收發中斷模式DMA 模式

UART

兩邊分别代表兩個通信的裝置,單從 UART 程式設計的角度講收發不需要實體同步握手,想發就發。圖中箭頭代表資料資訊流向。RX 表示接收資料,TX 表示發送資料。資料總是從發送端傳遞到接收端,這就是為啥 RX 連接配接 TX,TX 連 RX 的原因。

stm32f407 6路序列槽dma如何配置_單片機序列槽共性問題序列槽分類(序列槽是啥)啥是UART?啥是USART?程式設計政策查詢發送/中斷接收模式:收發中斷模式DMA 模式

同步簡單說,收發不可自如,不可以想發就發,收發需要利用硬體 IO 口進行握手,RTS/CTS 就是用于同步的握手信号:

  • RTS:Ready to send,請求發送,用于在目前傳輸結束時阻止資料發送。
  • CTS:clear to send,清除發送,用于訓示 USART 已準備好接收資料。

這個對于普通應用而言并不常見,這裡不做詳細展開,需要用到的時候隻需要對應收發時控制握手信号即可。

程式設計政策

對于不同的單片機,其硬體體系各異,寄存器也差異很大,但是從收發程式設計政策角度而言,常見有下面三種方式:

  • 查詢發送/中斷接收模式
  • 收發中斷模式
  • DMA 模式

查詢發送/中斷接收模式:

這裡以僞代碼方式描述一下:

/*查詢發送位元組*/void uart_send_byte( uint8 ch ){    /*如果目前序列槽狀态寄存器非空閑,則一直等待*/    /*注意while循環後的分号,表示循環體為空操作*/    while( !UART_IS_IDLE() );    /*此時将發送位元組寫入發送寄存器*/    UART_TX_REG = ch;}/*發送一個緩沖區*/void uart_send_buffer( uint8 *pBuf,uint8 size ){    uint8 i = 0;    /* 異常參數處理*/    if( pBuf == NULL )        return;    for( i=0; i
           

對于接收而言,如采用查詢模式則幾乎是沒有任何應用價值,因為外部資料不知道什麼時候會到來,是以查詢接收就不描述了,這裡描述一下中斷接收。

static uint8 rx_index = 0;void uart_rx_isr( void ){    /* 接收封包處理 */    rx_buffer[rx_index++] = UART_RX_REG;}
           

中斷接收需要考慮的幾個要點:

  • 斷幀:這就取決于協定怎麼制定了,比如應用協定定義的是 ASCII 碼方式,就可以定義同步頭、同步尾,比如 AT 指令的解析,做邏輯判斷幀頭、幀尾即可。但是如果傳輸的是 16 進制資料,比如 MODBUS-RTU 其斷幀采用的是 3.5 個位元組時間沒有新的位元組接收到,則認為收到完整的幀了。
  • 如何保證幀的完整性,一般會在封包尾部加校驗,比較常用的校驗模式有 CRC 校驗算法。
  • 不同的單片機開發環境對于中斷向量的處理方式略有不同,需要根據各自晶片的特點進行處理。比如 51 單片機,其發送/接收都共享一個中斷向量号。

收發中斷模式

#define FRAME_SIZE  (128u)static uint8 tx_buffer[FRAME_SIZE];static uint8 tx_index  = 0;static uint8 tx_length = 0;static uint8 rx_buffer[FRAME_SIZE];static uint8 rx_index = 0;static bool  rx_frame_done = false;void prepare_frame( uint8 * pBuf, uint8 size ){     /*将待傳的封包按照協定封裝*/     /*可能需要處理的事情,比如幀頭、幀尾、校驗等*/}bool uart_start_sending( uint8 * pBuf, uint8 size ){    if( pBuf == NULL )        return false;     memcpy( tx_buffer,pBuf,size );     tx_index  = 0;     tx_length = size;     /*使能發送中斷,向發送寄存器寫入一個位元組,進入連續發送模式*/     ENABLE_TX_INT = 1;     UART_TX_REG   = tx_buffer[tx_index++];}void uart_tx_isr( void ){    if( tx_index
           

還需要考慮的是,對于 UART 硬體層面的出錯處置,以 STM32 為例,就可能有下面的錯誤可能發生:

  • 溢出錯誤
  • 噪聲檢測
  • 幀錯誤
  • 奇偶校驗錯誤

另外不同的單片機其底層硬體實作差異也不較大,比如有的硬體發送緩沖是單位元組的緩沖,有的則具有 FIFO,這些在選型程式設計時都需要綜合考慮。

DMA 模式

DMA 發送模式而言,大緻分這樣幾步:

  • 初始化 UART 為 DMA 發送模式,開啟 DMA 結束中斷,并寫好 DMA 傳輸結束中斷處理函數
  • 準備待發送封包,幀頭、幀尾、校驗處理
  • 将待發送封包緩沖區首位址指派給 DMA 源位址,DMA 目标位址設定為 UART 發送寄存器,設定好發送長度。
  • 啟動 DMA 傳輸,剩下傳輸完成就會進入傳輸結束中斷處理函數。

DMA 接收模式而言,大緻分這樣幾步:

  • 初始化 UART 為 DMA 接收模式,開啟 DMA 結束中斷,并寫好 DMA 傳輸結束中斷處理函數
  • 中斷處理函數中标記接收到幀,對于使用 RTOS 而言,還可以使用的機制是利用 RTOS 的事件機制、消息機制進行通知有新的幀接收到了。
  • 對于 DMA 接收模式而言,對于變長幀的處理較為不利,是以如果想使用 DMA 接收,制定協定時盡量考慮将幀長度固定,這樣處理會友善些。