精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

STM32 DMA詳解

工程師 ? 來源:一口Linux ? 作者:一口Linux ? 2020-10-27 14:47 ? 次閱讀

1、綜述

DMA(Direct memory access)直接內存訪問,被用于內存和內存之間或內存和外設之間的高速數據傳輸。數據傳輸可以在沒有CPU的干預下快速移動,這樣可以保持CPU資源處理其他事情。

DMA 控制器基于復雜的總線矩陣架構,將功能強大的雙 AHB 主總線架構與獨立的 FIFO 結 合在一起,優化了系統帶寬,下圖①處,可以看出雙 AHB 主總線架構與獨立的 FIFO的結構。

注意看英文備注:

DMA1控制器AHB外設端口沒有像DMA2一樣連接到總線矩陣,所以只有DMA2數據流可以執行存儲器到存儲器的傳輸。

我們對上圖的②處,(DMA1和DMA2結構一樣,我們就選擇DMA1)詳細看

①每個數據流總共可以有多達 8 個通道(或稱請求)。

②DMA1共有8個數據數據流(兩個DMA共有16個數據流)。

③每個DMA都有數據流仲裁器,用于處理 DMA 請求間的優先級。

④DMA的數據流又有獨立的FIFO。

⑤DMA采用雙 AHB 主總線架構。

備注:

①處是選擇器,配置完成只能選擇一個通道,而③處是仲裁器,也就是說,配置完成,可能8個數據流全部存在,由仲裁器判斷優先級。

2、DMA事務

DMA從傳輸事務包含一系列的給定數目的數據傳輸序列。傳輸的數目可以通過軟件編程,8位,16位或32位。

每一次DMA傳輸包含3個操作

通過 DMA_SxPAR 或 DMA_SxM0AR 寄存器尋址,從外設數據寄存器或存儲器單元中加載數據。

通過 DMA_SxPAR 或 DMA_SxM0AR 寄存器尋址,將加載的數據存儲到外設數據寄存器或存儲器單元。

·DMA_SxNDTR 計數器在數據存儲結束后遞減,該計數器中包含仍需執行的事務數。

在產生事件后,外設會向 DMA 控制器發送請求信號。DMA 控制器根據通道優先級處理該請求。只要 DMA 控制器訪問外設, DMA 控制器就會向外設發送確認信號。外設獲得 DMA 控制器的確認信號后,便會立即釋放其請求。一旦外設使請求失效, DMA 控制器就會釋放確認信號。如果有更多請求,外設可以啟動下一個事務。

3、通道選擇

每個數據流可以有8個通道。

通過上圖①可以看出,通道選擇仲裁器可以通過DMA_SxCR寄存器的CHSEL[2:0]配置

DMA的請求可以來自TIM,ADC,SPI等外設。

DMA1的請求通道

DMA2的請求通道

4、仲裁器

仲裁器為兩個 AHB 主端口(存儲器和外設端口)提供基于請求優先級的 8 個 DMA 數據流請求管理,并啟動外設/存儲器訪問序列。

優先級管理分為兩個階段

·軟件:每個數據流優先級都可以在 DMA_SxCR 寄存器中配置。分為四個級別:非常高優先級、高優先級、中優先級、低優先級。

·硬件:如果兩個請求具有相同的軟件優先級,則編號低的數據流優先于編號高的數據流。例如,數據流2的優先級高于數據流4。

5、DMA數據流

8個DMA控制器數據流都能夠提供源和目標之間的單向傳輸鏈路。

每個數據流配置后都可以執行

常規類型事務:存儲器到外設、外設到存儲器或存儲器到存儲器的傳輸。

雙緩沖區類型事務:使用存儲器的兩個存儲器指針的雙緩沖區傳輸(當 DMA 正在進行自/至緩沖區的讀/寫操作時,應用程序可以進行至/自其它緩沖區的寫/讀操作)。

要傳輸的數據量(多達 65535)可以編程,并與連接到外設 AHB 端口的外設(請求 DMA 傳輸)的源寬度相關。每個事務完成后,包含要傳輸的數據項總量的寄存器都會遞減。

6、源、目標和傳輸模式

源地址和目標地址可以在整個4G地址空間,在0x00000000和0xFFFFFFFF之間。

在DNA_SxCR寄存求的DIR[1:0]配置DMA的傳輸方式。

源地址和目標地址的關系

當數據寬度是半字或字時,外設地址或存儲器地址必須是半字或字對齊

6.1、外設到存儲器模式

