本篇文章来讲解DMA的概念,并使用DMA来进行串口的数据收发。
DMA(Direct Memory Access,直接内存访问)是一种计算机系统的技术,允许外部设备(如硬盘驱动器、网络适配器或图形卡)直接与计算机内存进行数据传输,而不需要CPU的直接参与。这种直接的内存访问可以提高数据传输的效率,并减轻CPU的负担。
在没有DMA的情况下,数据传输通常需要通过CPU来完成,这涉及到CPU的中断处理程序从设备读取数据,然后将数据写入内存,或者从内存读取数据,然后将数据发送到设备。这种方式会消耗CPU的时间和计算资源,限制了系统的性能和吞吐量。
通过DMA技术,外部设备可以直接与系统内存进行数据传输,而不需要CPU的干预。在DMA传输开始之前,系统配置好DMA控制器,并提供一个DMA缓冲区,外部设备可以将数据直接写入到该缓冲区或者从该缓冲区读取数据。当DMA传输完成后,DMA控制器会发出一个中断信号,以通知CPU。
使用DMA的好处包括:
1.提高数据传输速度:由于数据传输不需要CPU的介入,DMA可以以更高的速度进行数据传输,从而提高系统性能和吞吐量。
2.减轻CPU负担:传统的数据传输需要CPU的参与,消耗CPU的时间和计算资源。而使用DMA进行数据传输时,CPU可以专注于其他的计算任务,减轻了CPU的负担。
3.支持大规模数据传输:DMA技术可以支持大规模的数据传输,例如高清视频流、大型文件和网络数据包的处理。
总之,DMA是一种能够提高系统性能和数据传输效率的技术,通过允许外部设备直接与内存进行数据传输,减少了CPU的介入。这在需要高速、大量或连续数据传输的场景中特别有用,如高性能计算、网络通信和存储系统等。
从DMA的描述来看在STM32 F103这款芯片中有DMA1和DMA2,DMA1有7个通道,DMA2有5个通道。
DMA架构图:
DMA支持直接和SRMA进行数据的传输,不需要经过CPU,这样就可以让CPU去做其他的事情,提高系统的运行效率。
使用DMA(Direct Memory Access)进行数据传输时,通常需要经过以下步骤:
1.设置DMA控制器:首先,需要在系统中配置和设置DMA控制器。这包括设置DMA的源地址和目标地址,传输长度,传输方向(从内存到设备或从设备到内存),以及其他相关参数。
2.发送DMA请求:在数据传输之前,需要向DMA控制器发送DMA请求。该请求通常由CPU或设备发起,用于指示DMA控制器执行特定的数据传输操作。
3.DMA传输:一旦DMA请求被接收和识别,DMA控制器将启动数据传输。它将直接从源地址读取数据,并将数据传输到目标地址。在传输过程中,DMA控制器绕过CPU,直接控制内存和设备之间的数据传输,以提高数据传输效率并减轻CPU的负担。
4.中断或完成通知:一旦DMA传输完成,DMA控制器通常会生成一个中断信号或发送一个完成通知,以通知CPU或相关设备传输已经完成。
正常进行数据的发送:
不使用DMA进行串口的数据发送时,CPU需要从SRMA中读取出存储的数据,然后再发送给串口,发送少量数据是不会影响CPU执行其他事情的,假如我想发送10000个数据,那么这个时候就会让CPU处于一直在发送数据的状态,这样就会影响到其他程序的执行。
DMA可以直接访问到外设和SRMA,那么这样就不需要CPU来进行数据的读取交换了,直接使用DMA就可以解决这个问题,那么这样的话就可以提高系统的运行效率了。
下面我们来看到DMA的两种模式,一种是循环模式,一种是内存到内存的模式。
DMA的循环模式(Circular Mode):
在循环模式下,DMA传输的数据可以在源和目的地之间循环传输,以连续地进行数据传输操作。这种模式下,一旦DMA传输完成,它会自动重新开始下一轮传输,而无需软件干预。
循环模式对于需要在连续数据块之间进行重复传输的应用非常有用,如音频、视频流等。它可以在不中断DMA传输的情况下循环传输数据,大大提高了数据传输效率和系统性能。
DMA的内存到内存模式(Memory-to-memory Mode):
内存到内存模式允许DMA直接在两个内存区域之间进行数据传输,而无需外设的参与。在这种模式下,DMA通道可以从一个内存位置读取数据,并将数据直接写入另一个内存位置,而不需要CPU的介入。
内存到内存模式非常适用于需要在内存之间快速传输数据的应用场景,例如内存拷贝、内存填充等。通过使用这种模式,DMA可以独立地执行数据传输,减轻CPU的负担,提高传输效率。
总结:DMA的循环模式允许数据在源和目的地之间循环传输,连续进行数据传输操作,并在每次传输完成后自动重新开始下一轮传输。而DMA的内存到内存模式允许DMA直接在两个内存区域之间传输数据,而不需要外设的触发请求,并且能够快速、高效地在内存之间传输数据。这两种模式都有助于提高数据传输效率并减轻CPU的负担,适用于不同的应用场景。
配置一个LED灯观察实验现象:
配置串口1:
开启串口中断:
这里不开启串口中断的话无法判断串口是否发送完成一次数据,这样串口就一直处于忙状态导致完成进行下一次的发送。
TX设置为从内存到外设,因为串口的发送就是把内存中的数据取出来再发给外设,RX设置为从外设到内存,串口发送过来的数据将会保存在内存中。
模式选择Normal,循环模式的话只需要调用一次发送函数就会一直进行数据的发送了。
具体代码:
这里发送一个非常长的数据,同时让这个LED闪烁,看看串口的发送会不会影响到LED的闪烁,结果是不会的。
uint8_t msg[1024] = "hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello";
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_UART_Transmit_DMA(&huart1, msg, strlen(msg) + 1);
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5);
HAL_Delay(100);
}
本篇文章就讲解到这里,下篇文章我们讲解DMA的具体配置和DMA串口接收不定长数据。