DMA使用心得-STM32

本文结构

  • DMA简要介绍
  • DMA主体思路
  • DMA代码实现与分析

DMA简要介绍

  1. 什么是DMA?
    DMA(Direct Memory Access, 直接存储器访问),允许外设与内存直接传输数据的技术,无需CPU干预。
  2. DMA的特点是什么?
    不受CPU直接控制的"数据搬运工",说人话,如果不用DMA,你在调试串口时,上位机发送数据过来,你在接收的地方打了断点,你就接收不到完整的数据;但是,如果你用了DMA,你打了断点数据照常接收。

DMA主体思路

DMA代码的实现

c 复制代码
/**
 * @brief  串口dma接收完成中断处理
 * @param  
 * @retval 
 */
void uart_dmarx_done_isr(uint8_t uart_id)
{
  	uint16_t recv_size;
	
	recv_size = s_uart_dev[uart_id].dmarx_buf_size - s_uart_dev[uart_id].last_dmarx_size;
    s_UartTxRxCount[uart_id*2+1] += recv_size;
	fifo_write(&s_uart_dev[uart_id].rx_fifo, 
				   (const uint8_t *)&(s_uart_dev[uart_id].dmarx_buf[s_uart_dev[uart_id].last_dmarx_size]), recv_size);

	s_uart_dev[uart_id].last_dmarx_size = 0;
}

/**
 * @brief  串口dma接收缓存大小一半数据中断处理 
 * @param  
 * @retval 
 * @描述:
 * 				将接收的数据
 */
void uart_dmarx_half_done_isr(uint8_t uart_id)
{
  	uint16_t recv_total_size;
  	uint16_t recv_size;
	
	if(uart_id == 0)
	{
	  	recv_total_size = s_uart_dev[uart_id].dmarx_buf_size - bsp_uart1_get_dmarx_buf_remain_size();	
	}
	else if (uart_id == 1)
	{
		recv_total_size = s_uart_dev[uart_id].dmarx_buf_size - bsp_uart2_get_dmarx_buf_remain_size();
	}
	recv_size = recv_total_size - s_uart_dev[uart_id].last_dmarx_size;
	s_UartTxRxCount[uart_id*2+1] += recv_size;
    
	fifo_write(&s_uart_dev[uart_id].rx_fifo, 
				   (const uint8_t *)&(s_uart_dev[uart_id].dmarx_buf[s_uart_dev[uart_id].last_dmarx_size]), recv_size);
	s_uart_dev[uart_id].last_dmarx_size = recv_total_size;
}

/**
 * @brief  串口空闲中断处理
 * @param  
 * @retval 
 */
void uart_dmarx_idle_isr(uint8_t uart_id)
{
  	uint16_t recv_total_size;
  	uint16_t recv_size;
	
	if(uart_id == 0)
	{
	  	recv_total_size = s_uart_dev[uart_id].dmarx_buf_size - bsp_uart1_get_dmarx_buf_remain_size();
	}
	else if (uart_id == 1)
	{
		recv_total_size = s_uart_dev[uart_id].dmarx_buf_size - bsp_uart2_get_dmarx_buf_remain_size();
	}
	
	recv_size = recv_total_size - s_uart_dev[uart_id].last_dmarx_size;
	s_UartTxRxCount[uart_id*2+1] += recv_size;


	fifo_write(&s_uart_dev[uart_id].rx_fifo, 
				   (const uint8_t *)&(s_uart_dev[uart_id].dmarx_buf[s_uart_dev[uart_id].last_dmarx_size]), recv_size);
	s_uart_dev[uart_id].last_dmarx_size = recv_total_size;
}

代码解析:

  • 这里有三个中断处理函数:半满中断、满中断和空闲中断处理函数,
  • 半满中断和全满中断:我们设置DMA接收区域的长度128Byte,DMA的CNDTR寄存器的值为128,每接收一个字节数据,数值就减1。当该数值减少为64时,进入半满中断。当数值减少为0时,进入全满中断;
  • 空闲中断:除非每帧数据刚好是半帧长度或者满帧长度,否则空闲中断处理必然有效;

案例:


初始条件下,以帧数据长度10为例,连续发送6次都不会进入半满中断,仅进入空闲中断;第7次时便会进入半满中断,同时也会进入空闲中断(图片中NDT的值不为64);第13次时便会进入全满中断,同时也会进入空闲中断(图片中NDT的值不为0而是翻板到0X7E)。

相关推荐
zlinear数据采集卡17 小时前
D223上位机C#开发实战:从帧解析到波形显示的完整实现
开发语言·arm开发·嵌入式硬件·fpga开发·开源·c#
ACP广源盛1392462567317 小时前
蚂蚁百灵 Ling‑3.0‑flash 开源 + 昇腾 0‑Day 原生适配@ACP#GSV9001E 在国产算力矩阵中的机会与落地场景
大数据·人工智能·分布式·单片机·嵌入式硬件
Rocktech_ruixun19 小时前
机器人端侧大模型部署对主板有哪些要求?瑞迅主控板分级方案对比
人工智能·嵌入式硬件·机器人
Lzh编程小栈20 小时前
【嵌入式底层】SPI超透彻详解:通信原理、四线结构、四种模式、寄存器底层 + 面试全集
c语言·stm32·单片机·面试·职场和发展
Rocktech_ruixun20 小时前
机器人数据采集能力取决于什么?瑞迅科技RK3588/3576核心板方案深度解析
人工智能·嵌入式硬件·机器人
水果里面有苹果20 小时前
28-DRV8825PWPR步进电机驱动器
单片机
恒锐丰科技韩生20 小时前
率能 SS6625E|3.0~20V 单通道 H 桥直流电机驱动 SOP8 电子锁玩具机器人分享
嵌入式硬件·硬件工程
zlinear数据采集卡20 小时前
D223 ADC数据处理流水线:从原始采样值到工程单位的完整转换链
开发语言·arm开发·嵌入式硬件·fpga开发·开源·c#
Dr.kangder1 天前
嵌入式面试总结(十八)——JTAG调试
嵌入式硬件·面试·职场和发展·架构·嵌入式
恒锐丰科技韩生1 天前
率能 SS6226|2.4~7.2V 低压双通道双 H 桥电机驱动 SOP16 玩具小家电专用芯片
嵌入式硬件·硬件工程