今天剛看了乙個adc採集的程式,和之前用其他微控制器寫的程式還是有比較大的差別,這個差別主要就在dma。這裡面總結一下,有一部分是**別人的。
什麼是stm32
的dma
?其全稱是:
direct memory access
;根據st
公司提供的相關資訊,
dma是
stm32
中乙個獨立與
cortex-m3
核心的模組,有點類似與
adc、
pwm、
timer
等模組;主要功能是通訊「橋梁」的作用,可以將所有外設對映的暫存器「連線」起來,這樣就可以高速問各暫存器,其傳輸不受
cpu的支配,傳輸還是雙向的;例如,從「表面」上看,它可以將
flash
中的資料與儲存器中變數建立通訊,還可以將一外設的積存器或緩衝器與另外設的暫存器或緩衝器建立雙向通訊,有點像把外設硬體之間用「導線」連線在一起了。其間的通訊不佔
cpu資源,訪問速度高,對於實時性強的應用將是乙個很好的選擇;當然,對於實時性非常強的,建議還是採用專用的
dsp晶元。
怎樣啟用
dma?首先,眾所周知的是初始化,任何裝置啟用前都要對其進行初始化,要對模組初始化,還要先了解該模組相應的結構及其函式,以便正確的設定;由於
dma較為複雜,我就只談談
dma的基本結構和和常用函式,這些都是
st公司提供在庫函式中的。
1、下面**是乙個標準
dma設定,當然實際應用中可根據實際情況進行裁減:
dma_deinit(dma_channel1);
上面這句是給
dma配置通道,根據
st提供的資料,
stm3210fx
中dma包含7
個通道(
ch1~ch7
),這裡需要選擇乙個傳輸通道
dma_initstructure.dma_peripheralbaseaddr
= adc1_dr_address;
上面語句中的
dma_initstructure
是乙個dma
結構體,在庫中有宣告了,當然使用時就要先定義了;
dma_peripheralbaseaddr
是該結構體中乙個資料成員,給
dma乙個起始位址,好比是乙個
buffer
àdma_peripheralbaseadd
àmemory
中變數空間(或
flash
中資料空間等),
adc1_dr_address
是adc1的位址,既然是橋梁,肯定要連線兩個端點,這裡需要明白所需要連線的外設的位址;
dma_initstructure.dma_memorybaseaddr
= (u32)adc_convertedvalue;
上面這句很顯然是
dma要連線在
memory
中變數的位址,
adc_convertedvalue
是我自己在
memory
中定義的乙個變數;
dma_initstructure.dma_dir
= dma_dir_peripheralsrc;
上面的這句是設定
dma的傳輸方向,就如前面我所說的,
dma可以雙向傳輸,也可以單向傳輸,這裡設定的是單向傳輸,如果需要雙向傳輸:把
dma_dir_peripheralsrc
改成dma_dir_peripheraldst
即可。dma_initstructure.dma_buffersize =
2;
上面的這句是設定
dma在傳輸時緩衝區的長度,前面有定義過了
buffer
adc1_dr_address
,為了安全性和可靠性,一般需要給
buffer
定義乙個儲存片區,這個引數的單位有三種型別:
byte
、halfword
、word
,我設定的2個
half-word(
見下面的設定);
32位的
mcu中1個
half-word
佔16 bits
。dma_initstructure.dma_peripheralinc
= dma_peripheralinc_disable;
上面的這句是設定
dma的外設遞增模式,如果
dma選用的通道(
chx)有多個外設連線,需要使用外設遞增模式:
dma_peripheralinc_enable;
我的例子裡
dma只與
adc1
建立了聯絡,所以選用
dma_peripheralinc_disable
dma_initstructure.dma_memoryinc =
dma_memoryinc_enable;
上面的這句是設定
dma的記憶體遞增模式,
dma訪問多個記憶體引數時,需要使用
dma_memoryinc_enable
,當dma
只訪問乙個記憶體引數時,可設定成:
dma_memoryinc_disable
。dma_initstructure.dma_peripheraldatasize
= dma_peripheraldatasize_halfword;
上面的這句是設定
dma在訪問時每次操作的資料長度。有三種資料長度型別,前面已經講過了,這裡不在敘述。
dma_initstructure.dma_memorydatasize =
dma_memorydatasize_halfword;
與上面雷同。在此不再說明。
dma_initstructure.dma_mode
= dma_mode_circular;
上面的這句是設定
dma的傳輸模式:連續不斷的迴圈模式,若只想訪問一次後就不要訪問了(或按指令操作來反問,也就是想要它訪問的時候就訪問,不要它訪問的時候就停止),可以設定成通用模式:
dma_mode_normal
dma_initstructure.dma_priority =
dma_priority_high;
上面的這句是設定
dma的優先級別:可以分為4級:
veryhigh
,high,medium,low.
dma_initstructure.dma_m2m = dma_m2m_disable;
上面的這句是設定
dma的2個
memory
中的變數互相訪問的
dma_init(dma_channel1,&dma_initstructure);
前面那些都是對
dma結構體成員的設定,在次再統一對
dma整個模組做一次初始化,使得
dma各成員與上面的引數一致。
/*dma enable*/
dma_cmd(dma_channel1,enable);
使能此通道。
當然更多的還需要看韌體庫函式的說明。
這裡面知識dma的乙個簡單應用,後面做很多設計在資料傳輸上需要做這種轉變,特別是像我這樣從微控制器學過來的,現在裡面有了更好的方式要學會去運用,不能固守原來微控制器的設計思路。這個相信也是後面學習中很重要的一部分。
STM32外設DMA使用總結
stm32外設dma使用總結 1 根據需要選擇dam模式 1 迴圈模式 dma mode dma mode circular 2 正常模式 dma mode dma mode normal 2 對於dma1的chanel3,對應外設為usart3的rx 試想 如果串列埠接收中斷和dam中斷同時開啟,...
STM32使用DMA方式Printf
使用庫函式除錯printf時需要占用系統資源所以採用dma方式來printf資料 兩種實現方式 pre 已經有dma傳送管理函式 include stdio.h include stdarg.h brief modbus傳送管理 void startmodbustranst uart handlet...
實現STM32中USART的DMA
2010年06月29日 星期二 20 56 終於開葷了 dma 先抄一小段dma的說明。對於沒玩過dma 的朋友,這裡簡單說一下dma,用自己的語言說吧,那就是,從某個位置 傳輸資料到某個位置,如果不用dma,那要cpu參與操作,乙個位元組乙個位元組地搬,效率高 點的,就乙個字乙個字地搬.但當你用了...