容易被大多數人忽視的STM32串口DMA問題

討論三個問題:php

1、什麼叫串口DMA 請求;算法

2、串口簡要複習;函數

3、串口DMA發送流程。學習

 

第一spa

什麼叫串口DMA 請求(戰艦STM32開發板)調試

 

說這個問題以前先簡單回顧DMA的基本特性。先導出原子哥的PPT內容:內存

 

DMA 全稱Direct Memory Access,即直接存儲器訪問。開發

 

DMA傳輸將數據從一個地址空間複製到另外一個地址空間。當CPU初始化這個傳輸動做,傳輸動做自己是由DMA控制器來實現和完成的。產品

 

STM32有兩個DMA控制器(DMA2只存在於大容量產品中),DMA1有7個通道,DMA2有5個通道,每一個通道專門用來管理來自於一個或者多個外設對存儲器的訪問請求。還有一個仲裁器來協調各個DMA請求的優先權。it

 

做用:爲CPU減負!

 

下面上圖

 

 

從外設(TIMx、ADCx、SPIx、I2Cx、和USARTx)產生的DMA請求,經過邏輯或輸入到DMA控制器,這就意味着同時只能有一個請求有效(在同一時間,就只能使用其中的一個,其餘通道也相似)。外設的DMA請求,能夠經過設置相應的外設寄存器中的控制位,被獨立的開啓或關閉。

 

看到這裏串口DMA請求的定義就出來了:先舉個例子:譬如我想用串口發送數據到PC機,通常作法是CPU經過APB1/APB2總線往串口寫數據,而後串口發送;或者是CPU經過總線從串口取(讀)數據;若是此時CPU處理的任務很是多,這就會耗費CPU的處理時間。

 

而咱們若是用DMA來傳送數據那就很快了,DMA會經過本身的特定通道將數據從一個地址空間複製到另外一個地址空間,並且不須要CPU的干預。因此串口DMA請求的定義是:串口要發送/接收數據會請求DMA來完成數據的寫和讀。(注意這句話只針對本文!)

 

第二

串口簡要複習(庫函數)

 

這裏給你們分享個帖子關於printf重定向和半主機模式的理解:

http://www.openedv.com/forum.php?mod=viewthread&tid=44609&highlight=printf

 

這裏簡要複習一下戰艦STM32串口的知識點。嵌入式物聯網企鵝意義氣嗚嗚吧久零就易,舉個例子:我想用PC機往STM32串口發送個數據,而後STM32接收到後將數據原樣返回給PC機(顯示在串口調試助手中)。

 

思路:首先咱們會在串口初始化函數中配置串口接收中斷,當你PC機往串口發送數據時,串口會產生接收中斷;並在中斷服務函數中,判斷接沒接收完,若是接收完畢就會把接收狀態寄存器的接收完成標誌位置1。到這兒是接收中斷的做用。

 

而後在主函數中,咱們不斷檢測接收狀態寄存器的接收完成標誌,看接沒接收完。若是接收完了,就經過for循環將接收到的數據,所有發給串口的USART_DR寄存器(當向該寄存器寫數據時,串口就會自動發送)。因而咱們經過PC機發給串口的數據就會被STM32經過串口發回來了,顯示在串口調試助手中。

 

第三

串口DMA發送流程(庫函數)

 

戰艦實驗:經過按鍵KEY0來控制DMA發送,每按一次KEY0,DMA就傳送一次數據到USART1,而後在TFTLCD模塊上顯示進度信息。這個如今理解就不難了吧。

 

從主函數入手,首先咱們在STM32的SRAM中開闢一段5200(這個數字越大DMA傳輸越慢,反之越快)字節的空間SendBuff[],做爲咱們的存儲器(內存),存儲要往外設(USART1)發送的數據。

 

而後咱們在SendBuff[]中寫滿TEXT_TO_SEND[]裏的內容。這裏戰艦往SendBuff[]裏寫的算法很是巧妙,應該學習;

 

如今SendBuff[]中已經存滿了要發送給串口的數據。這時咱們還要檢測KEY0有沒有按下,若是按下了,就經過兩個函數:一、使能串口發送(在STM32庫函數stm32f10x_usart.c中,配置USART_CR3中的DMA使能位DMAT);二、使能DMA1通道4,啓動傳輸(在dam.c中,最後也是調用了stm32f10x_dma.c中的DMA_Cmd();函數來使能通道)。加上以前(本文沒有)對DMA參數的初始化(初始化存儲器和外設基地址等),就能夠啓動一次傳輸了。

 

傳輸時間問題:傳輸時間跟波特率密切相關。好比波特率是9600,意思就是每秒鐘發送或接受的速率爲9600bit/s,8bit=1Byte(字節),故當波特率爲9600時,串口的傳輸速率爲1200字節每秒。上文咱們申請的存儲器(內存)空間是5200字節,故串口要傳輸完這個大小的空間內容內容,預計須要5200/1200約4秒多。