51c嵌入式~單片機~合集5~DMA

我自己的原文哦~? ??https://blog.51cto.com/whaosoft/12940885

一、DMA

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

DMA傳輸將數據從一個地址空間復制到另一個地址空間,提供在外設和存儲器之間或者存儲器和存儲器之間的高速數據傳輸

我們知道CPU有轉移數據、計算、控制程序轉移等很多功能,系統運作的核心就是CPU.

CPU無時不刻的在處理著大量的事務,但有些事情卻沒有那么重要,比方說數據的復制和存儲數據,如果我們把這部分的CPU資源拿出來,讓CPU去處理其他的復雜計算事務,是不是能夠更好的利用CPU的資源呢?

因此:轉移數據(尤其是轉移大量數據)是可以不需要CPU參與。比如希望外設A的數據拷貝到外設B,只要給兩種外設提供一條數據通路,直接讓數據由A拷貝到B 不經過CPU的處理

DMA就是基于以上設想設計的,它的作用就是解決大量數據轉移過度消耗CPU資源的問題。有了DMA使CPU更專注于更加實用的操作–計算、控制等。

DMA定義:

DMA用來提供在外設和存儲器之間或者存儲器和存儲器之間的高速數據傳輸。無須CPU的干預,通過DMA數據可以快速地移動。這就節省了CPU的資源來做其他操作。

DMA傳輸方式

DMA的作用就是實現數據的直接傳輸,而去掉了傳統數據傳輸需要CPU寄存器參與的環節,主要涉及四種情況的數據傳輸,但本質上是一樣的,都是從內存的某一區域傳輸到內存的另一區域(外設的數據寄存器本質上就是內存的一個存儲單元)。四種情況的數據傳輸如下:

  • 外設到內存
  • 內存到外設
  • 內存到內存
  • 外設到外設
DMA傳輸參數

我們知道,數據傳輸,首先需要的是1 數據的源地址 2 數據傳輸位置的目標地址 ,3 傳遞數據多少的數據傳輸量 ,4 進行多少次傳輸的傳輸模式?DMA所需要的核心參數,便是這四個

當用戶將參數設置好,主要涉及源地址、目標地址、傳輸數據量這三個,DMA控制器就會啟動數據傳輸,當剩余傳輸數據量為0時 達到傳輸終點,結束DMA傳輸 ,當然,DMA 還有循環傳輸模式?當到達傳輸終點時會重新啟動DMA傳輸。   也就是說只要剩余傳輸數據量不是0,而且DMA是啟動狀態,那么就會發生數據傳輸。  

DMA的主要特征

每個通道都直接連接專用的硬件DMA請求,每個通道都同樣支持軟件觸發。這些功能通過軟件來配置;

  • 在同一個DMA模塊上,多個請求間的優先權可以通過軟件編程設置(共有四級:很高、高、中等和低),優先權設置相等時由硬件決定(請求0優先于請求1,依此類推);
  • 獨立數據源和目標數據區的傳輸寬度(字節、半字、全字),模擬打包和拆包的過程。源和目標地址必須按數據傳輸寬度對齊;
  • 支持循環的緩沖器管理;
  • 每個通道都有3個事件標志(DMA半傳輸、DMA傳輸完成和DMA傳輸出錯),這3個事件標志邏輯或成為一個單獨的中斷請求;
  • 存儲器和存儲器間的傳輸、外設和存儲器、存儲器和外設之間的傳輸;
  • 閃存、SRAM、外設的SRAM、APB1、APB2和AHB外設均可作為訪問的源和目標;
  • 可編程的數據傳輸數目:最大為65535。
STM32少個DMA資源?

對于大容量的STM32芯片有2個DMA控制器?兩個DMA控制器,DMA1有7個通道,DMA2有5個通道。每個通道都可以配置一些外設的地址。

①DMA1 controller

從外設(TIMx[x=1、2、3、4]、ADC1、SPI1、SPI/I2S2、I2Cx[x=1、2]和USARTx[x=1、2、3])產生的7個DMA請求,通過邏輯或輸入到DMA1控制器 其中每個通道都對應著具體的外設:

② DMA2 controller

從外設(TIMx[5、6、7、8]、ADC3、SPI/I2S3、UART4、DAC通道1、2和SDIO)產生的5個請求,經邏輯或輸入到DMA2控制器,其中每個通道都對應著具體的外設:

上方的框圖,我們可以看到STM32內核,存儲器,外設及DMA的連接,這些硬件最終通過各種各樣的線連接到總線矩陣中,硬件結構之間的數據轉移都經過總線矩陣的協調,使各個外設和諧的使用總線來傳輸數據。我們對他來進行一點一點的分析:

下面看有與沒有DMA的情況下,ADC采集的數據是怎樣存放到SRAM中的?

沒有DMA

1.如果沒有DMA,CPU傳輸數據還要以內核作為中轉站,比如要將ADC采集的數據轉移到到SRAM中,這個過程是這樣的:

內核通過DCode經過總線矩陣協調,從獲取AHB存儲的外設ADC采集的數據,

然后內核再通過DCode經過總線矩陣協調把數據存放到內存SRAM中。

有DMA傳輸

有DMA的話,

  1. DMA傳輸時外設對DMA控制器發出請求。
  2. DMA控制器收到請求,觸發DMA工作。
  3. DMA控制器從AHB外設獲取ADC采集的數據,存儲到DMA通道中
  4. DMA控制器的DMA總線與總線矩陣協調,使用AHB把外設ADC采集的數據經由DMA通道存放到SRAM中,這個數據的傳輸過程中,完全不需要內核的參與,也就是不需要CPU的參與,

我們把上面的步驟專業一點介紹:

在發生一個事件后,外設向DMA控制器發送一個請求信號。DMA控制器根據通道的優先權處理請求。當DMA控制器開始訪問發出請求的外設時,DMA控制器立即發送給它一個應答信號。當從DMA控制器得到應答信號時,外設立即釋放它的請求。一旦外設釋放了這個請求,DMA控制器同時撤銷應答信號。DMA傳輸結束,如果有更多的請求時,外設可以啟動下一個周期。

