第7章
大量資料的快速搬移─DMA
7.1 STM32 DMA簡介
DMA,又稱Direct Memory Access。主要功能為對記憶體坐直接存取的動作而不用透過CPU,透過硬體使得記憶體與I/O設備建立一條直接傳送資料的通道,藉此使CPU的效率大為提高。
使用DMA,對CPU而言有兩個很大的好處:
- 1. 使用DMA,能使CPU的使用效率提升。
- 2. 使用DMA操作記憶體,比使用CPU操作記憶體還要快速。
STM32最多有兩個DMA的控制器,(DMA2僅存在於大容量的產品當中),DMA1有7個通道,每個通道專門用來管理來自於一個或多個外部設備的請求。此外還有一個仲裁器來協調各個DMA請求的優先權。
STM32的DMA有以下的特性:
- 每個通道都直接連接到DMA,每個通道都支援軟體觸發,這些功能透過軟體來設定。
- 在七個請求通知的優先權,須通過軟體進行設定,一共有四級,假如在相等優先權時,則由硬體決定優先權。
- 可獨立設置來源位置與目的位置的資料傳輸寬度(8bits、16bits、32bits),兩邊的資料寬度必須相等。
- 支援Circular buffer
- 每個通道都有三個旗標(DMA半傳輸、DMA傳輸完成、DMA傳輸錯誤)。
- 支援記憶體對記憶體的傳輸
- 支援外部設備對記憶體與記憶體對外部設備的傳輸
- FLASH、SRAM、外部SRAM、APB1APB2和AHB均可當作DMA操作的來源位置或目的位置。
- 可傳輸的最大數目為65535。
而SIOC(STM32F103C8T6)只有一個DMA控制器,DMA1,下面我們就針對DMA1進行介紹。
從外部周邊(TIMx、ADC、SPIx、I2Cx和USARTx)產生的DMA請求,須通過OR邏輯閘輸入至DMA控制器,這表示同時只能有一個外部請求可被執行。
DMA1通道一覽表與DMA Request Mapping:
外部 |
通道1 |
通道2 |
通道3 |
通道4 |
通道5 |
通道6 |
通道7 |
ADC |
ADC1 |
|
|
|
|
|
|
SPI |
|
SPI1_RX |
SPI1_TX |
SPI2_RX |
SPI2_TX |
|
|
USART |
|
USART3_TX |
USART3_RX |
USART1_TX |
USART1_RX |
USART2_RX |
USART2_TX |
I2C |
|
|
|
I2C2_TX |
I2C2_RX |
I2C1_TX |
I2C1_RX |
TIM1 |
|
TIM1_CH1 |
TIM1_CH2 |
TIM1_TX4 TIM1_TRIG TIM1_COM |
TIM1_UP |
TIM1_CH3 |
|
TIM2 |
TIM2_CH3 |
TIM2_UP |
|
|
TIM2_CH1 |
|
TIM2_CH2 TIM2_CH4 |
TIM3 |
|
TIM3_CH3 |
TIM3_CH4 TIM3_UP |
|
|
TIM3_CH1 TIM3_TRIG |
|
TIM4 |
TIM4_CH1 |
|
|
TIM4_CH2 |
TIM4_CH3 |
|
TIM4_UP |
7.2 DMA Registers
本章節將逐一介紹在使用DMA時,會使用到的暫存器
Register |
Description |
ISR |
紀錄DMA 中斷狀態的暫存器 |
IFCR |
計錄DMA 清除中斷的暫存器 |
CCRx |
紀錄DMA Channelx 設定的暫存器 |
CNDTRx |
紀錄DMA Channelx待傳輸資料筆數的暫存器 |
CPARx |
儲存DMA Channelx 周邊記憶體位置的暫存器 |
CMARx |
儲存DMA Channelx 主記憶體位置的暫存器 |
DMA Register Mapping
7.3 DMA Standard Driver Library
本章節將介紹使用者在撰寫程式時,會使用到的函式。
Function name |
Description |
DMA_DeInit |
|
DMA_Init |
初始 DMAy Channelx |
DMA_StructInit |
填入 DMA_InitStruct 參數 |
DMA_Cmd |
Enables or disables the specified DMAy Channelx. |
DMA_ITConfig |
Enables or disables the specified DMAy Channelx interrupts. |
DMA_GetCurrDataCounter |
回傳 DMAy當下的剩餘資料個數 |
DMA_ClearFlag |
清除 DMAy Channelx pending flags. |
DMA_GetITStatus |
確認 DMAy Channelx的中斷旗標有沒有被觸發 |
DMA_ClearITPendingBit |
清除 DMAy Channelx interrupt pending bits. |
DMA_DeInit function
Function name |
DMA_DeInit |
Function prototype |
void DMA_DeInit(DMA_Channel_TypeDef* DMAy_Channelx) |
Behavior description |
Resets the DMAy Channelx registers to their default reset values. |
Input parameter |
DMAy_Channelx: where y selects the DMA (y = 1 for DMA1, y = 2 for DMA2) and x selects the DMA Channel (x = 1 to 7 for DMA1 or x = 1 to5 for DMA2). |
Output parameter |
None |
Return parameter |
None |
Required preconditions |
None |
Called functions |
RCC_AHBPeriphClockCmd(). |
Example:
/* Deinitialize the DMA1 Channel2 */
DMA_DeInit(DMA1_Channel2);
DMA_Init function
Function name |
DMA_Init |
Function prototype |
void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx,DMA_InitTypeDef* DMA_InitStruct) |
Behavior description |
Initializes the DMAy Channelx according to the parameters specified in the DMA_InitStruct. |
Function name |
DMA_Init |
Input parameter1 |
DMAy_Channelx: where y selects the DMA (y = 1 for DMA1, y = 2 for DMA2) and x selects the DMA Channel (x = 1 to 7 for DMA1 or x = 1 to 5 for DMA2). |
Input parameter2 |
DMA_InitStruct: pointer to a DMA_InitTypeDef structure that contains the configuration information for the specified DMAy Channelx. Refer to DMA_InitTypeDef structure for more details on the allowed values for this parameter. |
Output parameter |
None |
Return parameter |
None |
Required preconditions |
None |
Required preconditions |
None |
DMA_InitTypeDef structure
The DMA_InitTypeDef structure is defined in the stm32f10x_dma.h file:
typedef struct
{
u32 DMA_PeripheralBaseAddr;
u32 DMA_MemoryBaseAddr;
u32 DMA_DIR;
u32 DMA_BufferSize;
u32 DMA_PeripheralInc;
u32 DMA_MemoryInc;
u32 DMA_PeripheralDataSize;
u32 DMA_MemoryDataSize;
u32 DMA_Mode;
u32 DMA_Priority;
u32 DMA_M2M;
} DMA_InitTypeDef;
DMA_PeripheralBaseAddr
紀錄DMA周邊記憶體起始位置。
DMA_MemoryBaseAddr
紀錄DMA主記憶體起始位置。
DMA_DIR
設定DMA要將周邊記憶體視為來源端或是目的端。
DMA_DIR |
Description |
DMA_DIR_PeripheralDST |
將周邊視為目的端 |
DMA_DIR_PeripheralSRC |
將周邊視為來源端 |
DMA_BufferSize
此欄位定義DMA傳送的buffer大小,此大小必須想等於DMA_PeripheralDataSize或DMA_MemoryDataSize。
DMA_PeripheralInc
此欄位將設定DMA操作周邊時,是否要啟用累加器。
DMA_PeripheralInc |
Description |
DMA_PeripheralInc_Enable |
Current peripheral register incremented |
DMA_PeripheralInc_Disable |
Current peripheral register unchanged |
DMA_MemoryInc
此欄位將設定DMA操作主記憶體時,是否要啟用累加器。
DMA_MemoryInc |
Description |
DMA_MemoryInc_Enable |
Current memory register incremented |
DMA_MemoryInc_Disable |
Current memory register unchanged |
DMA_PeripheralDataSize
此欄位設定來自周邊的資料寬度。
DMA_PeripheralDataSize |
Description |
DMA_PeripheralDataSize_Byte |
Data width = 8bits |
DMA_PeripheralDataSize_HalfWord |
Data width = 16bits |
DMA_PeripheralDataSize_Word |
Data width = 32bits |
DMA_MemoryDataSize
此欄位設定來自主記憶體的資料寬度。
DMA_MemoryDataSize |
Description |
DMA_MemoryDataSize_Byte |
Data width = 8bits |
DMA_MemoryDataSize_HalfWord |
Data width = 16bits |
DMA_MemoryDataSize_Word |
Data width = 32bits |
DMA_Mode
此欄位設定DMA的運作模式。
DMA_Mode |
Description |
DMA_Mode_Circular |
Circular buffer mode is used |
DMA_Mode_Normal |
Normal buffer mode is used |
在DMA_Mode_Circular模式下,不能使用memory-to-memory轉移。
DMA_Priority
此欄位設定軟體的優先權。
DMA_Priority |
Description |
DMA_Priority_VeryHigh |
DMAy Channelx has a very high priority |
DMA_Priority_High |
DMAy Channelx has a high priority |
DMA_Priority_Medium |
DMAy Channelx has a medium priority |
DMA_Priority_Low |
DMAy Channelx has a low priority |
DMA_M2M
此欄位設定memory-to-memory轉移是否要被啟用。
DMA_M2M |
Description |
DMA_M2M_Enable |
DMAy Channelx configured for memory-to-memory transfer |
DMA_M2M_Enable |
DMAy Channelx not configured for memory-to memory transfer |
Example:
/* Initialize the DMA1 Channel1 according to the DMA_InitStructure members */
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_PeripheralBaseAddr = 0x40005400;
DMA_InitStructure.DMA_MemoryBaseAddr = 0x20000100;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 256;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize =
DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize =
DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
DMA_StructInit function
Function name |
DMA_StructInit |
Function prototype |
Void DMA_StructInit(DMA_InitTypeDef* DMA_InitStruct) |
Behavior description |
Fills each DMA_InitStruct member with its default value. |
Input parameter |
DMA_InitStruct: pointer to the DMA_InitTypeDef structure to be initialized |
Output parameter |
None |
Return parameter |
None |
Required preconditions |
None |
Called functions |
None |
DMA_initStruct default values
Member |
Default value |
DMA_PeripheralBaseAddr |
0 |
DMA_MemoryBaseAddr |
0 |
DMA_DIR |
DMA_DIR_PeripheralSRC |
DMA_BufferSize |
0 |
DMA_PeripheralInc |
DMA_PeripheralInc_Disable |
DMA_MemoryInc |
DMA_MemoryInc_Disable |
DMA_PeripheralDataSize |
DMA_PeripheralDataSize_Byte |
DMA_MemoryDataSize |
DMA_MemoryDataSize_Byte |
DMA_Mode |
DMA_Mode_Normal |
DMA_Priority |
DMA_Priority_Low |
DMA_M2M |
DMA_M2M_Disable |
Example:
/* Initialize a DMA_InitTypeDef structure */
DMA_InitTypeDef DMA_InitStructure;
DMA_StructInit(&DMA_InitStructure);
DMA_Cmd function
Function name |
DMA_Cmd |
Function prototype |
void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx,FunctionalState NewState) |
Behavior description |
Enables or disables the specified DMAy Channelx. |
Input parameter1 |
DMAy_Channelx: where y selects the DMA (y = 1 for DMA1, y = 2 for DMA2) and x selects the DMA Channel (x = 1 to 7 for DMA1 or x = 1 to 5 for DMA2). |
Input parameter2 |
NewState: new state of the DMAy Channelx. This parameter can be: ENABLE or DISABLE |
Output parameter |
None |
Return parameter |
None |
Required preconditions |
None |
Called functions |
None |
Example:
/* Enable DMA1 Channel7 */
DMA_Cmd(DMA1_Channel7, ENABLE);
DMA_ITConfig function
Function name |
DMA_ITConfig |
Function prototype |
void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, u32 DMA_IT, FunctionalState NewState) |
Behavior description |
Enables or disables the specified DMAy Channelx interrupts. |
Input parameter1 |
DMAy_Channelx: where y selects the DMA (y = 1 for DMA1, y = 2 for DMA2) and x selects the DMA Channel (x = 1 to 7 for DMA1 or x = 1 to 5 for DMA2). |
Input parameter2 |
DMA_IT: specifies the DMAy Channelx interrupt sources to be enabled or disabled. More than one interrupt can be selected using the “|” operator.Refer to DMA_IT for more details on the allowed values for this parameter. |
Input parameter3 |
NewState: new state of the specified DMAy Channelx interrupts.This parameter can be: ENABLE or DISABLE. |
Output parameter |
None |
Return parameter |
None |
Required preconditions |
None |
Called functions |
None |
DMA_IT
此函數用來設置DMA的三個中斷
DMA_IT |
Description |
DMA_IT_TC |
Transfer complete interrupt mask |
DMA_IT_HT |
Half transfer interrupt mask |
DMA_IT_TE |
Transfer error interrupt mask |
Example:
/* Enable DMA1 Channel5 complete transfer interrupt */
DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);
DMA_GetCurrDataCounter function
Function name |
DMA_GetCurrDataCounter |
Function prototype |
u16 DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx) |
Behavior description |
Returns the number of remaining data units in the current DMAy Channelx transfer. |
Input parameter |
DMAy_Channelx: where y selects the DMA (y = 1 for DMA1, y = 2 for DMA2) and x selects the DMA Channel (x = 1 to 7 for DMA1 or x = 1 to 5 for DMA2). |
Output parameter |
None |
Return parameter |
The number of remaining data units in the current DMAy Channelx transfer. |
Required preconditions |
None |
Called functions |
None |
Example:
/* Get the number of remaining data units in the current DMA1 Channel2 transfer */
u16 CurrDataCount;
CurrDataCount = DMA_GetCurrDataCounter(DMA1_Channel2);
DMA_GetFlagStatus function
Function name |
DMA_GetFlagStatus |
Function prototype |
FlagStatus DMA_GetFlagStatus(u32 DMA_FLAG) |
Behavior description |
Checks whether the specified DMAy Channelx flag is set or not. |
Input parameter |
DMA_FLAG: specifies the flag to check.Refer to DMA_FLAG for more details on the allowed values for this parameter. |
Output parameter |
None |
Return parameter |
New state of DMA_FLAG (SET or RESET). |
Required preconditions |
None |
Called functions |
None |
DMA_FLAG
DMA_FLAG |
Description |
DMA1_FLAG_GL1 |
DMA1 Channel1 global flag |
DMA1_FLAG_TC1 |
DMA1 Channel1 transfer complete flag |
DMA1_FLAG_HT1 |
DMA1 Channel1 half transfer flag |
DMA1_FLAG_TE1 |
DMA1 Channel1 transfer error flag |
DMA1_FLAG_GL2 |
DMA1 Channel2 global flag |
DMA1_FLAG_TC2 |
DMA1 Channel2 transfer complete flag |
DMA1_FLAG_HT2 |
DMA1 Channel2 half transfer flag |
DMA1_FLAG_TE2 |
DMA1 Channel2 transfer error flag |
DMA1_FLAG_GL3 |
DMA1 Channel3 global flag |
DMA1_FLAG_TC3 |
DMA1 Channel3 transfer complete flag |
DMA1_FLAG_HT3 |
DMA1 Channel3 half transfer flag |
DMA1_FLAG_TE3 |
DMA1 Channel3 transfer error flag |
DMA1_FLAG_GL4 |
DMA1 Channel4 global flag |
DMA1_FLAG_TC4 |
DMA1 Channel4 transfer complete flag |
DMA1_FLAG_HT4 |
DMA1 Channel4 half transfer flag |
DMA1_FLAG_TE4 |
DMA1 Channel4 transfer error flag |
DMA1_FLAG_GL5 |
DMA1 Channel5 global flag |
DMA1_FLAG_TC5 |
DMA1 Channel5 transfer complete flag |
DMA1_FLAG_HT5 |
DMA1 Channel5 half transfer flag |
DMA1_FLAG_TE5 |
DMA1 Channel5 transfer error flag |
DMA1_FLAG_GL6 |
DMA1 Channel6 global flag |
DMA1_FLAG_TC6 |
DMA1 Channel6 transfer complete flag |
DMA1_FLAG_HT6 |
DMA1 Channel6 half transfer flag |
DMA1_FLAG_TE6 |
DMA1 Channel6 transfer error flag |
DMA1_FLAG_GL7 |
DMA1 Channel7 global flag |
DMA1_FLAG_TC7 |
DMA1 Channel7 transfer complete flag |
DMA1_FLAG_HT7 |
DMA1 Channel7 half transfer flag |
DMA1_FLAG_TE7 |
DMA1 Channel7 transfer error flag |
Example:
/* Test if the DMA1 Channel6 half transfer interrupt flag is set or not */
FlagStatus Status;
Status = DMA_GetFlagStatus(DMA1_FLAG_HT6);
DMA_ClearFlag function
Function name |
DMA_ClearFlag |
Function prototype |
void DMA_ClearFlag(u32 DMA_FLAG) |
Behavior description |
Clears the DMAy Channelx's pending flags. |
Input parameter |
DMA_FLAG: flag to be cleared. More than one flag can be cleared using the “|” operator. Refer to DMA_FLAG for more details on the allowed values for this parameter. The user can select more than one flag, by ‘ORing’ them. |
Output parameter |
None |
Return parameter |
None |
Required preconditions |
None |
Called functions |
None |
Example:
/* Clear the DMA1 Channel3 transfer error interrupt pending bit */
DMA_ClearFlag(DMA1_FLAG_TE3);
DMA_GetITStatus function
Function name |
DMA_GetITStatus |
Function prototype |
ITStatus DMA_GetITStatus(u32 DMA_IT) |
Behavior description |
Checks whether the specified DMAy Channelx interrupt has occurred or not. |
Input parameter |
DMA_IT: DMAy Channelx interrupt source to check. Refer to DMA_IT for more details on the allowed values for this parameter. |
Output parameter |
None |
Return parameter |
The new state of DMA_IT (SET or RESET). |
Required preconditions |
None |
Called functions |
None |
DMA_IT
DMA_FLAG |
Description |
DMA1_IT_GL1 |
DMA1 Channel1 global interrupt |
DMA1_IT_TC1 |
DMA1 Channel1 transfer complete interrupt |
DMA1_IT_HT1 |
DMA1 Channel1 half transfer interrupt |
DMA1_IT_TE1 |
DMA1 Channel1 transfer error interrupt |
DMA1_IT_GL2 |
DMA1 Channel2 global interrupt |
DMA1_IT_TC2 |
DMA1 Channel2 transfer complete interrupt |
DMA1_IT_HT2 |
DMA1 Channel2 half transfer interrupt |
DMA1_IT_TE2 |
DMA1 Channel2 transfer error interrupt |
DMA1_IT_GL3 |
DMA1 Channel3 global interrupt |
DMA1_IT_TC3 |
DMA1 Channel3 transfer complete interrupt |
DMA1_IT_HT3 |
DMA1 Channel3 half transfer interrupt |
DMA1_IT_TE3 |
DMA1 Channel3 transfer error interrupt |
DMA1_IT_GL4 |
DMA1 Channel4 global interrupt |
DMA1_IT_TC4 |
DMA1 Channel4 transfer complete interrupt |
DMA1_IT_HT4 |
DMA1 Channel4 half transfer interrupt |
DMA1_IT_TE4 |
DMA1 Channel4 transfer error interrupt |
DMA1_IT_GL5 |
DMA1 Channel5 global interrupt |
DMA1_IT_TC5 |
DMA1 Channel5 transfer complete interrupt |
DMA1_IT_HT5 |
DMA1 Channel5 half transfer interrupt |
DMA1_IT_TE5 |
DMA1 Channel5 transfer error interrupt |
DMA1_IT_GL6 |
DMA1 Channel6 global interrupt |
DMA1_IT_TC6 |
DMA1 Channel6 transfer complete interrupt |
DMA1_IT_HT6 |
DMA1 Channel6 half transfer interrupt |
DMA1_IT_TE6 |
DMA1 Channel6 transfer error interrupt |
DMA1_IT_GL7 |
DMA1 Channel7 global interrupt |
DMA1_IT_TC7 |
DMA1 Channel7 transfer complete interrupt |
DMA1_IT_HT7 |
DMA1 Channel7 half transfer interrupt |
DMA1_IT_TE7 |
DMA1 Channel7 transfer error interrupt |
Example:
/* Test if the DMA1 Channel7 transfer complete interrupt has occurred or not */
ITStatus Status;
Status = DMA_GetITStatus(DMA1_IT_TC7);
DMA_ClearITPendingBit function
Function name |
DMA_ClearITPending Bit |
Function prototype |
void DMA_ClearITPendingBit(u32 DMA_IT) |
Behavior description |
Clears the DMAy Channelx’s interrupt pending bits. |
Input parameter |
DMA_IT: DMAy Channelx interrupt pending bit to clear.More than one interrupt can be cleared using the “|” operator. Refer to DMA_IT for more details on the allowed values for this parameter. |
Output parameter |
None |
Return parameter |
None |
Required preconditions |
None |
Called functions |
None |
Example:
/* Clear the DMA1 Channel5 global interrupt pending bit */
DMA_ClearITPendingBit(DMA1_IT_GL5);
7.4 立即演練
實驗1:Polling DMA
實驗說明:利用Polling的方式使用DMA搬移記憶體資料。
Grafcet:
此實驗的重點,就是何謂「Polling」機制?所謂Polling就是輪詢的意思就是指CPU不斷的去檢查、查看。以範例的程式碼為例:
while (1)
{
/* Wait the end of transmission */
printf("\r\nWait the end of transmission...");
while (DMA_GetFlagStatus(DMA1_FLAG_TC6) == RESET);
printf("\r\nDMA1_FLAG_TC6:%d",DMA_GetFlagStatus(DMA1_FLAG_TC6));
printf("\r\nDMA1 Channel6 Received Data:");
/* Check if the transmitted and received data are equal */
Buffercmp(SRC_Const_Buffer, DST_Buffer, BufferSize);
DMA_ClearFlag(DMA1_FLAG_TC6);
}
這段敘述就是一個典型的Polling的例子。DMA1_FLAG_TC6是確認DMA是否已搬完資料的旗標,為RESET時表示尚未搬完;為SET時表示已搬完。當CPU執行這段程式碼,一旦DMA_GetFlagStatus(DMA1_FLAG_TC6) == RESET條件成立,即DMA尚未搬完資料,程式將不斷執行此空迴圈,而CPU也會不斷地去檢查while當中的條件是否成立。
在此實驗當中,雖然CPU並沒有提升使用效率,因為CPU大部分的時間還是花在Polling的動作。但是因為有使用到DMA,在做記憶體存取資料的速度,還是比一般用for迴圈速度還要來的快!
其餘重要的DMA設定部分如:
void RCC_Configuration(void)
{
/* Enable peripheral clocks ------------------------------------------------*/
/* Enable DMA1 clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
}
void DMA_Configuration(void)
{ /* DMA1 channel6 configuration */
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(DMA1_Channel6);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SRC_Const_Buffer;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)DST_Buffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = BufferSize;
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_M2M = DMA_M2M_Enable;
DMA_Init(DMA1_Channel6, &DMA_InitStructure);
}
實驗2:Interrupt DMA
實驗說明:利用Interrupt的方式使用DMA搬移記憶體資料。
Grafcet:
Interrupt機制最大不同於Polling就是,DMA完成工作時,將會主動告知CPU,而CPU就無須用Polling的方式,大大增進了效率。
讀者可以發現,在main.c的程式碼中,不同於上一實驗,已經少了while (DMA_GetFlagStatus(DMA1_FLAG_TC6) == RESET)的敘述,取而代之的是在stm32f10x_it中的void DMA1_Channel6_IRQHandler(void)敘述:
void DMA1_Channel6_IRQHandler(void)
{
/* Test on DMA1 Channel6 Transfer Complete interrupt */
if(DMA_GetITStatus(DMA1_IT_TC6))
{
printf("\r\nDMA1_FLAG_TC6:%d",DMA_GetFlagStatus(DMA1_FLAG_TC6));
DMA_ClearITPendingBit(DMA1_IT_TC6);
printf("\r\n DMA1 Channel6 Interrupt Received data:");
Buffercmp(SRC_Const_Buffer, DST_Buffer, BufferSize);
}
}
此敘述就是在描述當DMA的工作完成,即啟動Interrupt通知CPU。
開啟Interrupt設定部分如:
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_SetVectorTable(0x08003000,0x0);
/* Enable DMA1 channel6 IRQ Channel */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel6_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
留言列表