當配置成外設到存儲器的DMA傳輸模式時,兩種模式

FIFO模式:外設有DMA請求(TIM溢出,PWM下降沿等)時,DMA會搬運源數據(外設數據)到FIFO,當FIFO滿時,將數傳輸給目標地址(內存)。

直連模式:配置直連模式,DMA_SxFCR 寄存器中的 DMDIS 值為“0”。不使用 FIFO 的閾值級別控制:每完成一次從外設到 FIFO 的數據傳輸后,相應的數據立即就會移出并存儲到目標中。

傳輸開始條件,使能數據流(DMA_SxCR 寄存器中的位 EN 置 1),然后外設發出請求,再然后該請求贏得了數據流仲裁,才會開始傳輸。

傳輸停止條件,下列滿足一條即可

DMA_SxNDTR 寄存器達到零。

外設請求傳輸終止。

DMA_SxCR 寄存器中的 EN 位由軟件清零。

6.2 存儲器到外設模式

FIFO模式

這種模式,只要使能數據流(DMA_SxCR 寄存器中的位 EN 置 1),存儲器數據就會傳輸到FIFO中,發生外設請求,FIFO數據會移出并存儲到目標地址。當FIFO小于閾值,存儲器的數據會重載FIFO。

直連模式

使能數據流時,DMA傳輸存儲器的第一個數據到內部FIFO,發生外設請求時,DMA把預裝在值發送的目標地址,然后進行下一個數據的傳輸。預裝載的數據大小為 DMA_SxCR 寄存器中 PSIZE 位字段的值。

傳輸停止條件,下列滿足一條即可

DMA_SxNDTR 寄存器達到零。

外設請求傳輸終止。

DMA_SxCR 寄存器中的 EN 位由軟件清零。

存儲器到外設模式和外設到存儲器模式一樣,同樣需要對應數據流贏得仲裁,才會啟動傳輸

6.3 存儲器到存儲器模式

這種模式較為簡單,沒有外設請求

啟動傳輸

DMA_SxCR 寄存器中的使能位 (EN) 置 1 來使能數據流時,數據就會從源地址傳輸到FIFO,到達FIFO閾值時,FIFO數據移出到目標地址。

停止傳輸,下列滿足一條即可

DMA_SxNDTR 寄存器達到零。

DMA_SxCR 寄存器中的 EN 位由軟件清零。

當然,同樣該數據流需要贏得仲裁。

7、指針遞增

外設和存儲器指針在每次傳輸后自動向后遞增或保持常量,根據DMA_SxCR寄存器的PINC和MINC位。

禁止遞增模式時非常有用的,當外設源和目標數據是通過單個寄存器訪問的。

如果使能了遞增模式,則根據在 DMA_SxCR 寄存器 PSIZE 或 MSIZE 位中編程的數據寬度,下一次傳輸的地址將是前一次傳輸的地址遞增 1(對于字節)、 2(對于半字)或 4(對于字)。

為了優化封裝操作,可以不管 AHB 外設端口上傳輸的數據的大小,將外設地址的增量偏移大小固定下來。DMA_SxCR 寄存器中的 PINCOS 位用于將增量偏移大小與外設 AHB 端口或32 位地址(此時地址遞增 4)上的數據大小對齊。PINCOS 位僅對 AHB 外設端口有影響。

如果將 PINCOS 位置 1,則不論 PSIZE 值是多少,下一次傳輸的地址總是前一次傳輸的地址遞增 4(自動與 32 位地址對齊) 。但是, AHB 存儲器端口不受此操作影響。

如果 AHB 外設端口或 AHB 存儲器端口分別請求突發事務,為了滿足 AMBA 協議(在固定地址模式下不允許突發事務),則需要將 PINC 或 MINC 位置 1。

8、循環模式

循環模式可用于處理循環緩沖區和連續數據流(例如 ADC 掃描模式)。可以使用 DMA_SxCR 寄存器中的 CIRC 位使能此特性。

當激活循環模式時,要傳輸的數據項的數目在數據流配置階段自動用設置的初始值進行加載,并繼續響應 DMA 請求。

也就是說,比如我們要從內存中采集 64 個字節發送到串口,如果設置為重復采集,那么它會在 64 個字節采集完成之后繼續從內存的第一個地址采集,如此循環。這里我們設置為一次連續采集完成之后不循環。所以設置值為 DMA_Mode_Normal。在我們下面的實驗中,如果設置此參數為循環采集,那么你會看到串口不停的打印數據,不會中斷。

9、雙緩沖模式