總之,每次DMA傳送由3個操作組成:

  • 從外設數據寄存器或者從當前外設/存儲器地址寄存器指示的存儲器地址取數據,第一次傳輸時的開始地址是DMA_CPARx或DMA_CMARx寄存器指定的外設基地址或存儲器單元;
  • 存數據到外設數據寄存器或者當前外設/存儲器地址寄存器指示的存儲器地址,第一次傳輸時的開始地址是DMA_CPARx或DMA_CMARx寄存器指定的外設基地址或存儲器單元;
  • 執行一次DMA_CNDTRx寄存器的遞減操作,該寄存器包含未完成的操作數目
DMA傳輸方式

方法1:DMA_Mode_Normal正常模式,

當一次DMA數據傳輸完后,停止DMA傳送 ,也就是只傳輸一次    方法2:DMA_Mode_Circular?,循環傳輸模式

當傳輸結束時,硬件自動會將傳輸數據量寄存器進行重裝,進行下一輪的數據傳輸。也就是多次傳輸模式

仲裁器

仲裁器的作用是確定各個DMA傳輸的優先級

仲裁器根據通道請求的優先級來啟動外設/存儲器的訪問。

優先權管理分2個階段:

軟件:每個通道的優先權可以在DMA_CCRx寄存器中設置,有4個等級

  • 最高優先級
  • 高優先級
  • 中等優先級
  • 低優先級;

硬件:如果2個請求有相同的軟件優先級,則較低編號的通道比較高編號的通道有較高的優先權。比如:如果軟件優先級相同,通道2優先于通道4。

注意:在大容量產品和互聯型產品中,DMA1控制器擁有高于DMA2控制器的優先級。

DMA數據流(僅存在于STM32F4 /M4 內核上)

在設置了DMA的通道之后,還要選擇通道對應外設的數據流

8 個 DMA 控制器數據流都能夠提供源和目標之間的單向傳輸鏈路。每個數據流配置后都可以執行:● 常規類型事務:存儲器到外設、外設到存儲器或存儲器到存儲器的傳輸。● 雙緩沖區類型事務:使用存儲器的兩個存儲器指針的雙緩沖區傳輸(當 DMA 正在進行自/至緩沖區的讀/寫操作時,應用程序可以進行至/自其它緩沖區的寫/讀操作)。要傳輸的數據量(多達 65535)可以編程,并與連接到外設 AHB 端口的外設(請求 DMA 傳輸)的源寬度相關。每個事務完成后,包含要傳輸的數據項總量的寄存器都會遞減。

DMA_SxCR 寄存器控制數據流到底使用哪一個通道,每個數據流有 8 個通道可 供選擇,每次只能選擇其中一個通道進行 DMA 傳輸。接下來,我們看看 DMA2 的各數據流通 道映射表,如表 28.1.1 所示

DMA 傳輸通道

每個通道都可以在有固定地址的外設寄存器和存儲器地址之間執行DMA傳輸。DMA傳輸的數據 量是可編程的,大達到65535。包含要傳輸的數據項數量的寄存器,在每次傳輸后遞減。

可編程的數據量:外設和存儲器的傳輸數據量可以通過DMA_CCRx寄存器中的PSIZE和MSIZE位編程。

指針遞增模式

根據 DMA_SxCR 寄存器中 PINC 和 MINC 位的狀態,外設和存儲器指針在每次傳輸后可以自動向后遞增或保持常量。當設置為增量模式時,下一個要傳輸的地址將是前一個地址加上增量值

通過單個寄存器訪問外設源或目標數據時,禁止遞增模式十分有用。

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

存儲器到存儲器模式

DMA通道的操作可以在沒有外設請求的情況下進行,這種操作就是存儲器到存儲器模式。

當設置了DMA_CCRx寄存器中的MEM2MEM位之后,在軟件設置了DMA_CCRx寄存器中的EN位啟動DMA通道時,DMA傳輸將馬上開始。當DMA_CNDTRx寄存器變為0時,DMA傳輸結束。存儲器到存儲器模式不能與循環模式同時使用。

這里要注意僅 DMA2 的外設接口可以訪問存儲器,所以僅 DMA2 控制器支持存儲器到存儲器的傳輸,DMA1 不支持。

存儲器到存儲器模式不能與循環模式同時使用。

DMA中斷

每個DMA通道都可以在DMA傳輸過半、傳輸完成和傳輸錯誤時產生中斷。為應用的靈活性考慮,通過設置寄存器的不同位來打開這些中斷。

使沒開啟,我們也可以通過查詢這些位來獲得當前 DMA 傳輸的狀態。這里我們常用的是 TCIFx位,即數據流 x 的 DMA 傳輸完成與否標志。

可編程的數據傳輸寬度、對齊方式和數據大小端 當PSIZE和MSIZE不相同時,DMA模塊按照下圖進行數據對齊。

注意:在大容量產品中, DMA2 通道 4 和 DMA2 通道 5 的中斷被映射在同一個中斷向量上。在互聯型產品 中, DMA2 通道 4 和 DMA2 通道 5 的中斷分別有獨立的中斷向量。所有其他的 DMA 通道都有自己的 中斷向量

DMA的內存占用

在STM32控制器中,芯片采用Cortex-MX架構,總線結構有了很大的優化,DMA占用另外的地址總線,并不會與CPU的系統總線發生沖突。也就是說,DMA的使用不會影響CPU的運行速度

但是要注意:DMA 控制器和Cortex-M3核共享系統數據總線執行直接存儲器數據傳輸。當CPU和DMA同時訪問相同的目標(RAM或外設)時,DMA請求可能會停止 CPU訪問系統總線達若干個周期,總線仲裁器執行循環調度,以保證CPU至少可以得到一半的系統總線(存儲器或外設)帶寬。

DMA配置部分

此部分我們分為DMA寄存器和DMA庫函數分別介紹:

DMA寄存器

DMA配置參數包括:通道地址、優先級、數據傳輸方向、存儲器/外設數據寬度、存儲器/外設地址是否增量、循環模式、數據傳輸量。

DMA中斷狀態寄存器(DMA_ISR)

我們如果開啟了 DMA_ISR 中這些中斷,在達到條件后就會跳到中斷服務函數里面去,即使 沒開啟,我們也可以通過查詢這些位來獲得當前 DMA 傳輸的狀態。這里我們常用的是 TCIFx, 即通道 DMA 傳輸完成與否的標志。

