DMA通信编程与STM32串口中断方式

DMA通信原理

DMA的基本介绍

DMA,全称Direct Memory Access,即直接存储器访问。
DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。
我们知道CPU有转移数据、计算、控制程序转移等很多功能,系统运作的核心就是CPU,但有些事情却没有那么重要,比方说数据的复制和存储数据,如果我们把这部分的CPU资源拿出来,让CPU去处理其他的复杂计算事务,能够更好的利用CPU的资源呢。
因此:转移数据(尤其是转移大量数据)是可以不需要CPU参与。比如希望外设A的数据拷贝到外设B,只要给两种外设提供一条数据通路,直接让数据由A拷贝到B 不经过CPU的处理,DMA就是基于以上设想设计的,它的作用就是解决大量数据转移过度消耗CPU资源的问题。有了DMA使CPU更专注于更加实用的操作–计算、控制等。在这里插入图片描述

DMA工作原理

DMA的作用就是实现数据的直接传输,而去掉了传统数据传输需要CPU寄存器参与的环节,主要涉及四种情况的数据传输,但本质上是一样的,都是从内存的某一区域传输到内存的另一区域(外设的数据寄存器本质上就是内存的一个存储单元)。四种情况的数据传输如下:
1、外设到内存
2、内存到外设
3、内存到内存
4、外设到外设
当用户将参数设置好,主要涉及源地址、目标地址、传输数据量这三个,DMA控制器就会启动数据传输,传输的终点就是剩余传输数据量为0(循环传输不是这样的)。换句话说只要剩余传输数据量不是0,而且DMA是启动状态,那么就会发生数据传输。

STM32的DMA结构

对于大容量的STM32芯片有2个DMA控制器 两个DMA控制器,DMA1有7个通道,DMA2有5个通道。
每个通道都可以配置一些外设的地址。

DMA的主要特性

● 12个 独立的可配置的通道(请求)DMA1有7个通道,DMA2 有5个通道
● 每个通道都直接连接专用的硬件DMA请求,每个通道都同样支持软件触发。这些功能通过软件来配置。
● 在七个请求间的优先权可以通过软件编程设置(共有四级:很高、高、中等和低),假如在相等优先权时由硬件决定(请求0优先于请求1,依此类推) 。
● 独立的源和目标数据区的传输宽度(字节、半字、全字),模拟打包和拆包的过程。源和目标地址必须按数据传输宽度对齐。
● 支持循环的缓冲器管理
● 每个通道都有3个事件标志(DMA 半传输,DMA传输完成和DMA传输出错),这3个事件标志逻辑或成为一个单独的中断请求。
● 存储器和存储器间的传输
● 外设和存储器,存储器和外设的传输

● 闪存、SRAM 、外设的SRAM 、APB1 APB2和AHB外设均可作为访问的源和目标。
● 可编程的数据传输数目:最大为65536

DMA寄存器列表

① 中断类
DMA_ISR:DMA中断状态寄存器
DMA_IFCR:DMA中断标志位清除寄存器
说明:DMA1、DMA2分别有一组寄存器。
② 控制传输类
DMA_CCRx:DMA通道x配置寄存器 
DMA_CNDTRx:DMA通道x数据数量寄存器
DMA_CPARx:DMA通道x外设地址寄存器
DMA_CMARx:DMA通道x内存地址寄存器

DMA进行数据传输的必要条件

1、剩余传输数据量大于0
2、DMA通道传输使能通道上
3、DMA数据传输有事件请求
外设到XX方向的传输
假设是ADC到存储器的数据传输,显然ADC的DMA传输的源地址是ADC的数据寄存器。并不是说只要DMA通道传输使能后,就立即进行数据传输。只有当一次ADC转化完成,ADC的DMA通道的传输事件有效,DMA才会从ADC的数据寄存器读出数据,写入目的地址。当DMA在读取ADC的数据寄存器时,同时使ADC的DMA通道传输事件无效。显然,要等到下一次ADC转换完成后,才能启动再一次的数据传输。
存储器对XX的DMA传输
因为数据是准备好的,不像ADC还需要等待数据到位。所以,不需要对应通道的事件。只要使能DMA数据传输就一直传输,直到达到设定的传输量。

中断

中断概念

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

STM32执行中断

在STM32中执行中断主要分三部分:
1.配置NVIC_Config()函数
2.配置EXTI_Config()函数
3.编写中断服务函数
配置NVIC_Config()的目的是选择中断源的优先级以及打开中断通道,主要功能通过配置NVIC初始化结构体NVIC_InitStruct来完成。通俗的讲,STM32中有很多中断,而当有多个中断同时发生时就涉及到中断执行的先后问题了,所以引入了中断优先级的概念,中断优先级越高中断就越先执行。在这里我们只讨论外部中断的优先级,在 NVIC 有一个专门的寄存器:中断优先级寄存器 NVIC_IPRx,用来配置外部中断的优先级。优先级高低的比较包括抢占优先级和子优先级,先比较抢占优先级,如果抢占优先级相同就比较子优先级,从而得出中断之间的优先级高低。NVIC的主要任务就是给对应的中断源分配中断优先级。 中断优先级分配的原理繁杂,但固件库编程的好处就是化繁为简,我们只需要按照NVIC_InitStruct()中的内容进行配置就行。

