STM32中的DMA

2024-08-23 04:04
文章标签 stm32 dma

本文主要是介绍STM32中的DMA,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

概念

全称是Direct Memory Access,中文意思为直接存储器访问。
DMA可用于实现外设与存储器之间或者存储器与存储器之间数据传输的高效性。之所以称为高效,是因为DMA传输数据移动过程无需CPU直接操作,这样节省的 CPU 资源就可供其它操作使用。从硬件层面来理解,DMA就好像是RAM与I/O设备间数据传输的通路,外设与存储器之间或者存储器与存储器之间可以直接在这条通路上进行数据传输。这里说的外设一般指外设的数据寄存器,比如ADC、 SPI、 I2C等外设的数据寄存器,存储器一般是指片内SRAM、外部存储器、片内 Flash 等。

 利用DMA获取数据的流程

  • UART控制器读取外设发送的数据
  • DMA硬件上自动读取UART数据寄存器的数据
  • DMA硬件上自动将获取的数据搬移到内存中
  • UART控制器给CPU发送中断信号通知CPU数据读取完毕
  • CPU可以访问内存中的数据

总结:CPU无需频繁的访问数据寄存器,CPU只关心内存

 利用DMA发送数据的流程

  • CPU将数据写入指定的内存中
  • DMA硬件上自动从指定的内存中获取要发送的数据
  • DMA硬件上自动将数据搬移到数据寄存器中
  • UART控制器硬件上自动将数据发送出去
  • DMA给CPU发送中断信号通知数据发送完毕
     

结论:CPU无需频繁的访问数据寄存器,CPU只关心内存

DMA的特性

  • STM32F103有 2 个 DMA 控制器,分别是DMA1和DMA2
  • DMA1 有 7 个通道
  • DMA2 有 5个通道
  • 每个通道专门用来管理来自于一个或多个外设对存储器访问的请求

在同一个DMA模块上,多个请求间的优先权可以通过软件编程设置(共有四级:很高、高、中等和低),如果2个请求有相同的软件优先级,则较低编号的通道比较高编号的通道有较高的优先权。举个例子,通道2优先于通道4

 代码实现

标准库函数和结构体

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;

 初始化

采用DMA发送数据完成后,使用中断发送给CPU结束信号,需要匹配中断和DMA已经NVIC控制器

void My_DMA_Init(void)
{// 1.打开DMA1控制器时钟RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);// 2.配置DMA1通道4作为串口1发送 : 内存 -> 寄存器DMA_InitTypeDef DMA_Config;DMA_Config.DMA_MemoryBaseAddr = (u32)UART1DMA_TxBuff; // 内存缓冲区首地址DMA_Config.DMA_PeripheralBaseAddr = (u32)&USART1->DR; // 寄存器首地址DMA_Config.DMA_BufferSize = UART1DMA_TXBUFF_SIZE; // 内存缓冲区大小DMA_Config.DMA_DIR = DMA_DIR_PeripheralDST; // 内存->寄存器DMA_Config.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 寄存器不自增DMA_Config.DMA_MemoryInc = DMA_MemoryInc_Enable; // 内存自增DMA_Config.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // 内存搬移字节为单位DMA_Config.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 寄存器字节位单位DMA_Config.DMA_Mode = DMA_Mode_Normal; // 普通模式DMA_Config.DMA_Priority = DMA_Priority_Medium; // 中等DMA_Config.DMA_M2M = DMA_M2M_Disable; // 禁止内存之间拷贝DMA_Init(DMA1_Channel4, &DMA_Config);// 3.配置DMA1通道4支持DMA_IT_TC中断 DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE);// 4.配置NVIC支持DMA1通道4中断 NVIC_InitTypeDef NVIC_Config;NVIC_Config.NVIC_IRQChannel = DMA1_Channel4_IRQn; // DMA1通道4中断 NVIC_Config.NVIC_IRQChannelPreemptionPriority = 0;NVIC_Config.NVIC_IRQChannelSubPriority = 2;NVIC_Config.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_Config);
}