注意此寄存器為只讀寄存器,所以在這些位被置位之后,只 能通過其他的操作來清除。

DMA中斷標志清除寄存器(DMA_IFCR)

DMA_IFCR 的各位就是用來清除 DMA_ISR 的對應位的,通過寫 0 清除。在 DMA_ISR 被置位后, 我們必須通過向該位寄存器對應的位寫入 0 來清除。

DMA通道x配置寄存器(DMA_CCRx)

該寄存器控制著 DMA 的很多相關 信息,包括數據寬度、外設及存儲器的寬度、通道優先級、增量模式、傳輸方向、中斷允許、 使能等都是通過該寄存器來設置的。所以 DMA_CCRx 是 DMA 傳輸的核心控制寄存器

DMA通道x傳輸數量寄存器(DMA_CNDTRx)(x = 1…7)

這個寄存器控制 DMA 通道 x 的每次 傳輸所要傳輸的數據量。其設置范圍為 0~65535。并且該寄存器的值會隨著傳輸的進行而減少, 當該寄存器的值為 0 的時候就代表此次數據傳輸已經全部發送完成了。所以可以通過這個寄存 器的值來知道當前 DMA 傳輸的進度

DMA通道x外設地址寄存器(DMA_CPARx)(x = 1…7)

該寄存器用來存儲 STM32 外設的地 址,比如我們使用串口 1,那么該寄存器必須寫入 0x40013804(其實就是&USART1_DR)。如果使 用其他外設,就修改成相應外設的地址就行了。

DMA通道x配置寄存器(DMA_CMARx)

,該寄存器和 DMA_CPARx 差不多, 但是是用來放存儲器的地址的。比如我們使用 SendBuf[5200]數組來做存儲器,那么我們在 DMA_CMARx 中寫入&SendBuff 就可以了。

DMA寄存器配置流程

通道配置過程 下面是配置DMA通道x的過程(x代表通道號):

  1. 在DMA_CPARx寄存器中設置外設寄存器的地址。發生外設數據傳輸請求時,這個地址將 是數據傳輸的源或目標。
  2. 在DMA_CMARx寄存器中設置數據存儲器的地址。發生外設數據傳輸請求時,傳輸的數 據將從這個地址讀出或寫入這個地址。
  3. 在DMA_CNDTRx寄存器中設置要傳輸的數據量。在每個數據傳輸后,這個數值遞減。
  4. 在DMA_CCRx寄存器的PL[1:0]位中設置通道的優先級。
  5. 在DMA_CCRx寄存器中設置數據傳輸的方向、循環模式、外設和存儲器的增量模式、外 設和存儲器的數據寬度、傳輸一半產生中斷或傳輸完成產生中斷。
  6. 設置DMA_CCRx寄存器的ENABLE位,啟動該通道。

一旦啟動了DMA通道,它既可響應連到該通道上的外設的DMA請求。當傳輸一半的數據后,半傳輸標志(HTIF)被置1,當設置了允許半傳輸中斷位(HTIE)時,將產生 一個中斷請求。在數據傳輸結束后,傳輸完成標志(TCIF)被置1,當設置了允許傳輸完成中斷位 (TCIE)時,將產生一個中斷請求。

DMA庫函數

1.DMA初始化函數

DMA_DeInit(DMAX_ChannelX);

功能:將DMAyChannelx寄存器的初始化為其默認值

注釋:RCC_ResetCmd中對DMA無定義,因此采用的直接操縱DMA寄存器的方式

void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx,  DMA_InitTypeDef* DMA_InitStruct)

功能:設置要開啟的通道,還有一些參數,包括外設基地址,存儲器基地址,傳輸的數據量,增量模式,數據寬度等。

具體看下方結構體代碼介紹:

typedef struct {  uint32_t DMA_PeripheralBaseAddr;   /*設置DMA源地址*/uint32_t DMA_MemoryBaseAddr;       /*設置DMA目的地址*/uint32_t DMA_DIR; /* 設置數據傳輸方向,決定是從外設讀取數據到內存還送從內存讀取數 據發送到外設,也就是外設是源地還是目的地*/                       uint32_t DMA_BufferSize;      /*設置傳輸大小*/    uint32_t DMA_PeripheralInc;       /*設置ReceiveBuff地址是否自增*/      uint32_t DMA_MemoryInc; /*設置傳輸數據時候內存地址是否遞,需要開啟*/       uint32_t DMA_PeripheralDataSize;   /*外設的數據長度是為字節傳輸(8bits),半 字傳輸(16bits) 還是字傳輸(32bits) */    uint32_t DMA_MemoryDataSize;    /*設置內存的數據長度*/uint32_t DMA_Mode;      /*設置DMA的模式,正常模式/循環模式  是否循環發送*/        uint32_t DMA_Priority; /*設置 DMA 通道的優先級,有低,中,高,超高四種模式*/        uint32_t DMA_M2M;    /*設置是否是存儲器到存儲器模式傳輸,*/       }DMA_InitTypeDef;

2.DMA使能函數

void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx, FunctionalState  NewState);

功能:使能或者失能DMA外設

例如:DMA_Cmd(DMA1_Channel1 , ENABLE);  3.DMA中斷使能函數

void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT,  FunctionalState NewState);
1

功能:配置指定的DMAy通道x的中斷

注釋:DMA_IT_TC:傳輸完成 DMA_IT_HT:傳輸一半 DMA_IT_TE:傳輸錯誤

例如:DMA_ITConfig(DMA1_Channel1 , DMA_IT_TC , ENABLE);

4.設置CNDTRx和讀CNDTRx函數 (通道傳輸數據量)

void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t  DataNumber);uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx);
12

作用:前者設置DMA通道的傳輸數據量(DMA處于關閉狀態);后者獲取當前DMA通道傳輸剩余數據量(DMA處于開啟狀態)。

DMA庫函數配置過程:
  • 使能DMA時鐘:RCC_AHBPeriphClockCmd();
  • 初始化DMA通道:DMA_Init();
  • //設置通道;傳輸地址;傳輸方向;傳輸數據的數目;傳輸數據寬度;傳輸模式;優先級;是否開啟存儲器到存儲器。
  • 使能外設DMA
  • 以串口為例:使能串口DMA發送,串口DMA使能函數。調用函數:USART_DMACmd();
  • 使能DMA通道傳輸;函數:DMA_Cmd();
  • 查詢DMA傳輸狀態。函數:DMA_GetFlagStatus();
  • 獲取當前剩余數據量大小 函數:DMA_GetCurrDataCounter(DMA1_Channel4);