此模式可用于所有 DMA1 和 DMA2 數據流。

通過將 DMA_SxCR 寄存器中的 DBM 位置 1,即可使能雙緩沖區模式。

除了有兩個存儲器指針之外,雙緩沖區數據流的工作方式與常規(單緩沖區)數據流的一樣。使能雙緩沖區模式時,將自動使能循環模式( DMA_SxCR 中的 CIRC 位的狀態是“無關”),并在每次事務結束時交換存儲器指針。

在此模式下,每次事務結束時, DMA 控制器都從一個存儲器目標交換為另一個存儲器目標。這樣,軟件在處理一個存儲器區域的同時, DMA 傳輸還可以填充/使用第二個存儲器區域。

基于DMA雙緩沖模式的的特點,應用中必須開辟兩個存儲區以及存放兩個存儲區首地址的存儲寄存器,DMA_SxM0AR和DMA_SxM1AR。

1:DMA_SxM0AR:指向存儲區0(DMA_Memory_0),單緩沖模式下默認使用該寄存器做存儲區指針。

2:DMA_SxM1AR:指向存儲區1(DMA_Memory_1),僅在DMA雙緩沖模式下才能使用。

3:DMA正在訪問的當前存儲區由DMA_SxCR表示

CT:當前目標

CT = 0:DMA正在訪問存儲區0,CPU可以訪問存儲區1。

CT = 1:DMA正在訪問存儲區1,CPU可以訪問存儲區0。

優點:

使用DMA雙緩沖傳輸,既可以減少CPU的負荷,又能最大程度地實現DMA數據傳輸和CPU數據處理互不打擾又互不耽擱,DMA雙緩沖模式的循環特性,使用它對存儲區的空間容量要求也會大大降低。尤其在大批量數據傳送時,你只需開辟兩個合適大小的存儲區,能滿足DMA在切換存儲區時的當前新存儲區空出來就好,并不一定要開辟多大多深的存儲空間,單純一味地加大雙緩沖區的深度并不明顯改善數據傳輸狀況。

10、代碼

標準外設庫配置代碼:

/* Configure DMA Stream */DMA_InitStructure.DMA_Channel = DMA_Channel_0;DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SRC_Const_Buffer;DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)DST_Buffer;DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToMemory;DMA_InitStructure.DMA_BufferSize = (uint32_t)32;DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;DMA_InitStructure.DMA_Priority = DMA_Priority_High;DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;。 DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;DMA_Init(DMA2_Stream0, &DMA_InitStructure);

DMA_Channel :

設置 DMA 數據流對應的通道,供每個數據流選擇的通道請求多達 8 個,取值有

#define DMA_Channel_0 ((uint32_t)0x00000000)#define DMA_Channel_1 ((uint32_t)0x02000000)#define DMA_Channel_2 ((uint32_t)0x04000000)#define DMA_Channel_3 ((uint32_t)0x06000000)#define DMA_Channel_4 ((uint32_t)0x08000000)#define DMA_Channel_5 ((uint32_t)0x0A000000)#define DMA_Channel_6 ((uint32_t)0x0C000000)#define DMA_Channel_7 ((uint32_t)0x0E000000)

DMA_PeripheralBaseAddr :

DMA 傳輸的外設基地址,假設進行uart1串口DMA 傳輸,我們可以按照寄存器的地址偏移直接設置地址:0x40011004,也可以直接使用ST提供庫的表示方法:&USART1-》DR。

DMA_Memory0BaseAddr :

DMA 傳輸的內存基地址。

DMA_DIR:

設置數據傳輸方向,有存儲器到存儲器,存儲器到外設,外設到存儲器三種選擇,取值有:

#define DMA_DIR_PeripheralToMemory ((uint32_t)0x00000000)#define DMA_DIR_MemoryToPeripheral ((uint32_t)0x00000040) #define DMA_DIR_MemoryToMemory ((uint32_t)0x00000080)

DMA_BufferSize:

設置一次傳輸數據量的大小

DMA_PeripheralInc:

設置傳輸數據的時候外設地址是不變還是遞增,如果設置為遞增,那么下一次傳輸的時候地址加 1,取值有:

#define DMA_PeripheralInc_Enable ((uint32_t)0x00000200)#define DMA_PeripheralInc_Disable ((uint32_t)0x00000000)

DMA_MemoryInc:

設置傳輸數據時 候內存地址 是否遞增。這個參數和DMA_PeripheralInc 意思接近,只不過針對的是內存(存儲器),取值有:

