DMA与空间中断

本文介绍了STM32的DMA技术,如何通过DMA实现串口发送和接收数据,并详细讲解了如何配置CubeMX以及编写相关代码。实验中,使用串口DMA发送不定长数据,并通过空闲中断接收,确保了数据包的完整性和效率。

文章目录

    • DMA简介
    • STM32的DMA
    • DMA中断
    • 全局中断
    • 使用串口DMA发送数据(实验1)
      • Cube设置
      • 代码修改
    • 空闲中断
    • 串口通讯协议的数据包
    • 使用串口空闲中断接收数据(实验2)
      • 编写代码
    • 参考资料

DMA简介

  • Direct Memony Access,直接内存访问
  • 可以不经过CPU,直接将某一地址的数据复制到另一地址
  • 节省CPU时间
  • DMA实质上相当于不经过CPU自动完成* p1=* p2

STM32的DMA

  • STM32具有数个DMA,每个DMA具有多个通道
  • 同一时间每个DMA只能有一个通道在复制数据
  • 类似中断,DMA的通道之间也有优先级的设置
  • 每个通道可以在外设和内存之间交换数据,或者内存和内存之间交换数据
  • DMA的传输可以由其他外设触发或由软件触发
  • 每次传输之后,内存的地址可以自动+1

DMA中断

  • 当DMA传输完成或传输错误时可以产生中断
  • HAL库会自动启动并处理DMA中断,无需自行配置

全局中断

  • 点开 USART3 的设置页面,打开DMA Settings 的标签页,点击 Add,于select处选择USART3_RX,将优先级(priority)配置为非常高,再将mode配置为循环模式(circular)
    最后最后开启USART3的全局中断

使用串口DMA发送数据(实验1)

  • UART1使用DMA发送数据

  • UART6使用中断接收数据

Cube设置

在之前串口实验基础上打开Cube,在Connectivity的USART1中的DMA Settings中

添加一个DMA Request,选择TX

然后就很之前设置一样,生成代码

代码修改

把代码中的HAL_UART_Transmit_IT改为HAL_UART_Transmit_DMA即可

空闲中断

  • 串口处于空闲状态,即连续一个字节的时间RX处于高电平触发
  • 可以使用空闲中断配合DMA接收不定长的数据

串口通讯协议的数据包

  • 串口是一种接口,在这个接口是可以实现通讯协议
  • 常见的串口通信协议的一个数据包一般可以包含以下部分
    • 一个固定值起始字节
    • 接收方地址(仅用于大于2个设备时)
    • 数据量
    • 实际数据
    • 校验字节(例如CRC8检验)
    • 一个固定值结束字节
  • 有时数据量是不确定的,需要接收方进行处理
  • 如果数据包没有结束字节和数据量字节,一般需要利用空闲中断
  • 一般使用空闲中断接收数据

使用串口空闲中断接收数据(实验2)

  • UART1使用DMA发送不定长的数据
  • UART6使用DMA接收数据
    • 接收使用空闲中断函数
    • 添加UART6的DMA

编写代码

首先,编写一个不定长的数据,把txDataBuffer和rxDataBuffer的容量扩大,把4改为10

同时定义两个uint8_t类型的数据长度

/* USER CODE BEGIN PV */
uint8_t txDataBuffer[10],rxDataBuffer[10];//unsign char类型
uint32_t rxDate;//unsign int类型
uint8_t txDatelen,rxDatelen;//长度为一个字节,使用uint8_t类型
/* USER CODE END PV */

这里我们可以引入随机数来定义这个数据的长度或者使用一个循环队列来生成这个不定长数据

在STM32Cube中也可以在Security的RNG中进行勾选来产生一个硬件随机数

这里我们使用循环队列来生成随机数,更改原来的回调函数

 void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin==GPIO_PIN_0)
	{
		uint32_t temp =HAL_GetTick();
		*((uint32_t*)txDataBuffer) = temp;
       
    //循环队列来使数据长度变化(不定长数据)
    txDatelen++;//数据长度进行递增
    if(txDatelen==5)
    {
      txDatelen =0;
    }//即数据长度从1~4进行变化
        
		while(huart1.gState !=HAL_UART_STATE_READY);//保护数据程序
		HAL_UART_Transmit_DMA(&huart1,txDataBuffer,txDatelen +4);//使用DMA通道
	}
}

然后把我们之前写的接收函数注释掉

  /* USER CODE BEGIN 2 */