UART DMA傳輸

DMA就是一個搬運工,可以將數據從一個位置搬運到另一個位置。以UART為例,如果要接收數據,會觸發UART中斷,然后CPU介入,在中斷中通過CPU將UART輸入寄存器的值讀出來,存放到內存中;而DMA方式,產生UART中斷后,DMA直接參與,把UART輸入寄存器的值搬運到內存中,CPU只需要在去檢查內存的值就好了,這樣提高了CPU的效率。

DMA代碼配置

① DMA初始化配置

void dma_init()
{DMA_InitTypeDef DMA_InitStructure;RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);/*DMA配置*/DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_Base;//串口數據寄存器地址DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SendBuff; //內存地址(要傳輸的變量的指針)DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //方向(從內存到外設)DMA_InitStructure.DMA_BufferSize = 500; //傳輸內容的大小DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外設地址不增DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //內存地址自增DMA_InitStructure.DMA_PeripheralDataSize =DMA_PeripheralDataSize_Byte ; //外設數據單位DMA_InitStructure.DMA_MemoryDataSize =DMA_MemoryDataSize_Byte ; //內存數據單位DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ; //DMA模式:一次傳輸,循環DMA_InitStructure.DMA_Priority = DMA_Priority_Medium ; //優先級:高DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //禁止內存到內存的傳輸DMA_Init(DMA1_Channel4, &DMA_InitStructure); //配置DMA1的4通道DMA_Cmd(DMA1_Channel4,ENABLE);DMA_SetCurrDataCounter(DMA_CH4,DMA1_MEM_LEN);//DMA通道的DMA緩存的大小DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);//配置DMA發送完成后產生中斷}

DMA中斷

void DMA1_Channel4_IRQHandler(void)
{if(DMA_GetFlagStatus(DMA1_FLAG_TC4)==SET){DMA_ClearFlag(DMA1_FLAG_TC4);}
}

main函數

#define SEND_BUF_SIZE 500 //發送數據長度,最好等于sizeof(TEXT_TO_SEND)+2的整數倍.u8 SendBuff[SEND_BUF_SIZE]; //發送數據緩沖區
const u8 TEXT_TO_SEND[]={"STM32F1 DMA 串口實驗"};uint16_t i;
int main(void)
{    uart_init(115200);   //串口初始化為115200for(i=0;i<500;i++){SendBuff[i] =0xaf;} USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);  //使能串口dma傳輸 while(1);
}

二、STM32中的DMA原理

DMA的基本介紹

什么是DMA (DMA的基本定義)

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

??? DMA傳輸將數據從一個地址空間復制到另一個地址空間,提供在外設和存儲器之間或者存儲器和存儲器之間的高速數據傳輸。

????我們知道CPU有轉移數據、計算、控制程序轉移等很多功能,系統運作的核心就是CPU,CPU無時不刻的在處理著大量的事務,但有些事情卻沒有那么重要,比方說數據的復制和存儲數據,如果我們把這部分的CPU資源拿出來,讓CPU去處理其他的復雜計算事務,是不是能夠更好的利用CPU的資源呢?

????因此:轉移數據(尤其是轉移大量數據)是可以不需要CPU參與。比如希望外設A的數據拷貝到外設B,只要給兩種外設提供一條數據通路,直接讓數據由A拷貝到B 不經過CPU的處理。

??? DMA就是基于以上設想設計的,它的作用就是解決大量數據轉移過度消耗CPU資源的問題。有了DMA使CPU更專注于更加實用的操作–計算、控制等。

DMA定義:

??? DMA用來提供在外設和存儲器之間或者存儲器和存儲器之間的高速數據傳輸。無須CPU的干預,通過DMA數據可以快速地移動。這就節省了CPU的資源來做其他操作。

DMA傳輸方式

??? DMA的作用就是實現數據的直接傳輸,而去掉了傳統數據傳輸需要CPU寄存器參與的環節,主要涉及四種情況的數據傳輸,但本質上是一樣的,都是從內存的某一區域傳輸到內存的另一區域(外設的數據寄存器本質上就是內存的一個存儲單元)。四種情況的數據傳輸如下:

  • 外設到內存
  • 內存到外設
  • 內存到內存
  • 外設到外設

DMA傳輸參數

????我們知道,數據傳輸,首先需要的是1 數據的源地址 2 數據傳輸位置的目標地址 ,3 傳遞數據多少的數據傳輸量 ,4 進行多少次傳輸的傳輸模式 DMA所需要的核心參數,便是這四個。

????當用戶將參數設置好,主要涉及源地址、目標地址、傳輸數據量這三個,DMA控制器就會啟動數據傳輸,當剩余傳輸數據量為0時 達到傳輸終點,結束DMA傳輸 ,當然,DMA 還有循環傳輸模式 當到達傳輸終點時會重新啟動DMA傳輸。

????也就是說只要剩余傳輸數據量不是0,而且DMA是啟動狀態,那么就會發生數據傳輸。  

DMA的主要特征

????每個通道都直接連接專用的硬件DMA請求,每個通道都同樣支持軟件觸發。這些功能通過軟件來配置。

  • 在同一個DMA模塊上,多個請求間的優先權可以通過軟件編程設置(共有四級:很高、高、中等和低),優先權設置相等時由硬件決定(請求0優先于請求1,依此類推);
  • 獨立數據源和目標數據區的傳輸寬度(字節、半字、全字),模擬打包和拆包的過程。源和目標地址必須按數據傳輸寬度對齊;
  • 支持循環的緩沖器管理;
  • 每個通道都有3個事件標志(DMA半傳輸、DMA傳輸完成和DMA傳輸出錯),這3個事件標志邏輯或成為一個單獨的中斷請求;
  • 存儲器和存儲器間的傳輸、外設和存儲器、存儲器和外設之間的傳輸;
  • 閃存、SRAM、外設的SRAM、APB1、APB2和AHB外設均可作為訪問的源和目標;
  • 可編程的數據傳輸數目:最大為65535。

