開發平臺
- 野火開發板F429
- 標準庫
DMA(直接存儲區訪問)
- DMA可以數據的高效傳輸,數據移動過程無需經過任何CPU的操作和控制。
- F4支持:存儲器到存儲器、存儲器到外設、外設到存儲器
- F4有兩個DMA控制器:DMA1和DMA2,只有DMA2才支持存儲器到存儲器
DMA架構
- 1、外設通道選擇(每個數據流的每個通道有對應的外設,不過有一些是沒有的)
- 2、數據流的選擇
- 3、仲裁器,當有個多個外設同時請求一個DMA控制器時,這時就要分先後了,仲裁器的作用就在這裏了。所以要設置優先級(較高優先級、高優先級、中優先級、低優先級),若優先級相等時,就看數據流序號,序號越小優先級越高
- 4、FIFO:DMA傳輸分爲直接模式(當DMA使能後直接傳輸數據)、FIFO模式(當閾值滿後,才一次過傳輸)就有了突發傳輸
- 存儲器端口
- 外設端口
寄存器
看手冊
- 前面四個就是中斷標誌位以及清除中斷標誌位
- 數據流配置寄存器(SxCR),配置通道、優先級、存儲器數據寬度、外設數據寬度等等
- 外設地址寄存器(SxPAR),外設的數據地址或者存儲器的目標地址
- 存儲器0地址寄存器/存儲器1地址寄存器,存儲器源地址,存儲器1地址寄存器只用於雙緩衝區模式
- FIFO控制寄存器:使能失能直接模式、設置FIFO閾值
- 數據項數寄存器(SxNDTR),可以讀取該寄存器,得知數據傳輸到哪
存儲器到外設
1.配置DMA參數即可
- DMA_GetCmdStatus(),只有當數據傳輸完成後纔會被有效禁用,表示數據傳輸完成
代碼如下:
void DMA_MTP_Config(void)
{
DMA_InitTypeDef DMA_InitStruct;
/*打開時鐘*/
RCC_AHB1PeriphClockCmd(DMA2_CLOCK,ENABLE);
/*復位初始化DMA數據流*/
DMA_DeInit(DMA_USART_STREAM);
while(DMA_GetCmdStatus(DMA_USART_STREAM)==ENABLE);
/*
**通道7
**方向 寄存器到外設
**DMA寄存器數據寬度:字節(8位)
**DMA外設寬度:字節(8位)
**fifo模式不開
**寄存器地址:發送數據的首地址
**外設地址:數據寄存器地址
**寄存器:單次傳輸
**外設:單次傳輸
**寄存器地址自動遞增
**外設地址:不需要
**循環模式
**優先級爲高
*/
DMA_InitStruct.DMA_Channel=DMA_USART_CHANNLE;
DMA_InitStruct.DMA_DIR=DMA_DIR_MemoryToPeripheral;
DMA_InitStruct.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
DMA_InitStruct.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
DMA_InitStruct.DMA_BufferSize=BUFFER_SIZE;
DMA_InitStruct.DMA_FIFOMode=DMA_FIFOMode_Disable;
DMA_InitStruct.DMA_FIFOThreshold=DMA_FIFOThreshold_Full;
DMA_InitStruct.DMA_Memory0BaseAddr=(u32)senddata;
DMA_InitStruct.DMA_PeripheralBaseAddr=USART_DR_BASE;
DMA_InitStruct.DMA_MemoryBurst=DMA_MemoryBurst_Single;
DMA_InitStruct.DMA_PeripheralBurst=DMA_PeripheralBurst_Single;
DMA_InitStruct.DMA_MemoryInc=DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_Mode=DMA_Mode_Circular;
DMA_InitStruct.DMA_Priority=DMA_Priority_High;
DMA_Init(DMA_USART_STREAM,&DMA_InitStruct);
DMA_Cmd(DMA_USART_STREAM,ENABLE);
while(DMA_GetCmdStatus(DMA_USART_STREAM)==DISABLE);
}