STM32 DMA

DMA介绍

  1. DMA直接存储器存取
  2. 储存器可以是SRAM或者FLASH
  3. 一共有两个DMA DMA1和DMA2 DMA2只存在于大容量的单片机中
  4. DMA的一个通道在同一时间一般只允许一个外设进行数据的传输

DMA的使用

1.DMA进行串口数据的搬运

在这里插入图片描述
上面的表格阐述了DMA1的通道的使用
对串口进行数据的传输,需要使用的是DMA的通道四和通道五

首先进行初始化DMA的操作
设置宏定义

#define DMA_CHANNEL4       DMA1_Channel4
#define DMA_CHANNEL5       DMA1_Channel5   //表示的是DMA1的5通道  
#define DMA_CLOCK         RCC_AHBPeriph_DMA1  //DMA的时钟在AHB总线上面
//#define DMA_FLAG_TC       DMA1_FLAG_TC4
#define RECEIVEBUFFER_SIZE   100
#define USART_DR_ADDRESS  (USART1_BASE+0x04)  //串口的基地址加上数据寄存器的偏移地址  构成了外设的地址
//同时初始化两个DMA通道,分别作为接收和发送
//首先初始化DMA的通道5 DMA的通道5对应的是串口的USART_RX
//使用串口的DMA的时候 需要启动串口DMA的接收和发送
// USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);   //启DMA发送
// USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);   //启DMA接收
	  DMA_InitTypeDef DMA_Structure;
    
    //初始化时钟  DMA的时钟在AHB总线上面
    RCC_AHBPeriphClockCmd(DMA_CLOCK,ENABLE);	
	  
	  //配置DMA结构体
	  //配置谁给谁穿 传输的方向   这里的外设是源地址 从外设读取数据到内存中
	  DMA_Structure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS;//串口1 相对于串口1的基地址的偏移值的地址 当作外设的地址
	  DMA_Structure.DMA_MemoryBaseAddr = (uint32_t)ReceiveBuff; //内部的SRAM作为 储存器的地址
	  DMA_Structure.DMA_DIR = DMA_DIR_PeripheralSRC;	  // 方向:串口是外设,作为源地址,进行数据的发送,因此是SRC
    //配置传送的数据大小 数量
    DMA_Structure.DMA_BufferSize = RECEIVEBUFFER_SIZE ;	//传输元素的数目
	  DMA_Structure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址不增
	  DMA_Structure.DMA_MemoryInc = DMA_MemoryInc_Enable;   //内存地址自增
	  DMA_Structure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //设置外设数据宽度 一个字节
	  DMA_Structure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//设置储存器数据宽度
	  //配置模式
	  DMA_Structure.DMA_Mode = DMA_Mode_Normal;//设置模式   循环模式  
	  DMA_Structure.DMA_Priority = DMA_Priority_Medium; //通道优先级选择
	  DMA_Structure.DMA_M2M = DMA_M2M_Disable; //配置储存器到储存器 不使用M2M  禁止内存到内存之间传输
	  DMA_Init(DMA_CHANNEL5,&DMA_Structure);  //初始化DMA
    
      USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);   //启DMA发送    		
	  DMA_Cmd(DMA_CHANNEL5,ENABLE);          //使能DMA1的通道5
//初始化DMA的通道4作为USART_TX
	  //配置谁给谁穿 传输的方向   这里的外设是源地址 从外设读取数据到内存中
	  DMA_Structure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS;//串口1 相对于串口1的基地址的偏移值的地址 当作外设的地址
	  DMA_Structure.DMA_MemoryBaseAddr = (uint32_t)SendBuff; //内部的SRAM作为 储存器的地址
	  DMA_Structure.DMA_DIR = DMA_DIR_PeripheralDST;	  // 方向:串口是外设,作为目标地址,进行数据的接收,因此是DST
    //配置传送的数据大小 数量
    DMA_Structure.DMA_BufferSize = SENDBUFFER_SIZE ;	//传输元素的数目
	  DMA_Structure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址不增
	  DMA_Structure.DMA_MemoryInc = DMA_MemoryInc_Enable;   //内存地址自增
	  DMA_Structure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //设置外设数据宽度 一个字节
	  DMA_Structure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//设置储存器数据宽度
	  //配置模式
	  DMA_Structure.DMA_Mode = DMA_Mode_Normal;//设置模式   循环模式  
	  DMA_Structure.DMA_Priority = DMA_Priority_Medium; //通道优先级选择
	  DMA_Structure.DMA_M2M = DMA_M2M_Disable; //配置储存器到储存器 不使用M2M  禁止内存到内存之间传输
	  DMA_Init(DMA_CHANNEL4,&DMA_Structure);  //初始化DMA
	
	  USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);   //启DMA接收    		
	  DMA_Cmd(DMA_CHANNEL4,ENABLE);          //使能DMA的通道4     

初始化完成两个DMA的通道
在主函数中,当向发送数据的数组中进行赋值的时候,DMA就会把赋值的数发送到串口的TX 通过串口助手,进行查看
串口的中断服务函数

/*
DMA在接收数据的时候,串口接收DMA在初始化的时候就处于开启状态,一直等待数据的到来,
在软件上无需做任何事情,只要在初始化配置的时候设置好配置就可以了。等到接收到数据的时候,告诉CPU去处理即可。
当我们检测到触发了串口总线空闲中断的时候,我们就知道这一波数据传输完成了,然后我们就能得到这些数据,去进行处理即可。
这种方法是最简单的,根本不需要我们做多的处理,只需要配置好,串口就等着数据的到来,dma也是处于工作状态的,来一个数据就自动搬运一个数据。
暂时关闭串口接收DMA通道,有两个原因:1.防止后面又有数据接收到,产生干扰,因为此时的数据还未处理。2.DMA需要重新配置。
*/
void DEBUG_USART_IRQHandler(void)
{
//	printf("OK\r\n");
	uint16_t aa;

	//检查中断是否发生
	if(USART_GetITStatus(DEBUG_USARTx,USART_IT_IDLE) != RESET){
		
		DMA_Cmd(DMA_CHANNEL5,DISABLE);//首先关闭DMA传输
		
		aa = DMA_GetCurrDataCounter(DMA_CHANNEL5);//获取该通道剩余的信息数目	
		Usart_SendArray(DEBUG_USARTx,ReceiveBuff,RECEIVEBUFFER_SIZE-aa);
		if(strcmp((char *)ReceiveBuff,"open")==0){
			printf("OPEN\r\n");
		}
		DMA_SetCurrDataCounter(DMA_CHANNEL5,RECEIVEBUFFER_SIZE);
	  DMA_Cmd(DMA_CHANNEL5,ENABLE);                          //开启DMA传输	
		USART_ReceiveData(DEBUG_USARTx);                              //读取一次数据,不然会一直进中断
		USART_ClearFlag(DEBUG_USARTx,USART_FLAG_IDLE);                //清除串口空闲中断标志位	
	
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值