STM32少個DMA資源?

????對于大容量的STM32芯片有2個DMA控制器 兩個DMA控制器,DMA1有7個通道,DMA2有5個通道。

????每個通道都可以配置一些外設的地址。

①DMA1 controller

????從外設(TIMx[x=1、2、3、4]、ADC1、SPI1、SPI/I2S2、I2Cx[x=1、2]和USARTx[x=1、2、3])產生的7個DMA請求,通過邏輯或輸入到DMA1控制器 其中每個通道都對應著具體的外設:

② DMA2 controller

????從外設(TIMx[5、6、7、8]、ADC3、SPI/I2S3、UART4、DAC通道1、2和SDIO)產生的5個請求,經邏輯或輸入到DMA2控制器,其中每個通道都對應著具體的外設:

????這些在下方系統框圖中也可以清晰地看到。

DMA工作系統框圖

????上方的框圖,我們可以看到STM32內核,存儲器,外設及DMA的連接,這些硬件最終通過各種各樣的線連接到總線矩陣中,硬件結構之間的數據轉移都經過總線矩陣的協調,使各個外設和諧的使用總線來傳輸數據。

????我們對他來進行一點一點的分析:

????下面看有與沒有DMA的情況下,ADC采集的數據是怎樣存放到SRAM中的?

沒有DMA

??? 1.如果沒有DMA,CPU傳輸數據還要以內核作為中轉站,比如要將ADC采集的數據轉移到到SRAM中,這個過程是這樣的:

????內核通過DCode經過總線矩陣協調,從獲取AHB存儲的外設ADC采集的數據,

????然后內核再通過DCode經過總線矩陣協調把數據存放到內存SRAM中。

有DMA傳輸

????有DMA的話:

  • DMA傳輸時外設對DMA控制器發出請求。
  • DMA控制器收到請求,觸發DMA工作。
  • DMA控制器從AHB外設獲取ADC采集的數據,存儲到DMA通道中
  • DMA控制器的DMA總線與總線矩陣協調,使用AHB把外設ADC采集的數據經由DMA通道存放到SRAM中,這個數據的傳輸過程中,完全不需要內核的參與,也就是不需要CPU的參與。

????我們把上面的步驟專業一點介紹:

????在發生一個事件后,外設向DMA控制器發送一個請求信號。DMA控制器根據通道的優先權處理請求。當DMA控制器開始訪問發出請求的外設時,DMA控制器立即發送給它一個應答信號。當從DMA控制器得到應答信號時,外設立即釋放它的請求。一旦外設釋放了這個請求,DMA控制器同時撤銷應答信號。DMA傳輸結束,如果有更多的請求時,外設可以啟動下一個周期。

????總之,每次DMA傳送由3個操作組成:

  • 從外設數據寄存器或者從當前外設/存儲器地址寄存器指示的存儲器地址取數據,第一次傳輸時的開始地址是DMA_CPARx或DMA_CMARx寄存器指定的外設基地址或存儲器單元;
  • 存數據到外設數據寄存器或者當前外設/存儲器地址寄存器指示的存儲器地址,第一次傳輸時的開始地址是DMA_CPARx或DMA_CMARx寄存器指定的外設基地址或存儲器單元;
  • 執行一次DMA_CNDTRx寄存器的遞減操作,該寄存器包含未完成的操作數目。

DMA傳輸方式

????方法1:DMA_Mode_Normal,正常模式,

????當一次DMA數據傳輸完后,停止DMA傳送 ,也就是只傳輸一次 ????

????方法2:DMA_Mode_Circular ,循環傳輸模式

????當傳輸結束時,硬件自動會將傳輸數據量寄存器進行重裝,進行下一輪的數據傳輸。也就是多次傳輸模式

仲裁器

圖片

????仲裁器的作用是確定各個DMA傳輸的優先級。

????仲裁器根據通道請求的優先級來啟動外設/存儲器的訪問。

????優先權管理分2個階段:

????軟件:每個通道的優先權可以在DMA_CCRx寄存器中設置,有4個等級:

  • 最高優先級
  • 高優先級
  • 中等優先級
  • 低優先級;

????硬件:如果2個請求有相同的軟件優先級,則較低編號的通道比較高編號的通道有較高的優先權。比如:如果軟件優先級相同,通道2優先于通道4。

????注意:在大容量產品和互聯型產品中,DMA1控制器擁有高于DMA2控制器的優先級。

DMA數據流(僅存在于STM32F4 /M4 內核上)

????在設置了DMA的通道之后,還要選擇通道對應外設的數據流。

??? 8 個 DMA 控制器數據流都能夠提供源和目標之間的單向傳輸鏈路。每個數據流配置后都可以執行:

  • 常規類型事務:存儲器到外設、外設到存儲器或存儲器到存儲器的傳輸。
  • 雙緩沖區類型事務:使用存儲器的兩個存儲器指針的雙緩沖區傳輸(當 DMA 正在進行自/至緩沖區的讀/寫操作時,應用程序可以進行至/自其它緩沖區的寫/讀操作)。要傳輸的數據量(多達 65535)可以編程,并與連接到外設 AHB 端口的外設(請求 DMA 傳輸)的源寬度相關。每個事務完成后,包含要傳輸的數據項總量的寄存器都會遞減。

??? DMA_SxCR 寄存器控制數據流到底使用哪一個通道,每個數據流有 8 個通道可供選擇,每次只能選擇其中一個通道進行 DMA 傳輸。接下來,我們看看 DMA2 的各數據流通道映射表,如表 28.1.1 所示:

DMA 傳輸通道

????每個通道都可以在有固定地址的外設寄存器和存儲器地址之間執行DMA傳輸。DMA傳輸的數據 量是可編程的,大達到65535。包含要傳輸的數據項數量的寄存器,在每次傳輸后遞減。

????可編程的數據量:

????外設和存儲器的傳輸數據量可以通過DMA_CCRx寄存器中的PSIZE和MSIZE位編程。

指針遞增模式

????根據 DMA_SxCR 寄存器中 PINC 和 MINC 位的狀態,外設和存儲器指針在每次傳輸后可以自動向后遞增或保持常量。當設置為增量模式時,下一個要傳輸的地址將是前一個地址加上增量值。

