zoukankan      html  css  js  c++  java
  • stm32F1 DMA

    DMA,全称是Direct Memory Access,中文意思为直接存储器访问

    DMA可用于实现外设与存储器之间或者存储器与存储器之间数据传输的高效性

    DMA请求映像
    各通道的DMA1请求:
    1

    各通道的DMA2请求:
    2

    DMA配置步骤

    1.使能DMA控制器时钟
    2.初始化DMA通道,DMA_InitTypeDef
    3.使能外设DMA功能
    4.开启DMA的通道
    5.查询DMA传输状态

    举例

    u8 txBuffer[50] = {0};
    u8 rxBuffer[50] = {0};
    
    void DMA_send(u32 num)
    {
    	DMA_Cmd(DMA1_Channel4, DISABLE);
    	DMA_SetCurrDataCounter(DMA1_Channel4, num);
    	DMA_Cmd(DMA1_Channel4, ENABLE); //开启DMA的通道
    }
    
    void DMA1_Channel4_IRQHandler(void)
    {
    	while(DMA_GetFlagStatus(DMA1_FLAG_TC4) != SET);
    	
    	DMA_ClearFlag(DMA1_FLAG_TC4);
    }
    
    typedef struct
    {
    	uint32_t DMA_PeripheralBaseAddr; //外设地址
    	uint32_t DMA_MemoryBaseAddr; //存储器地址
    	uint32_t DMA_DIR; //数据传输方向
    	uint32_t DMA_BufferSize; //数据传输数量
    	uint32_t DMA_PeripheralInc; //外设地址增量模式
    	uint32_t DMA_MemoryInc; //存储器地址增量模式
    	uint32_t DMA_PeripheralDataSize; //外设数据宽度
    	uint32_t DMA_MemoryDataSize; //存储器数据宽度
    	uint32_t DMA_Mode; //循环模式
    	uint32_t DMA_Priority; //通道优先级
    	uint32_t DMA_M2M; //存储器到存储器模式
    }DMA_InitTypeDef;
    
    void DMA_nvic_init(DMA_Channel_TypeDef *DMAy_Channelx, uint8_t NVIC_IRQChannel)
    {
    	NVIC_InitTypeDef NVIC_InitStructure;
    	
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    	NVIC_InitStructure.NVIC_IRQChannel = NVIC_IRQChannel;
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    	NVIC_Init(&NVIC_InitStructure);
    	
    	DMA_ITConfig(DMAy_Channelx, DMA_IT_TC, ENABLE);
    }
    
    void DMA_init(DMA_Channel_TypeDef *DMAy_Channelx, uint32_t dir, u32 mem_addr, u32 buf_size)
    {
    	DMA_InitTypeDef dma = {0};
    
    	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA控制器时钟
    
    	dma.DMA_PeripheralBaseAddr = (u32)&USART1->DR; //USART1数据寄存器
    	dma.DMA_MemoryBaseAddr = mem_addr;
    	dma.DMA_DIR = dir;
    	dma.DMA_BufferSize = buf_size;
    	dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //不执行外设地址增量操作
    	dma.DMA_MemoryInc = DMA_MemoryInc_Enable; //执行存储器地址增量操作
    	dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    	dma.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    	dma.DMA_Mode = DMA_Mode_Normal; //不执行循环操作
    	dma.DMA_Priority = DMA_Priority_Medium; //中
    	dma.DMA_M2M = DMA_M2M_Disable; //非存储器到存储器模式
    	DMA_Init(DMAy_Channelx, &dma); //初始化DMA通道
    
    	USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); //使能DMA发送模式
    	USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE); //使能DMA接收模式
    }
    
    void USART1_IRQHandler(void)
    {
    	uint16_t rxCount;
    
    	if(USART_GetFlagStatus(USART1, USART_FLAG_IDLE) != RESET)
    	{
    		//清中断
    		USART1->SR;
    		USART1->DR;
    
    		//接收
    		DMA_Cmd(DMA1_Channel5, DISABLE); 
    		rxCount = sizeof(rxBuffer) - DMA_GetCurrDataCounter(DMA1_Channel5); //获取接收字节数
    		DMA_SetCurrDataCounter(DMA1_Channel5, sizeof(rxBuffer)); //计数重置
    		DMA_Cmd(DMA1_Channel5, ENABLE); //开启下一次接收
    
    		//发送
    		DMA_send(rxCount); //开启一次发送
    	}
    }
    
    int main(void)
    {
    	//USART1发送
    	DMA_init(DMA1_Channel4, DMA_DIR_PeripheralDST, (u32)txBuffer, sizeof(txBuffer));
    	DMA_nvic_init(DMA1_Channel4, DMA1_Channel4_IRQn);
    	
    	//USART1接收
    	DMA_init(DMA1_Channel5, DMA_DIR_PeripheralSRC, (u32)rxBuffer, sizeof(rxBuffer));
    	DMA_Cmd(DMA1_Channel5, ENABLE); //使能接收
    
    	while(1)
    	{
    		led1 = ~led1;
    		delay_ms(1000);
    	}
    }
    
  • 相关阅读:
    《Orange‘s》 Bochs环境配置
    《CSAPP》读书笔记
    基于SDL2实现俄罗斯方块
    VS 提示对象被多次指定;已忽略多余的指定
    SDL2.0 vs2017环境配置
    初探模板元编程
    从代码理解 cartographer X --- 浅析Cartographer框架之美
    从代码理解 cartographer 1
    Arch Linux 安装总结
    从代码理解 cartographer 3 --- 理解 Range data 数据的流入
  • 原文地址:https://www.cnblogs.com/zhangxuechao/p/11709557.html
Copyright © 2011-2022 走看看