STM32自學之SPI的DMA操作(寄存器級)
一、實驗目標
學會配置STM32的SPI寄存器和DMA寄存器,實現STM32的SPI1與SPI2通信功能,每次發送一字節數據,并可多次發送,如果接收的數據正確,則點亮LED燈。之后看可以利用DMA來實現什么功能~~~
二、實驗目的
加入DMA的SPI通信相對于普通SPI通信有什么好處?ST給SPI加了DMA功能出于什么目的?我覺得這是很重要的一個問題,一直邊學習邊想。以下是我的看法:
減少CPU負荷?我想這應該是DMA最主要的功能,可是對于SPI通信來說,其實大部分時候我們需要根據發送的指令->目標器件的應答來決定下一個指令,所以此時CPU還是需要一直等待每次通信的結束。而且像SD卡的操作,是一個順序流的指令操作過程,用中斷也不容易控制。那到底加入了DMA有什么好處?仔細查看了STM32F10xxx的用戶手冊,發現這么一行字“連續和非連續傳輸:當在主模式下發送數據時,如果軟件足夠快,能夠在檢測到每次TXE的上升沿(或TXE中斷),并立即在正在進行的傳輸結束之前寫入SPI_DR寄存器,則能夠實現連續的通信;此時,在每個數據項的傳輸之間的SPI時鐘保持連續,同時BSY位不會被清除。如果軟件不夠快,則會導致不連續的通信;這時,在每個數據傳輸之間會被清除”以及
也就是說如果連續傳輸而不使用DMA的話,需要CPU不停檢測TXE并很快地置入SPI->DR的值,對于復雜程序的話這是很難達到的,而如果使用DMA,就可以輕易實現連續傳輸,CPU只需等待其完成就好。我想到的一個應用就是在寫SD卡的時候,每次寫一個塊512字節,就可以用到,能提高SD卡的寫入數據速率。
其次還可以降低功耗,記得數字集成電路老師說過一句話“軟件上降低數字電路功耗的一個方法就是減少電平轉換。”那么連續通信的時候,像SPI的BSY電平轉換會大大減少!
最后一點,雖然效果不大,就是如果不是用DMA,那么CPU的工作就是搬運工,把SPI->DR的內容搬到內存存儲起來,而如果使用DMA,就省略了這個環節!
我想,為什么實現同一個功能,有的執行起來很流暢,有的卻很卡,應該和這些小細節的減載有關吧。
這次先把SPI基本通信寫出來,然后再寫SPI的連續通信,并看能不能用到SD卡讀寫上。
三、SPI&DMA分析
1、這里先說明一下SPI的全雙工通信(高手略過哈)
SPI全雙工通信的特點:一邊發送一邊接收,硬件上只有一個SPI->DR寄存器和兩個緩沖器(發送緩沖器和接收緩沖器),主模式(從模式類似):SPI->DR會先讀發送緩沖器,并通過MOSI管腳(Master output Slave Input)一位一位地發送出去,在發送的過程中,SPI->DR的數據會左移(如果是高位先發送),并且會從MISO(Master input Slave output)讀入數據填補SPI->DR左移后的空缺。傳完8比特后,SPI->DR再把數據并行寫入接收緩沖寄存器。所以,SPI1與SPI2的通信過程如下:
配置SPI寄存器的時候,需要注意以下幾點:
(1)nss的配置:如果是單主單從,使用nss軟件管理,除了用MSTR配置主從設備,還要設置SSM和SSI,只有在SSM位為1時,SSI位才有意義。
(2)主從設備的數據幀格式,時鐘沿讀寫模式要一致;
(3)SPI的寄存器也需要開啟DMA使能;
(4)SPI雖然可以發送16bit數據,可是只支持8bitDMA!
2、再說一下DMA
DMA——Direct Memory Access,直接內存存取,作用是獨立于CPU,直接建立內存與外設的通信通道。
SPI的DMA操作,就是在SPI->TXE為1時,會向對應的DMA通道發出請求,DMA通道會發出應答信號,SPI收到應答信號后撤銷請求信號,DMA撤銷應答信號,并把內存值置入發送緩沖,SPI傳送開始。接收過程與上面類似。
DMA配置的部分說明:
(1) 需要使能RCC寄存器的SPI和DMA時鐘,至于輔助時鐘,查過網上的討論,有人說一些外設如果沒有開啟輔助時鐘會不能用,但SPI不需要;
(2) DMA的存儲器地址(memorybaseaddr):即變量地址。我們在程序中定義的每個變量,都有對應的內存地址,你想把SPI的接收發送數據存在哪個變量,就將對應變量的地址賦給DMA存儲器地址寄存器。如u8 SPI1_TX_Buff的地址是(u32)&SPI1_TX_Buff;u8 SPI1_TX_Buff[512]的地址是(u32)SPI1_TX_Buff。
(3) DMA循環模式:有些資料會譯為DMA的循環緩存模式,我覺得不太準確,這里循環的意思是指DMA的傳輸數量計數器會重置初值,由于DMA每傳一個數據,傳輸數量計數器減一,只有在傳輸數量計數器的值不為零時,才會響應請求。在循環模式下,當傳輸計數器的值減為0后,會重新裝載;而內存(緩存)地址則不管循環非循環模式,都會在每次傳輸完成后重置為基地址。所以,如果我們把DMA設置會正常模式,那么在下次傳輸前,只需對DMA的傳輸數量計數器重新寫入就行。
循環模式一般用于數據更新,比如ADC采用需要不停更新數據。
(4) DMA的外設地址:正點原子的串口DMA實驗中,在寫外設地址時,都會用一個變量緩存再寫入,否則程序就運行不正確,他也不知道為什么,而ST庫函數的example中對于外設地址也都是重新define的,所以外設地址最好還是采用#define SPI1_DR_Addr ( (u32)0x4001300C )定義的好。
至于外設地址,可以先從STM32的用戶手冊“2.3存儲器映像”得到起始地址+對應外設所在目錄的“寄存器地址映像”標識的偏移地址。例如:從“2.3存儲器映像”得到SPI1起始地址0x40013000,從SPI所在目錄的“寄存器地址映像”得到SPI->DR的偏移量為0x0C,那么SPI1_DR_Addr就是0x4001300C;
(5) DMA通道開啟順序:按照下圖的數字序號依次開啟,才能確保數據正確發送。比如①的SPI2_TX_Buff對應的是DMA通道5.
(6) 正常模式的第二次發送:DMA發送的時候只需使能DMA就可以開始傳送,但是第二次傳送之前,需要進行以下步驟:
1、 關閉DMA通道;
2、 清除DMA傳輸完成標志以及重置CNDTR傳輸數量計數器;
3、 開啟DMA通道,等待傳輸完成。
四、實驗結果
利用SPI1和SPI2進行兩次數據傳輸,并比較SPI1_RX與SPI2_TX,SPI2_RX與SPI1_TX,數據相同點亮LED燈。
在某個論壇看到有人說把SPI的速度設置為2分頻傳輸數據不正確,分析原因是DMA反應不過來。我也試了一下,傳輸正常,數據正確。(SPI傳輸速率是用JTAG仿真查看寄存器的)
哦,對了,期間還吃過一個虧,害我調了好久,就是下面的語句:
while( ( DMA1->ISR & (1<<17) ) == 0 ) ; //等待通道5傳輸完成
我寫成:
while( DMA1->ISR & (1<<17) == 0 ) ; //等待通道5傳輸完成
由于“==”的優先級比“&”高,所以會先執行“(1<<17) == 0”,結果是0,再與上DMA1->ISR,那么相當于while直接跳過了,讀不到數據!很低級的錯誤!所以提醒后來者,看起來可加可不加的括號,還是要加上去的好!
還有一個問題,一直在想DMA傳輸,那么硬件怎么認為一次傳輸的結束而停止以及怎樣才能開啟新一次的傳輸。我覺得最關鍵就是DMA的傳輸數量計數器以及DMA的傳輸完成標志。只要DMA的計數器不為零,就能響應請求傳輸,此時就算傳輸完成標志置位,也能進行DMA響應,只不過你不知道什么時候完成罷了。所以每次傳輸開始前,程序需要清除標志位并檢測到該標志位置位,才知道一次傳輸是否完成!
續:終于把SPI的DMA弄完了,實現了連續發送和讀取的功能,DMA開辟512字節的數組作為內存存儲數據(所以連續發送最大的數據量也是512,當然可以在宏定義里面更改),通過num控制要寫入或讀入的數據量,源代碼中有3個函數,一個函數是讀寫一體的,一個函數是只發送模式,一個函數是只接收模式,都通過測試。唯一的缺陷就是沒有進行錯誤檢測,特別說明一下,我把清標志位是放在函數前面而不是函數后面,就是想函數執行完,標志位依然還在,我們可以以此來判斷是否有錯誤。在這里和大家分享一下小經驗。
(1) 怎么測試?最好的測試方法我覺得就是雙機通訊了,由于實驗室資源比較好,所以我得以有兩個STM32(非MiniSTM32,用的是AG嵌入式開發板)進行測試,所以以上代碼都是通過雙擊測試的,不過我只整理了SPI1主機源代碼,需要的自己稍微改一下就可以,程序中有注釋!
(2) 用雙機測試的時候,剛開始我沒有共地,導致數據可以接收,但是數據錯誤!所以緊記,當你使用兩個器件通訊或交互時,一定要先檢查兩個器件是否共地,甚至共源!
(3) 如果只有一個STM32其實也可以測試,就是把MISO和MOSI短接,但這個測試方法,用來測試SPI1_ReceiveSendByte(u16 num)就比較方便,用來測試只發送和只接收模式就需要改一下函數咯。
(4) 弄了這么久的SPI_DMA,也不知道用處大不大,總之弄完了,呵呵,也算比較了解SPI總線和DMA了,接下來想試試原子哥的新的SD卡函數,原來AG嵌入式開發板也是移植原子哥的舊版,也是有些卡初始化失敗,我還以為是我的卡有問題呢?還有就是文件系統,前陣子只弄了基本的讀寫,準備把FATFS文件系統寫得完善一點~
最后,附上源代碼。(使用的不是MiniSTM32,所以大家在測試時只需要改一下LED驅動。)
第一個源代碼是基礎的,實現一個字節在SPI1&SPI2的傳送;
第二個是函數化的代碼咯,發送隨意數量的8bit數據,數量小于512;
STM32學習附件下載 學習交流群:611386401
STM32學習相關視頻:(stm32串口應用)
http://www.makeru.com.cn/live/detail/1290.html?s=60220
http://www.makeru.com.cn/live/1392_1164.html?s=60220
(stm32電機驅動)
http://www.makeru.com.cn/live/1392_1218.html?s=60220
(定時器)
http://www.makeru.com.cn/live/1392_1199.html?s=60220
(DMA專題講解)
http://www.makeru.com.cn/live/1392_1048.html?s=60220
http://www.makeru.com.cn/live/1392_1020.html?s=60220
( ADC讀取光照傳感器)
http://www.makeru.com.cn/live/1392_1004.html?s=60220
一小時徹底掌握STM32中斷
http://www.makeru.com.cn/live/3523_1666.html?s=60220
(STM32中斷系統)
http://www.makeru.com.cn/live/1392_1124.html?s=60220
(時鐘系統)
http://www.makeru.com.cn/live/1392_1082.html?s=60220
(stm32 實戰之溫濕度采集)
http://www.makeru.com.cn/live/detail/1476.html?s=60220
(零基礎電子產品設計)
http://www.makeru.com.cn/live/3727_1388.html?s=60220
上一篇:STM32學習------SPI筆記【寄存器版】
下一篇:STM32學習筆記——SPI介紹及配置
推薦閱讀
史海拾趣
進入90年代后期,Corsair再次調整其產品策略,由生產標準內存轉變為生產高于規格的內存,即超頻內存。這一決策迎合了當時市場對高性能內存的需求,Corsair的超頻內存迅速在市場上獲得了認可。其產品的超級性能專為極大需求的應用軟件而設,也一直被應用關鍵的服務器及極高性能的工作站(包括游戲系統)上。
在電子行業中,產品質量是企業立足之本。DC Components公司深知這一點,因此始終把質量控制放在首位。公司通過實施嚴格的質量控制系統,確保每一個產品都符合高質量標準,并符合所有合同要求。這種對質量的堅守,使DC Components公司在市場上贏得了良好的口碑,吸引了眾多客戶的青睞。
在電子行業中,技術創新是企業持續發展的關鍵。DAICO公司始終將研發創新作為核心戰略,不斷投入大量資源用于新技術和新產品的研發。通過持續的創新和積累,DAICO在中頻/射頻和微波控制領域取得了多項技術領先成果,成為行業內的佼佼者。
DAICO公司成立于XXXX年,最初是一家位于加利福尼亞的小型私營公司。在公司成立的初期,DAICO專注于研發和生產中頻/射頻和微波控制產品,以及放大器。這些產品主要用于國防電子和航空航天領域,為DAICO在電子行業中打下了堅實的基礎。
在電子行業中,環保問題日益受到關注。Component Research Co積極響應環保號召,將環保理念融入產品研發和生產過程中。公司采用環保材料、推行節能減排措施、加強廢棄物處理等,努力降低生產過程中的環境污染。這些舉措不僅提升了公司的社會形象,還為公司贏得了更多客戶的青睞。
隨著光通信技術的快速發展,三環集團敏銳地捕捉到了這一市場機遇。在2001年,公司開始研發生產光通訊用陶瓷部件,這些部件在光纖通信中發揮著重要作用。通過不斷的技術創新和產品優化,三環集團成功地將光通訊用陶瓷部件推向市場,并獲得了客戶的廣泛認可。這一舉措不僅拓展了公司的業務領域,也為公司帶來了新的增長點。
1、 應用Web和MATLAB的信號與系統基礎(第二版) 作者:(美)Edward Kamen, Bonnie Heck, Ed Kamen 2、CMOS 射頻集成電路設計(英文版) 作者:美Lee,T.H.著 3、MATLAB原理與工程應用 作者:(美)Edward B.Magrab ...… 查看全部問答∨ |
|
上拉電阻: 1、當TTL電路驅動COMS電路時,如果TTL電路輸出的高電平低于COMS電路的最低高電平(一般為3.5V),這時就需要在TTL的輸出端接上拉電阻,以提高輸出高電平的值。 2、OC門電路必須加上拉電阻,才能使用。 3、為加大輸出引腳的驅動能力, ...… 查看全部問答∨ |
昨中午加上今早上,學習總算完成,學習過程跟蹤帖子: https://bbs.eeworld.com.cn/thread-355463-1-3.html 考試通過80分 繼續努力! … 查看全部問答∨ |
最近想做一個對射式紅外報警裝置,已經差不多完成了,居然被一體化的紅外遙控頭難住了。 大概的框圖如附圖,發射端用1KHz方波去調制38KHz紅外載波,本來想著接收端僅僅把38KHz的載波濾掉,還原出1KHz的方波,然后被LM567鎖相識別的。 誰知道這個 ...… 查看全部問答∨ |
1.我想問下ADCTRIG這個應該怎么使能?我沒在ADC的頭文件里找到這一位。具體附圖。2.我想問下ADCINT·~9這9個位置都有什么區別,難道只是提供了九個中斷? 3.我想問下INTSEL9N10這些位是干嘛的啊~ 拜托各位啦,我最近自己學這個真是好煩惱啊,唉唉 ...… 查看全部問答∨ |