????通過單個寄存器訪問外設源或目標數據時,禁止遞增模式十分有用。

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

存儲器到存儲器模式

??? DMA通道的操作可以在沒有外設請求的情況下進行,這種操作就是存儲器到存儲器模式。

????當設置了DMA_CCRx寄存器中的MEM2MEM位之后,在軟件設置了DMA_CCRx寄存器中的EN位啟動DMA通道時,DMA傳輸將馬上開始。當DMA_CNDTRx寄存器變為0時,DMA傳輸結束。存儲器到存儲器模式不能與循環模式同時使用。

????這里要注意僅 DMA2 的外設接口可以訪問存儲器,所以僅 DMA2 控制器支持存儲器到存儲器的傳輸,DMA1 不支持。

????存儲器到存儲器模式不能與循環模式同時使用。

DMA中斷

????每個DMA通道都可以在DMA傳輸過半、傳輸完成和傳輸錯誤時產生中斷。為應用的靈活性考慮,通過設置寄存器的不同位來打開這些中斷。

圖片

????使沒開啟,我們也可以通過查詢這些位來獲得當前 DMA 傳輸的狀態。這里我們常用的是 TCIFx位,即數據流 x 的 DMA 傳輸完成與否標志。

????可編程的數據傳輸寬度、對齊方式和數據大小端。

????當PSIZE和MSIZE不相同時,DMA模塊按照下圖進行數據對齊。

????注意:在大容量產品中, DMA2 通道 4 和 DMA2 通道 5 的中斷被映射在同一個中斷向量上。在互聯型產品 中, DMA2 通道 4 和 DMA2 通道 5 的中斷分別有獨立的中斷向量。所有其他的 DMA 通道都有自己的中斷向量。

DMA的內存占用

????在STM32控制器中,芯片采用Cortex-MX架構,總線結構有了很大的優化,DMA占用另外的地址總線,并不會與CPU的系統總線發生沖突。也就是說,DMA的使用不會影響CPU的運行速度。

????但是要注意:

??? DMA控制器和Cortex-M3核共享系統數據總線執行直接存儲器數據傳輸。當CPU和DMA同時訪問相同的目標(RAM或外設)時,DMA請求可能會停止 CPU訪問系統總線達若干個周期,總線仲裁器執行循環調度,以保證CPU至少可以得到一半的系統總線(存儲器或外設)帶寬。

DMA配置部分

????此部分我們分為DMA寄存器和DMA庫函數分別介紹:

DMA寄存器

??? DMA配置參數包括:通道地址、優先級、數據傳輸方向、存儲器/外設數據寬度、存儲器/外設地址是否增量、循環模式、數據傳輸量。

DMA中斷狀態寄存器(DMA_ISR)

圖片

????我們如果開啟了 DMA_ISR 中這些中斷,在達到條件后就會跳到中斷服務函數里面去,即使 沒開啟,我們也可以通過查詢這些位來獲得當前 DMA 傳輸的狀態。這里我們常用的是 TCIFx, 即通道 DMA 傳輸完成與否的標志。

????注意此寄存器為只讀寄存器,所以在這些位被置位之后,只 能通過其他的操作來清除。

DMA中斷標志清除寄存器(DMA_IFCR)

??? DMA_IFCR 的各位就是用來清除 DMA_ISR 的對應位的,通過寫 0 清除。在 DMA_ISR 被置位后, 我們必須通過向該位寄存器對應的位寫入 0 來清除。

DMA通道x配置寄存器(DMA_CCRx)

圖片

????該寄存器控制著 DMA 的很多相關 信息,包括數據寬度、外設及存儲器的寬度、通道優先級、增量模式、傳輸方向、中斷允許、 使能等都是通過該寄存器來設置的。所以 DMA_CCRx 是 DMA 傳輸的核心控制寄存器。

DMA通道x傳輸數量寄存器(DMA_CNDTRx)(x = 1…7)

圖片

????這個寄存器控制 DMA 通道 x 的每次 傳輸所要傳輸的數據量。其設置范圍為 0~65535。并且該寄存器的值會隨著傳輸的進行而減少, 當該寄存器的值為 0 的時候就代表此次數據傳輸已經全部發送完成了。所以可以通過這個寄存 器的值來知道當前DMA 傳輸的進度。

DMA通道x外設地址寄存器(DMA_CPARx)(x = 1…7)

圖片

????該寄存器用來存儲 STM32 外設的地 址,比如我們使用串口 1,那么該寄存器必須寫入 0x40013804(其實就是&USART1_DR)。如果使 用其他外設,就修改成相應外設的地址就行了。

DMA通道x配置寄存器(DMA_CMARx)

????該寄存器和 DMA_CPARx 差不多, 但是是用來放存儲器的地址的。比如我們使用 SendBuf[5200]數組來做存儲器,那么我們在 DMA_CMARx 中寫入&SendBuff 就可以了。

DMA寄存器配置流程

????通道配置過程 下面是配置DMA通道x的過程(x代表通道號):

  • 在DMA_CPARx寄存器中設置外設寄存器的地址。發生外設數據傳輸請求時,這個地址將 是數據傳輸的源或目標。
  • 在DMA_CMARx寄存器中設置數據存儲器的地址。發生外設數據傳輸請求時,傳輸的數 據將從這個地址讀出或寫入這個地址。
  • 在DMA_CNDTRx寄存器中設置要傳輸的數據量。在每個數據傳輸后,這個數值遞減。
  • 在DMA_CCRx寄存器的PL[1:0]位中設置通道的優先級。
  • 在DMA_CCRx寄存器中設置數據傳輸的方向、循環模式、外設和存儲器的增量模式、外 設和存儲器的數據寬度、傳輸一半產生中斷或傳輸完成產生中斷。
  • 設置DMA_CCRx寄存器的ENABLE位,啟動該通道。

????一旦啟動了DMA通道,它既可響應連到該通道上的外設的DMA請求。當傳輸一半的數據后,半傳輸標志(HTIF)被置1,當設置了允許半傳輸中斷位(HTIE)時,將產生 一個中斷請求。在數據傳輸結束后,傳輸完成標志(TCIF)被置1,當設置了允許傳輸完成中斷位 (TCIE)時,將產生一個中斷請求。