实验练习

STM32用HAL库点亮LED灯

任务要求

用stm32F103核心板的GPIOA端一管脚接一个LED,GPIOB端口一引脚接一个开关(用杜邦线模拟代替)。采用中断模式编程,当开关接高电平时,LED亮灯;接低电平时,LED灭灯。

实验过程

选择芯片在这里插入图片描述
找到PB5,选择为GPIO——EXTI5中断模式在这里插入图片描述
A1引脚配置,默认设置为高电平,处于熄灭状态在这里插入图片描述

开启中断在这里插入图片描述
配置时钟为外部时钟源
在这里插入图片描述
时钟树设置在这里插入图片描述
在这里插入图片描述
生成代码
在这里插入图片描述
在main.c中加入

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    /* Prevent unused argument(s) compilation warning */
    HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_1);  //翻转电平
    /* NOTE: This function Should not be modified, when the callback is needed,
             the HAL_GPIO_EXTI_Callback could be implemented in the user file
     */
}

编译烧录请添加图片描述

在这里插入图片描述

采用串口中断方式通信

任务要求

采用串口中断方式重做上周的串口通信作业。

实验过程

新建项目,选择芯片
在这里插入图片描述
SYS设置
在这里插入图片描述
RCC设置
在这里插入图片描述
时钟树设置
在这里插入图片描述

配置串口,并将USTART1配置为异步通信模式:
在这里插入图片描述
使能中断
在这里插入图片描述
选择MDK-ARM,加入项目名称
在这里插入图片描述
生成代码
在这里插入图片描述
打开keil在main.c中加入:
1、定义缓冲区的大小
define LENGTH 10 // 接收缓冲区大小
位置
在这里插入图片描述
2、定义缓冲区和标识位
uint8_t RxBuffer[LENGTH]; // 接收缓冲区
uint8_t Rxflag = 0; // 标志位,0为接收未完成,1为接收完成
位置:
在这里插入图片描述
3、定义接收成功信息
HAL_UART_Receive_IT(&huart1, (uint8_t*)RxBuffer, LENGTH); // 使能接收中断
char data[] = “\nReveive Success\n”; // 接收成功信息```

位置(将原有的删除):
在这里插入图片描述
4、在while循环中发送成功信息和接收到的信息:

if (Rxflag == 1){ // 若数据接收完成
	Rxflag = 0;  // 清除标志位
	HAL_UART_Transmit(&huart1, (uint8_t *)data, 18, 0xFFFF);  // 接收成功信息
	// 发送接收到的字符
	HAL_UART_Transmit_IT(&huart1, (uint8_t*)RxBuffer, LENGTH);
}

位置:
在这里插入图片描述
4、在main.c中定义回调函数

	if (huart->Instance == USART1){
		Rxflag = 1;  // 设置标志位为1
		HAL_UART_Receive_IT(&huart1, (uint8_t*)&RxBuffer, LENGTH); // 使能接收中断
	}
}

位置:
在这里插入图片描述
编译生成.hex
在这里插入图片描述
在这里插入图片描述
烧录
在这里插入图片描述
在这里插入图片描述

DMA实现串口通信

任务要求

STM32采用串口DMA方式,用115200bps或更高速率向上位机连续发送数据

实验过程

选择芯片在这里插入图片描述
SYS设置
在这里插入图片描述
RCC设置
在这里插入图片描述
时钟树设置,将8改为72
在这里插入图片描述
设置USTART1,设置mode
在这里插入图片描述
使能串口中断
在这里插入图片描述
DMA Settings中ADD设置加入USTART1_RX,USTART1_TX:
在这里插入图片描述
项目设置在这里插入图片描述
生成代码打开keil
在这里插入图片描述
打开main.c在while循环中添加语句:

uint8_t data[] = "Hello Windows\r\n";
HAL_UART_Transmit_DMA(&huart1,(uint8_t *)data,16);
HAL_Delay(1000);   //延时

设置魔术棒生成.hex文件
在这里插入图片描述
编译
在这里插入图片描述
烧录
在这里插入图片描述

运行
在这里插入图片描述

总结

程序设置中断可以灵活处理事务,将更紧急的事务优先处理。
DMA传输过程的初始化和启动由CPU完成,传输过程由DMA控制器来执行,无需CPU参与,从而节省CPU资源,提高利用率。

参考

1、DMA:https://blog.csdn.net/lushoumin/article/details/78907526
https://blog.csdn.net/as480133937/article/details/104827639/
2、中断:
第七章__中断系统(new).pdf
https://blog.csdn.net/qq_43743762/article/details/97272694

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值