STM32使用CUBEMX配置DMA+USRT
DMA基础知识:
简单来说:DMA(Direct Memory Access,直接存储器访问)是一个数据搬运工,实现存储器和存储器,外设和外设,存储器和外设,外设和存储器之间的数据搬运, 可以实现数据的搬运(不需要CPU的参入),
2.DMA的意义
代替 CPU 搬运数据,为 CPU 减负。
1). 数据搬运的工作比较耗时间;
2). 数据搬运工作时效要求高(有数据来就要搬走);
3). 没啥技术含量(CPU 节约出来的时间可以处理更重要的事);
3、DMA搬运方式
存储器→存储器(例如:复制某特别大的数据)
存储器→外设 (例如:将某数据buf写入串口TDR寄存器)
外设→存储器 (例如:将串口RDR寄存器写入某数据buf)
存储器到存储器的数据搬运最好使用软件触发(实现数据的搬运即可)
外设到存储器的数据搬运使用硬件触发(因为外设不是时时刻刻都在发数据,而其数据可能是有时效性的)
Dirction : DMA传输方向
四种传输方向:
4、DMA控制器
STM32的芯片型号不同,DMA的数量和通道不同(需要自己查询技术手册)一个通道只能搬运一个外设的数据,当多个数据来的时候,需要仲裁器来判断优先级。
1、存储器到存储器
memory to memory代表存储器到存储器,
DMA2 Stream 0:DMA2通道0
Priority:优先级
Mode:Normal代表当一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次
Circular代表传输完成后又重新开始继续传输,不断循环永不停止
如果是存储器到存储器,那两边的地址都要自增
主要就是启动函数
HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
DMA的工作方式是将数据从一个内存区域(比如A)传输到另一个区域(比如B),但这个过程通常是一次性的或者在预定的条件下进行的。DMA不会自动地检测到内存A的数值变化,也不会自动更新内存B。换句话说,DMA在执行数据搬运后,内存A和内存B之间的关系就结束了,除非再次通过DMA进行传输。
2、存储器到外设
串口发送数据是将数据不断存进固定外设地址串口的发送数据寄存器(USARTx_TDR)。所以外设的地址是不递增。
而存储器存储的是要发送的数据,所以地址指针要递增,保证数据依次被发出
HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size)
开启串口UART,const uint8_t *pData是你想要传输到串口的数据(这个转运是实时的,存储器的数值改变后,或通过DMA将最新的数据转运到串口)
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
for (int i = 0; i < 8; i++) {
B_Uart_RAM[i]++; // 每个元素自增1
sprintf((char *)T_Buf, "SrcBuf[%d]: %02d", i, B_Uart_RAM[i]);
lcd_show_string(10, 130 + i * 20, 210, 16, 16, (char*)T_Buf, RED); // 显示自增后的 SrcBuf
}
HAL_Delay(150);
HAL_UART_Transmit_DMA(&huart1,B_Uart_RAM,10);
}
3、外设到存储器(重点)
外设通过DMA转运串口数据到内存储器中,使用
HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
STM32 IDLE 接收空闲中断
STM32的IDLE的中断产生条件:在串口无数据接收的情况下,不会产生,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一但接收的数据断流,没有接收到数据,即产生IDLE中断
具体配置可以看下面链接的【测试例程2】
【STM32】HAL库 STM32CubeMX教程十一—DMA (串口DMA发送接收)_cubemx dma-CSDN博客
作者:小咖大_