DMA庫函數

1.DMA初始化函數

DMA_DeInit(DMAX_ChannelX);//RCC_ResetCmd中對DMA無定義,因此采用的直接操縱DMA寄存器的方式

????功能:將DMAyChannelx寄存器的初始化為其默認值

void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx,  DMA_InitTypeDef* DMA_InitStruct)

????功能:設置要開啟的通道,還有一些參數,包括外設基地址,存儲器基地址,傳輸的數據量,增量模式,數據寬度等。

????具體看下方結構體代碼介紹:

2.DMA使能函數

void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx, FunctionalState  NewState);

????功能:使能或者失能DMA外設

????例如:DMA_Cmd(DMA1_Channel1 , ENABLE);

3.DMA中斷使能函數

void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT,  FunctionalState NewState);
//DMA_IT_TC:傳輸完成 DMA_IT_HT:傳輸一半 DMA_IT_TE:傳輸錯誤

????功能:配置指定的DMAy通道x的中斷

????例如:DMA_ITConfig(DMA1_Channel1 , DMA_IT_TC , ENABLE);

4.設置CNDTRx和讀CNDTRx函數 (通道傳輸數據量)

void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t  DataNumber);
uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx);

????作用:前者設置DMA通道的傳輸數據量(DMA處于關閉狀態);后者獲取當前DMA通道傳輸剩余數據量(DMA處于開啟狀態)。

DMA庫函數配置過程:

  • 使能DMA時鐘:RCC_AHBPeriphClockCmd();
  • 初始化DMA通道:DMA_Init();
    //設置通道;傳輸地址;傳輸方向;傳輸數據的數目;傳輸數據寬度;傳輸模式;優先級;是否開啟存儲器到存儲器。
  • 使能外設DMA;
    以串口為例:使能串口DMA發送,串口DMA使能函數。調用函數:USART_DMACmd();
  • 使能DMA通道傳輸;函數:DMA_Cmd();
  • 查詢DMA傳輸狀態。函數:DMA_GetFlagStatus();
  • 獲取當前剩余數據量大小 函數:DMA_GetCurrDataCounter(DMA1_Channel4);

UART DMA傳輸

??? DMA就是一個搬運工,可以將數據從一個位置搬運到另一個位置。

????以UART為例,如果要接收數據,會觸發UART中斷,然后CPU介入,在中斷中通過CPU將UART輸入寄存器的值讀出來,存放到內存中;

????而DMA方式,產生UART中斷后,DMA直接參與,把UART輸入寄存器的值搬運到內存中,CPU只需要在去檢查內存的值就好了,這樣提高了CPU的效率。

DMA代碼配置

DMA初始化配置

void dma_init()
{DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);/*DMA配置*/DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_Base;//串口數據寄存器地址
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SendBuff; //內存地址(要傳輸的變量的指針)
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //方向(從內存到外設)
DMA_InitStructure.DMA_BufferSize = 500; //傳輸內容的大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外設地址不增
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //內存地址自增
DMA_InitStructure.DMA_PeripheralDataSize =
DMA_PeripheralDataSize_Byte ; //外設數據單位
DMA_InitStructure.DMA_MemoryDataSize =
DMA_MemoryDataSize_Byte ; //內存數據單位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ; //DMA模式:一次傳輸,循環
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium ; //優先級:高
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //禁止內存到內存的傳輸DMA_Init(DMA1_Channel4, &DMA_InitStructure); //配置DMA1的4通道
DMA_Cmd(DMA1_Channel4,ENABLE);
DMA_SetCurrDataCounter(DMA_CH4,DMA1_MEM_LEN);//DMA通道的DMA緩存的大小
DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);//配置DMA發送完成后產生中斷}

DMA中斷

void DMA1_Channel4_IRQHandler(void)
{if(DMA_GetFlagStatus(DMA1_FLAG_TC4)==SET){DMA_ClearFlag(DMA1_FLAG_TC4);}
}

main函數

#define SEND_BUF_SIZE 500  //發送數據長度,最好等于sizeof(TEXT_TO_SEND)+2的整數倍.u8 SendBuff[SEND_BUF_SIZE];  //發送數據緩沖區
const u8 TEXT_TO_SEND[]={"STM32F1 DMA 串口實驗"};uint16_t i;
int main(void)
{     uart_init(115200);     //串口初始化為115200for(i=0;i<500;i++){SendBuff[i] =0xaf;}  USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);  //使能串口dma傳輸 while(1);
}

三、xx

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/79932.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/79932.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/79932.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux隨記(十七)

一、綜合報錯&#xff1a;fork: Cannot allocatte memory 和 modues is unknwon 和 pam_limits(crond:session) : unknwon limit item ‘noproc’ 1.1 fork: Cannot allocatte memory 處理 - 隨記 排查時間2025年4月。 環境描述&#xff1a; 2014年左右的服務器&#xff0c;…

支持mingw g++14.2 的c++23 功能print的vscode tasks.json生成調試

