DMA模式简介:
什么是DMA?(Direct Memory Access)
DMA 是 "Direct Memory Access"(直接内存访问)的缩写,是计算机系统中允许外部设备(如硬盘、网卡等)直接访问主存储器(内存)的一种技术,而无需通过中央处理器(CPU)的干预。
这样做可以提高系统的效率,因为它减少了 CPU 在数据传输中的负担,使其能够专注于其他处理任务。
在使用 DMA 时,设备会通过一个被称为 DMA 控制器的硬件模块来管理数据的读写。DMA 控制器会请求访问内存总线,一旦获得总线控制权,它就可以直接将数据传输到内存或从内存中读取数据。CPU 只需在传输开始和结束时进行一些基本的设置和控制。
数据发送与接收:
DMA通道创建:
因此,在使用DMA时,我们需要创建DMA通道。
进入配置界面:Connectivity--->USART2--->Add--->将DMA Request 改为USARTT2_TX和USARTT2_RX(表示此DMA通道用于USART2的串口发送and接收)
(从USARTT2_TX这一栏可以看到数据搬运方向被设置为从内存(Memory)向外设(Peripheral)搬运——即内存变量向发送数据寄存器进行搬运)
串口接收不定长数据:
串口空闲中断的触发条件与接收的字节数无关,当串口接收从忙碌转为空闲时才会触发,因此我们一般认为空闲中断发生时,就是一帧数据包接收完成了。
使用处理函数
HAL_UARTEx_ReceiveToIdle_DMA(&huart2, receiveData, Sizeof(receiveData));
此时,我们需要用到该函数对应的回调函数:
在stm32f1xx_it.c文件中--->找到void USART2_IRQHandler(void)函数,按住Ctrl键,点击HAL_UART_IRQHandler,进入到HAL_UART_IRQHandler所在的stm32f1xx_hal_uart.c--->找到void HAL_UARTEx_RxEventCallback回调函数
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
问题与解决:
在使用串口的DMA模式时,除了串口空闲中断以外,DMA的“传输过半中断”也会触发RxEventCallback回调函数。
我们在后面添加以下代码就可以解决问题了
__HAL_DMA_DISABLE_IT(&hdma_usart2_rx,DMA_IT_HT);
代码:
定义全局变量
uint8_t receiveData[50];
回调处理
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
if(huart == &huart2)
{
HAL_UART_Transmit_DMA(&huart2, receiveData, Size);
GPIO_PinState state =GPIO_PIN_SET;
if(receiveData[1]=='0')
{
state = GPIO_PIN_RESET;
}
else if(receiveData[1]=='1')
{
state = GPIO_PIN_SET;
}
if(receiveData[0]=='R')
{
HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, state);
}
else if(receiveData[0]=='G')
{
HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin, state);
}
else if(receiveData[0]=='B')
{
HAL_GPIO_WritePin(LED_BLUE_GPIO_Port, LED_BLUE_Pin, state);
}
HAL_UARTEx_ReceiveToIdle_DMA(&huart2, receiveData, sizeof(receiveData));
__HAL_DMA_DISABLE_IT(&hdma_usart2_rx,DMA_IT_HT);
}
}
发送处理
HAL_UARTEx_ReceiveToIdle_DMA(&huart2, receiveData, sizeof(receiveData));
__HAL_DMA_DISABLE_IT(&hdma_usart2_rx,DMA_IT_HT);