测试函数

// 串口1发送测试函数 
void UART1_DMA_Tx_Test(void)
{// 1.初始化内存缓冲区 u32 i;for(i = 0; i < UART1DMA_TXBUFF_SIZE; i++)UART1DMA_TxBuff[i] = 'A';// 2.关闭DMA1通道4DMA_Cmd(DMA1_Channel4, DISABLE);// 3.配置串口1支持DMA的发送 USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);// 4.设置搬移数据的长度DMA_SetCurrDataCounter(DMA1_Channel4, UART1DMA_TXBUFF_SIZE);// 5.打开DMA1通道4DMA_Cmd(DMA1_Channel4, ENABLE);// 打开该功能后, DMA1通道4就会自动从内存缓冲区中搬移数据到串口1的DR中// 搬移完成会触发DMA1通道4 TC中断DMA_TcFlag = 0; // 标识数据还没发完// 6.采用中断的方式判断数据是否搬移完毕 ??while(1){if(DMA_TcFlag){ // printf("\n DMA TX SUCCESS\n");break;}// 做其它业务 ...LED0 = !LED0;delay_ms(200);}
}

中断处理函数

// DMA1通道4触发的中断 
// 发送完成触发中断
void DMA1_Channel4_IRQHandler(void){// 1.判断是哪个中断 if(DMA_GetITStatus(DMA1_IT_TC4) != RESET){// 2.清除中断到来位 DMA_ClearITPendingBit(DMA1_IT_TC4);// 3.关闭DMA1通道4DMA_Cmd(DMA1_Channel4, DISABLE);// 4.标志数据发送完毕DMA_TcFlag = 1;}
}

初始化函数和cmd函数中需要将DMA相关添加进来

init.c中
static PINIT_T init_func[] = {LED_Init,			// led灯初始化BEEP_Init,		// beep初始化 Systick_init,	// 滴答定时器初始化KEY_Init,			// 按键初始化My_EXTI_Init,	// 中断初始化 UART_Init,		// 串口初始化AT24C02_Init, // AT24C02初始化DS18B20_Init, // 温度传感器的初始化My_DMA_Init,  // DMA初始化0
};cmd.c中
cmd_t cmd[] = {{"led on", LED_On},{"led off", LED_Off},{"beep on", BEEP_On},{"beep off", BEEP_Off},{"EEPROM R", AT24C02_ReadOne}, // 读取单字节{"EEPROM W", AT24C02_WriteOne}, //写入单字节{"EEPROM RS", AT24C02_ReadMul}, // 读取多字节{"EEPROM WS", AT24C02_WriteMul},	// 写入多字节{"temp", DS18B20_Test},  // 获取温度命令{"rom", DS18B20_ReadRom},	// 读取ROM值命令{"dma tx", UART1_DMA_Tx_Test} // DMA发送数据命令
};

实验结果

在串口工具中发送dma tx,串口工具能够显示通过内存写入到寄存器中的数据,本文中是写了1024和'A'

这篇关于STM32中的DMA的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1098299

相关文章

【STM32】SPI通信-软件与硬件读写SPI

SPI通信-软件与硬件读写SPI 软件SPI一、SPI通信协议1、SPI通信2、硬件电路3、移位示意图4、SPI时序基本单元(1)开始通信和结束通信(2)模式0---用的最多(3)模式1(4)模式2(5)模式3 5、SPI时序(1)写使能(2)指定地址写(3)指定地址读 二、W25Q64模块介绍1、W25Q64简介2、硬件电路3、W25Q64框图4、Flash操作注意事项软件SPI读写W2

STM32(十一):ADC数模转换器实验