#define DMA_MemoryInc_Enable ((uint32_t)0x00000400) #define DMA_MemoryInc_Disable ((uint32_t)0x00000000)

DMA_PeripheralDataSize:

設置外設的數據長度是為字節傳輸(8bits),半字 傳 輸 (16bits) 還 是 字 傳 輸 (32bits),取值有:

#define DMA_PeripheralDataSize_Byte ((uint32_t)0x00000000) #define DMA_PeripheralDataSize_HalfWord ((uint32_t)0x00000800)#define DMA_PeripheralDataSize_Word ((uint32_t)0x00001000)

DMA_MemoryDataSize:

用來設置內存的數據長度。

DMA_Mode:

設置 DMA 模式是否循環采集,取值有:

#define DMA_Mode_Normal ((uint32_t)0x00000000) #define DMA_Mode_Circular ((uint32_t)0x00000100)

DMA_Priority:

設置 DMA 通道的優先級,有低,中,高,超高三種模式。就是仲裁器仲裁的時候用的,當多個數據流同時開啟,DMA仲裁器優先處理優先級高的數據流,取值有:

#define DMA_Priority_Low ((uint32_t)0x00000000) #define DMA_Priority_Medium ((uint32_t)0x00010000)#define DMA_Priority_High ((uint32_t)0x00020000) #define DMA_Priority_VeryHigh ((uint32_t)0x00030000)

DMA_FIFOMode:

設置是否開啟 FIFO 模式,取值有:

#define DMA_FIFOMode_Disable ((uint32_t)0x00000000) #define DMA_FIFOMode_Enable ((uint32_t)0x00000004)

DMA_FIFOThreshold:

選擇 FIFO 閾值,只有上個參數選擇使能FIFO,這個參數才有用。取值有:

#define DMA_FIFOThreshold_1QuarterFull ((uint32_t)0x00000000)#define DMA_FIFOThreshold_HalfFull ((uint32_t)0x00000001)#define DMA_FIFOThreshold_3QuartersFull ((uint32_t)0x00000002) #define DMA_FIFOThreshold_Full ((uint32_t)0x00000003)

DMA_MemoryBurst:

配置存儲器突發傳輸配置。可以選擇為 4 個節拍的增量突發傳輸 ,8 個節拍的增量突發傳輸 , 16 個街拍的增量突發傳輸以及單次傳輸。取值有:

#define DMA_MemoryBurst_Single ((uint32_t)0x00000000) #define DMA_MemoryBurst_INC4 ((uint32_t)0x00800000) #define DMA_MemoryBurst_INC8 ((uint32_t)0x01000000) #define DMA_MemoryBurst_INC16 ((uint32_t)0x01800000)

DMA_PeripheralBurst:

配置外設突發傳輸配置。跟前面一個參數DMA_MemoryBurst 作用類似,只不過一個針對的是存儲器。取值有:

#define DMA_PeripheralBurst_Single ((uint32_t)0x00000000) #define DMA_PeripheralBurst_INC4 ((uint32_t)0x00200000) #define DMA_PeripheralBurst_INC8 ((uint32_t)0x00400000) #define DMA_PeripheralBurst_INC16 ((uint32_t)0x00600000)

責任編輯:haq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 控制器
    +關注

    關注

    112

    文章

    15896

    瀏覽量

    175427
  • STM32
    +關注

    關注

    2258

    文章

    10828

    瀏覽量

    352546
  • dma
    dma
    +關注

    關注

    3

    文章

    552

    瀏覽量

    99954
