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