1.DMA
1.1DMA的基本介绍
直接存储器访问(Direct Memory Access),简称DMA。DMA是CPU一个用于数据从一个地址空间到另一地址空间“搬运”(拷贝)的组件,数据拷贝过程不需CPU干预,数据拷贝结束则通知CPU处理。因此,大量数据拷贝时,使用DMA可以释放CPU资源。DMA数据拷贝过程,典型的有:
·内存—>内存,内存间拷贝
·外设—>内存,如uart、spi、i2c等总线接收数据过程
·内存—>外设,如uart、spi、i2c等总线发送数据过程
因此:转移数据(尤其是转移大量数据)是可以不需要CPU参与。比如希望外设A的数据拷贝到外设B,只要给两种外设提供一条数据通路,直接让数据由A拷贝到B 不经过CPU的处理,
DMA就是基于以上设想设计的,它的作用就是解决大量数据转移过度消耗CPU资源的问题。有了DMA使CPU更专注于更加实用的操作–计算、控制等。
1.2DMA传输参数
我们知道,数据传输,首先需要的是1 数据的源地址 2 数据传输位置的目标地址 ,3 传递数据多少的数据传输量 ,4 进行多少次传输的传输模式 DMA所需要的核心参数,便是这四个。
当用户将参数设置好,主要涉及源地址、目标地址、传输数据量这三个,DMA控制器就会启动数据传输,当剩余传输数据量为0时 达到传输终点,结束DMA传输 ,当然,DMA 还有循环传输模式 当到达传输终点时会重新启动DMA传输。
也就是说只要剩余传输数据量不是0,而且DMA是启动状态,那么就会发生数据传输。
1.3DMA的主要特征
每个通道都直接连接专用的硬件DMA请求,每个通道都同样支持软件触发。这些功能通过软件来配置:
1、在同一个DMA模块上,多个请求间的优先权可以通过软件编程设置(共有四级:很高、高、中等和低),优先权设置相等时由硬件决定(请求0优先于请求1,依此类推);
2、独立数据源和目标数据区的传输宽度(字节、半字、全字),模拟打包和拆包的过程。源和目标地址必须按数据传输宽度对齐;
3、支持循环的缓冲器管理;
4、每个通道都有3个事件标志(DMA半传输、DMA传输完成和DMA传输出错),这3个事件标志逻辑或成为一个单独的中断请求;
5、存储器和存储器间的传输、外设和存储器、存储器和外设之间的传输;
闪存、SRAM、外设的SRAM、APB1、APB2和AHB外设均可作为访问的源和目标;
6、可编程的数据传输数目:最大为65535。
DMA传输
DMA传输时外设对DMA控制器发出请求。
DMA控制器收到请求,触发DMA工作。
DMA控制器从AHB外设获取ADC采集的数据,存储到DMA通道中
DMA控制器的DMA总线与总线矩阵协调,使用AHB把外设ADC采集的数据经由DMA通道存放到SRAM中,这个数据的传输过程中,完全不需要内核的参与,也就是不需要CPU的参与。
2.实验过程
2.1创建工程
2.2 添加代码
添加头文件
#include "stdio.h"
#include "string.h"
添加变量
uint8_t RxBuffer[LENGTH]; //字符缓冲区,LENGTH定义为4
uint8_t RxFlag = 0;//是否接受到stop
uint8_t ch;//额外字符't'的缓冲区
uint8_t flag = 1;//是否需要继续接收额外字符
添加while循环
while (1)
{
/* USER CODE END WHILE */
if(RxFlag == 0){
HAL_UART_Transmit(&huart1,(uint8_t*)"hello windows!\r\n",16,0xffff);
HAL_Delay(1000);
}
/* USER CODE BEGIN 3 */
}
添加中断接收回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
if(huart->Instance == USART1&&strcmp((char *)RxBuffer,"stop")==0){
RxFlag = 1;
HAL_UART_Receive_IT(huart, (uint8_t*)&RxBuffer, LENGTH);
}else if(huart->Instance == USART1&&strcmp((char *)RxBuffer,"star")==0&&flag==1){
flag = 0;
HAL_UART_Receive_IT(huart, (uint8_t*)&ch, 1);
}
if(huart->Instance == USART1 && ch == 't' && flag == 0){
RxFlag = 0;
flag = 1;
ch = '0';
HAL_UART_Receive_IT(huart, (uint8_t*)&RxBuffer, LENGTH);
}
}
3.结果