收藏 人收藏

    評論

    相關推薦

    STM32的USB的數據能通過DMA直接傳到SPI接口嗎?STM32DMA能訪問USB寄存器不?

    提問:STM32的USB的數據能通過DMA直接傳到SPI接口嗎?STM32DMA能訪問USB寄存器不?多謝啦
    發表于 05-17 14:30

    STM32F407頻繁調用DMA_GetCurrDataCounter,DMA接收不到數據的原因?

    STM32F407頻繁調用DMA_GetCurrDataCounter,DMA接收不到數據,像死了一樣
    發表于 05-14 07:13

    大家使用過STM32DMA功能嗎?感覺怎么樣?

    大家使用過STM32DMA功能嗎?感覺怎么樣。
    發表于 05-11 06:06

    使用stm32CubeMx時,設置DMA為Circular模式會被HAL_ADC_Start_DMA阻塞為什么?

    在使用stm32CubeMx時遇到一個問題,我在用DMA方式獲取ADC數據時,設置DMA為Circular模式會被HAL_ADC_Start_DMA阻塞,不懂為什么會這樣,后來換了F1
    發表于 04-25 08:12

    stm32f407zet6串口的dma會和sdio的dma發生干擾嗎?

    stm32f407zet6 串口的dma會和sdio的dma發生干擾嗎
    發表于 03-11 07:25

    STM32U5系列TIMER+DMA+DAC應用演示

    有人使用STM32U575芯片的DAC功能。他希望使用TIMER事件觸發DMA,并通過DMA傳輸內存數據到DAC輸出寄存器,進而產生相應的DAC輸出波形。可他不知如何配置DMA并實現期
    的頭像 發表于 01-24 09:10 ?1333次閱讀
    <b class='flag-5'>STM32</b>U5系列TIMER+<b class='flag-5'>DMA</b>+DAC應用演示

    STM32DMA的五大問題

    1,DMA控制器的內部結構STM32中的DMA控制器是一種用于在外設和存儲器之間傳輸數據的專用硬件。DMA控制器的內部結構主要包括以下幾個關鍵部分:通道:
    的頭像 發表于 12-10 08:00 ?1494次閱讀
    <b class='flag-5'>STM32</b>的<b class='flag-5'>DMA</b>的五大問題

    stm32啟動過程詳解

    STM32啟動過程詳解 近年來,STM32微控制器在嵌入式系統中的應用越來越廣泛。STM32微控制器具有高性能、低功耗、易擴展和豐富的外設接口等優勢。而要讓
    的頭像 發表于 12-08 15:47 ?1217次閱讀

    STM32 DMA傳輸的問題分析

    用戶使用STM32G473RET6芯片,開發環境STM32CubeMX+Keil(LL庫)。使用DMA1通道1,在半傳輸中斷和完全傳輸中斷里,拷貝ADC采集的數據。在應用過程中發現DMA
    的頭像 發表于 12-01 09:19 ?2291次閱讀
    <b class='flag-5'>STM32</b> <b class='flag-5'>DMA</b>傳輸的問題分析

    小白都看得懂的STM32DMA知識

    一、DMA簡介1、DMA簡介DMA(DirectMemoryAccess:直接內存存取)是一種可以大大減輕CPU工作量的數據轉移方式。CPU有轉移數據、計算、控制程序轉移等很多功能,但其實轉移
    的頭像 發表于 11-27 08:00 ?3270次閱讀
    小白都看得懂的<b class='flag-5'>STM32</b>的<b class='flag-5'>DMA</b>知識

    STM32串口中斷及DMA接收常見的幾個問題

    STM32串口中斷及DMA接收常見的幾個問題
    的頭像 發表于 10-26 16:41 ?3187次閱讀
    <b class='flag-5'>STM32</b>串口中斷及<b class='flag-5'>DMA</b>接收常見的幾個問題

    stm32 LL庫開發-DMA使用方法

    本文以stm32 F303K8為例,不同型號的DMA配置方法略有不同。
    的頭像 發表于 10-26 14:58 ?1102次閱讀
    <b class='flag-5'>stm32</b> LL庫開發-<b class='flag-5'>DMA</b>使用方法

    STM32基礎知識:串口通信-DMA方式

    直接存儲器訪問 (DMA) : 用于在外設與存儲器之間以及存儲器與存儲器之間進行高速數據傳輸。DMA傳輸過程的初始化和啟動由CPU完成,傳輸過程由DMA控制器來執行,無需CPU參與,從而節省CPU資源,提高利用率。
    的頭像 發表于 10-26 11:48 ?4797次閱讀
    <b class='flag-5'>STM32</b>基礎知識:串口通信-<b class='flag-5'>DMA</b>方式

    STM32速成筆記(8)—DMA

    DMA全程Direct Memory Access,即直接存儲器訪問。簡單來講,它的功能是把數據從一個地址搬運到另一個地址。
    的頭像 發表于 10-24 14:08 ?1035次閱讀
    <b class='flag-5'>STM32</b>速成筆記(8)—<b class='flag-5'>DMA</b>

    STM32 TIMER+DMA輸出PWM異常案例的問題解析

    有人使用STM32U575的TIMER加上DMA做PWM輸出。具體就是利用某TIMER的一個通道的比較事件觸發DMA,通過DMA修改CCR值來實現指定占空比的PWM輸出。
    的頭像 發表于 09-28 09:04 ?6985次閱讀
    <b class='flag-5'>STM32</b> TIMER+<b class='flag-5'>DMA</b>輸出PWM異常案例的問題解析