//HAL_UART_Receive_IT(&huart6,txDataBuffer,sizeof(rxDataBuffer));
  /* USER CODE END 2 */

然后调用一个UARTEx函数

  /* USER CODE BEGIN 2 */
//HAL_UART_Receive_IT(&huart6,txDataBuffer,sizeof(rxDataBuffer));
HAL_UARTEx_ReceiveToIdle_DMA(&huart6,rxDataBuffer,sizeof(rxDataBuffer));//串口6的DMA通道的接收函数
  /* USER CODE END 2 */

把原来接收的回调函数注释掉

然后编写UARTEx的回调函数

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef*huart,uint16_t size)
{
  	if(huart == &huart6)
	{
		rxDate =*((uint32_t*)rxDataBuffer);
    	rxDatelen=size;
		HAL_UARTEx_ReceiveToIdle_DMA(&huart6,rxDataBuffer,sizeof(rxDataBuffer));//进行重复调用接收函数
	}
};

然后编译烧录。

参考资料

CH3.2 UART 第2讲 DMA与空闲中断【南工骁鹰嵌入式软件培训】

### DMA空闲中断的基础概念 DMA(Direct Memory Access,直接内存访问)是一种允许外设存储器之间数据传输而无需CPU干预的技术。通过使用DMA控制器,可以显著提高系统的效率并减少CPU负载[^1]。 在嵌入式系统中,尤其是基于STM32系列微控制器的应用场景下,DMA常被用来实现高效的数据传输操作。例如,在串口通信过程中,利用DMA配合空闲中断功能,可以在接收到一定量的数据或者检测到线路空闲状态时触发特定事件处理逻辑[^2]。 ### 配置DMA空闲中断的具体方法 对于STM32L476G-DISCO开发板上的UART4接口而言,要启用其DMA模式下的空闲中断接收功能,则需按照如下方式进行设置: #### 初始化配置阶段 - **使能相关时钟资源** 确保所有涉及的外设及时钟树节点均已开启。 - **定义缓冲区大小及地址映射关系** 设定好目标寄存器以及实际物理RAM之间的关联参数,比如最大记录长度`MAX_REC_LENGTH`所对应的字节数目等信息。 ```c /* 定义全局变量 */ uint8_t RxBuffer[MAX_REC_LENGTH]; ``` - **调用初始化函数完成基础属性设定** 利用HAL库提供的API服务来指定波特率、停止位数等相关选项值。 ```c MX_USART3_UART_Init(); ``` #### 启动DMA通道及其对应控制机制部分 当一切准备就绪之后,就可以正式激活该链路了。下面展示了一段典型的代码片段用于启动DMA引擎的同时也注册了一个针对IDLE信号敏感型回调入口点。 ```c // 开启串口DMA空闲中断接收 HAL_UARTEx_ReceiveToIdle_DMA(&huart3, (uint8_t*)RxBuffer, MAX_REC_LENGTH); // 关闭DMA半满中断 __HAL_DMA_DISABLE_IT(hdma_usart3_rx, DMA_IT_HT); ``` 上述代码实现了两件事情:一是开启了串口DMA空闲中断接收;二是禁用了DMA半满中断,这有助于优化性能表现并防止不必要的干扰发生。 ### 常见错误分析解决方案 尽管遵循标准流程能够极大程度上降低出错概率,但在实践当中仍然可能出现各种异常状况。以下是几种常见的问题描述连同相应的排查思路: 1. **未能成功捕获任何有效字符流** - 可能原因:硬件连接存在问题或者是软件层面未正确定义工作模式。 - 解决办法:仔细核对接线方式是否符合预期设计图纸的要求;另外重新审查程序清单中的每一项指令语句是否有遗漏之处。 2. **频繁丢失某些特定位置处的关键字段** - 可能原因:缓存容量不足导致溢出现象产生。 - 解决办法:适当增加分配给临时储存空间的尺寸规模直至满足需求为止。 3. **偶尔会出现随机性的崩溃重启行为** - 可能原因:存在非法指针解引用动作或是越界读写操作。 - 解决办法:借助调试工具逐步定位具体故障源所在区域并通过修正算法逻辑加以规避。 ### 进一步学习建议 为了更深入理解如何运用DMA技术结合不同类型的外部设备协同作业,推荐参考官方文档资料集以及社区分享的经验总结文章。这些材料通常包含了详尽的操作指南实例演示视频等内容可以帮助开发者快速掌握核心技术要点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

书阁下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值