AD单通道: 1.RCC开启GPIO和ADC时钟。配置ADCCLK分频器。 2.配置GPIO,把GPIO配置成模拟输入的模式。 3.配置多路开关,把左面通道接入到右面规则组列表里。 4.配置ADC转换器, 包括AD转换器和AD数据寄存器。单次转换,连续转换;扫描、非扫描;有几个通道,触发源是什么,数据对齐是左对齐还是右对齐。 5.ADC_CMD 开启ADC。 void RCC_AD

STM32内部闪存FLASH(内部ROM)、IAP

1 FLASH简介  1 利用程序存储器的剩余空间来保存掉电不丢失的用户数据 2 通过在程序中编程(IAP)实现程序的自我更新 (OTA) 3在线编程(ICP把整个程序都更新掉) 1 系统的Bootloader写死了,只能用串口下载到指定的位置,启动方式也不方便需要配置BOOT引脚触发启动  4 IAP(自己写的Bootloader,实现程序升级) 1 比如蓝牙转串口,

FreeRTOS-基本介绍和移植STM32

FreeRTOS-基本介绍和STM32移植 一、裸机开发和操作系统开发介绍二、任务调度和任务状态介绍2.1 任务调度2.1.1 抢占式调度2.1.2 时间片调度 2.2 任务状态 三、FreeRTOS源码和移植STM323.1 FreeRTOS源码3.2 FreeRTOS移植STM323.2.1 代码移植3.2.2 时钟中断配置 一、裸机开发和操作系统开发介绍 裸机:前后台系

寻迹模块TCRT5000的应用原理和功能实现(基于STM32)

目录 概述 1 认识TCRT5000 1.1 模块介绍 1.2 电气特性 2 系统应用 2.1 系统架构 2.2 STM32Cube创建工程 3 功能实现 3.1 代码实现 3.2 源代码文件 4 功能测试 4.1 检测黑线状态 4.2 未检测黑线状态 概述 本文主要介绍TCRT5000模块的使用原理,包括该模块的硬件实现方式,电路实现原理,还使用STM32类

STM32 ADC+DMA导致写FLASH失败

最近用STM32G070系列的ADC+DMA采样时,遇到了一些小坑记录一下; 一、ADC+DMA采样时进入死循环; 解决方法:ADC-dma死循环问题_stm32 adc dma死机-CSDN博客 将ADC的DMA中断调整为最高,且增大ADCHAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, ADC_Buffer_Size); 的ADC_Bu

基于stm32的河流检测系统-单片机毕业设计

文章目录 前言资料获取设计介绍功能介绍具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订阅👇🏻 单片机设计精品

STM32的使用方法一

注:我采用的是STM32F103RC芯片、相应的电路图和STM32CubeIDE软件这是在STM32CubeIDE软件定义芯片后,所给的必要的代码逻辑,加上了注释 #include "main.h"/* Private variables ---------------------------------------------------------*//* Private function

STM32 HAL CAN通讯 实操

1、简介 相比于串口通讯,对于刚接触CAN通讯的小白来说,CAN通讯相对复杂,看各种视频、帖子理论,总是一知半解。本次通过傻瓜式操作,先实现CAN通讯的交互,以提高小白的信心,也便于自己复习观看。本次以STM32CubeMX进行初始化配置,通过Keil 5软件进行软件设计,通过CAN盒实现进行数据的交互。该流程实际以STM32F0、F1、F3、F4、F7实测好用(理论上都适用),这三种型号单片机

我在高职教STM32——准备HAL库工程模板(1)

新学期开学在即,又要给学生上 STM32 嵌入式课程了。这课上了多年了,一直用的都是标准库来开发,已经驾轻就熟了。人就是这样,有了自己熟悉的舒适圈,就很难做出改变,老师上课也是如此,排斥新课和不熟悉的内容。显然,STM32 的开发,HAL 库已是主流,自己其实也在使用,只不过更换库就意味着教学内容有很大变化,自己也就迟迟没有迈出调整这一步。现在,是时候做出变化了,笔者计划保持教学项