一、DMA概述
二、DMA通道
注意,想要往串口中寫數據,外部請求信號應該是USARTx_TX,當DR寄存器為空時,產生TX信號,請求DMA。反之,從串口中讀數據,外部請求信號應該是USARTx_RX,當DR寄存器滿時,產生RX信號,請求DMA。
三、DMA處理過程
四、DMA中斷
五、相關寄存器
六、實驗部分
1、實驗要求
使用DMA,將內存中800個字節發送給串口。
2、詳細代碼
①dma.c
#include "dma.h"void MYDMA_Config(DMA_Channel_TypeDef*DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
{//時鐘使能RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);//初始化DMA_DeInit(DMA_CHx);DMA_InitTypeDef DMA_InitStruct;DMA_InitStruct.DMA_BufferSize = cndtr;DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST;DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;DMA_InitStruct.DMA_MemoryBaseAddr =cmar;DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;DMA_InitStruct.DMA_PeripheralBaseAddr = cpar;DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;DMA_InitStruct.DMA_Priority = DMA_Priority_Medium;DMA_Init(DMA1_Channel4, &DMA_InitStruct);
}void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
{DMA_Cmd(DMA_CHx, DISABLE);DMA_SetCurrDataCounter(DMA_CHx,MAXNUM);USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);DMA_Cmd(DMA_CHx, ENABLE);}
②main.c
#include "stm32f10x.h"
#include "rtc.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "wkup.h"
#include "adc.h"
#include "tsensor.h"
#include "lsensor.h"
#include "dac.h"
#include "key.h"
#include "timer.h"
#include "dma.h"
#include "string.h"int main(void){ u16 t = 0;char data[MAXNUM + 1] = {0};char name[] = "我是春春大哥哥\r\n";for(u16 i = 0;i < MAXNUM / strlen(name);i++){strcat(data,name);}delay_init();uart_init(115200);LED_Init();KEY_Init();NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);RTC_Init();LCD_Init(); Adc_Init();MYDMA_Config(DMA1_Channel4,(u32)&(USART1->DR),(u32)data,MAXNUM);LCD_ShowString(60,120,200,24,24," - - ");LCD_ShowString(60,174,200,24,24," : : ");while(1){++t;if(t % 100 == 0){LED0 =! LED0;}u8 key = KEY_Scan(0);if(key == kup_pres){MYDMA_Enable(DMA1_Channel4);}delay_ms(10);}}
3、代碼調試
一定要注意,如果不是循環模式的話,當一次DMA結束后,DMA_BufferSize就會清0,并且該位為0時,DMA不工作。所以,每次使用DMA都要重設該值,并且重設該值之前要DIABLE CMD。