在mingw14.2版本中, print庫的功能默認沒有開啟, 生成可執行文件的tasks.json里要顯式加-lstdcexp, 注意放置順序. tasks.json (支持mingw g14.2 c23的print ) {"version": "2.0.0","tasks": [{"type": "cppbuild","…

賦能能源 | 智慧數據,構建更高效智能的儲能管理系統

行業背景 隨著新能源產業的快速發展&#xff0c;大規模儲能系統在電力調峰、調頻及可再生能源消納等領域的重要性日益凸顯。 儲能電站作為核心基礎設施&#xff0c;其能量管理系統&#xff08;EMS&#xff09;需要處理海量實時數據&#xff0c;包括電池狀態、功率變化、環境監…

使用 Flutter 遇坑小計

前言 首先, 谷哥很貼心地為國內用戶準備了一份使用手冊 不過很遺憾 就算你照著它的手冊來了, 還是會在后續使用中遇到其它的坑 今天我踩了, 保不齊明天就是其他人(lol) running gradle task ‘assembledebug’ stuck 首先去確定下當下Android Studio(或者說你目前的Flutter項…

鏈表與文件

鏈表 單鏈表 1.鏈表的初始化 typedef struct node {char name[100];int number;struct node *next; }Node,*LinkList;}Node;2.鏈表的初始化函數(Initlist) LinkList InitList() {LinkList head;head(Node*)malloc(sizeof(Node));head->nextNULL;return head; }3.建立鏈…

uniapp打ios包

uniapp在windows電腦下申請證書并打包上架 前言 該開發筆記記錄了在window系統下&#xff0c;在蘋果開發者網站生成不同證書&#xff0c;進行uniapp打包調試和上線發布&#xff0c;對window用戶友好 注&#xff1a;蘋果打包涉及到兩種證書&#xff1a;開發證書 和 分發證書 …

OpenCV 圖形API(48)顏色空間轉換-----將 LUV 顏色空間的圖像數據轉換為 BGR 顏色空間函數LUV2BGR()

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 將圖像從LUV顏色空間轉換為BGR顏色空間。 該函數將輸入圖像從LUV顏色空間轉換為BGR。B、G和R通道值的常規范圍是0到255。 輸出圖像必須是8位無符…

HOW MUCH POSITION INFORMATION DO CONVOLUTIONAL NEURAL NETWORKS ENCODE?

1. 動機: 卷積神經網絡中的卷積操作實際上是一個局部的操作,這樣的話就會使得它雖然知道自己看的是什么,但是卻不清楚他在圖像中的位置信息,但是位置信息實際上是很有用的,因此CNN可能潛在的學習到了如何去編碼這種位置信息。所以這篇論文就是為了研究這種位置信息是如何在…

56、如何快速讓?個盒??平垂直居中

在網頁開發中&#xff0c;有多種方式能讓一個盒子實現水平垂直居中。下面為你介紹幾種常見且快速的方法。 1. 使用 Flexbox 布局 Flexbox 是一種非常便捷的布局模型&#xff0c;能夠輕松實現元素的水平和垂直居中。 html <!DOCTYPE html> <html lang"en"&…

RAG應用過程監控系統選型:LangFuse

Langfuse 是一個開源的大語言模型&#xff08;LLM&#xff09;工程平臺&#xff0c;旨在協助團隊構建、調試和改進由人工智能驅動的應用程序。憑借其全面的工具套件&#xff0c;Langfuse 使開發者能夠深入洞察其 LLM 應用程序&#xff0c;并優化性能。 Stars 數10,522Forks 數9…

Java+nanomsg快速實現去broker的數據通信

先說一下nanomsgJava需要做什么&#xff1a; 1、nanomsg的so文件的制作與放置路徑 2、Java代碼引入nanomsg的依賴 3、支持Socket參數的調節&#xff08;包括ipv4/ipv6的網絡支持&#xff09; 在我目前的認知范圍內要與一個通訊目標實現數據交互通常有這些方式 1、broker中間人…

lightgbm原理、特殊點、參數分析

lightgbm&#xff1a; 一、位置&#xff1a; 相比XGB&#xff0c;LGBM有更高效的計算效率和更低的內存占用&#xff0c;并且面對高維數據&#xff0c;LGBM算法擁有更好的過擬合特性&#xff0c;這使得在建模數據量日趨增加的今天&#xff0c;LGBM會更適合作為前期探索性建模的模…

車載軟件架構 --- 二級boot設計說明需求規范

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 周末洗了一個澡,換了一身衣服,出了門卻不知道去哪兒,不知道去找誰,漫無目的走著,大概這就是成年人最深的孤獨吧! 舊人不知我近況,新人不知我過…

Cpp實現window上cmd執行效果

Cpp實現window上cmd執行效果 文章目錄 Cpp實現window上cmd執行效果1.頭文件包含部分2.main 函數部分3. 獲取當前工作目錄部分4.主循環部分5.退出條件部分6.處理 cd 命令部分7.執行其他命令部分8.讀取命令輸出部分9.關閉管道并處理返回碼部分10.源碼 1.頭文件包含部分 #include…

STM32 HAL庫FreeRTOS 中斷管理

一、引言 在嵌入式系統開發中&#xff0c;STM32 微控制器憑借其高性能、低功耗和豐富的外設資源&#xff0c;被廣泛應用于各種領域。FreeRTOS 作為一款輕量級、開源且功能強大的實時操作系統&#xff0c;為多任務處理提供了良好的支持。中斷是嵌入式系統中實現實時響應外部事件…

在 UE5 編輯器中,由于游戲設置 -> EV100 設置,點擊播放前后的光照不同。如何保持點擊播放前后的光照一致?

?In Unreal Engine 5 (UE5), discrepancies in lighting between the editor and play modes are often due to auto exposure settings, particularly when using the EV100 system. To maintain consistent lighting across both modes, follow these steps:?YouTube1Epic …

[python] set

1.添加元素 在 Python 中&#xff0c;向 set 添加一個元素可以使用 add() 方法。如果添加的元素已經存在于 set 中&#xff0c;add() 不會重復添加&#xff08;因為 set 具有自動去重的特性&#xff09;。 方法 1&#xff1a;add(element)&#xff08;添加單個元素&#xff0…

第一期第18講26:23

shell腳本以 .sh為后綴&#xff0c;里面存放著一行行要運行的linux指令。 shell腳本第一行一定為 #!/bin/bash&#xff0c;表示使用bash。 shell文件舉例如下&#xff1a; #!/bin/bash echo "hello shell!" shell文件默認沒有可執行權限&#xff0c;因此 chmod 777 m…

解決 Ubuntu 下 VTune 無法收集 CPU 硬件時間計數數據的問題

解決 Ubuntu 下 VTune 無法收集 CPU 硬件時間計數數據的問題 在 Ubuntu 上使用 Intel VTune Profiler 時遇到無法收集 CPU 硬件性能計數器數據的問題&#xff0c;通常是由于權限和系統配置問題導致的。以下是解決方案&#xff1a; 1. 檢查并加載性能監控模塊 首先確保 Linux…

健康元 以韌性換彈性

拼韌性的時候到了&#xff01; 一面是復雜的市場、政策環境與醫藥行業轉型所疊加形成的向下壓力&#xff1b;一面是AI技術深度賦能醫藥企業創新加速的向上機遇。 中國藥企在經歷了一輪群體性低潮期后&#xff0c;進入“結構性”分化的階段。 在這一階段上&#xff0c;一些財…