一、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。