C/C++教程

用stm32CubeMx和HAL库实现中断与DMA通信编程

本文主要是介绍用stm32CubeMx和HAL库实现中断与DMA通信编程,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

文章目录

    • 一、中断
      • 1.关于中断
        • 1)什么是中断
        • 2)中断响应过程
        • 3)中断优先级
      • 2.实例
        • 1) 中断方式读取按键控制LED灯
        • 2)用中断的方式实现接发串口通信
    • 二、DMA编程
      • 1.关于DMA
        • 1)什么是DMA
        • 2)DMA数据配置
      • 2.实例DMA通信
    • 三、总结
    • 四、参考资料

一、中断

1.关于中断

1)什么是中断

中断是处理器和外部设备的数据传输方式,一方通过申请中断的方式与另一方进行数据传输,收发双方可以同时进行工作。中断可以解决快速的CPU与慢速的外部设备之间传送数据时速度匹配问题,使CPU可以分时为多个外部设备服务和实时处理各种随机突发事件,提高计算机的利用率和可靠性。

2)中断响应过程

在这里插入图片描述

中断服务程序:在响应一个特定中断的时候,处理器会执行的一个函数。

3)中断优先级

STM32的单个外设通常具备若干个可以引起中断的中断源,这些中断源通过指定的中断通道向内核申请中断,由于中断通道有限,多个中断源可能会共享一个中断通道。

GPIO引脚中断通道分配
在这里插入图片描述

STM32的中断优先级分为抢占优先级和子优先级,比较顺序为抢占优先级>>子优先级>>优先级编号(编号越小,优先级越高)。

STM32中断优先级分组
在这里插入图片描述
HAL_库初始化函数将优先级设置为第4组,公16级抢占优先级,没有子优先级。0号为最高,15号为最低。

2.实例

HAL库外部中断处理流程
中断
服务程序的属性定义为"weak",如果该函数没有在其他文件中定义,则使用该函数,否则则使用用户定义的函数。编程时相关参数设置和初始化工作在stm32CubeMx中完成,用户主要关注中断服务程序和外部中断回调函数的编写。

1) 中断方式读取按键控制LED灯

采用中断模式编程,当开关接高电平时,LED亮灯;接低电平时,LED灭灯。

新建项目,根据自己的情况选择芯片,进入编程。
在这里插入图片描述
配置调试接口为Serial Wire
在这里插入图片描述
配置时钟源,选择Crystal/Ceramic Resonator
在这里插入图片描述
配置时钟树,配置HCLK频率为72HZ
在这里插入图片描述
分配引脚,将PA5设置为’‘GPIO_Output’’,作指示灯引脚。将PB15设置为"’'GPIO_EXTI15"外部中断功能,与外部中断线EXTI15连接作按键引脚。
在这里插入图片描述
在出现的引脚表中单击需要配置的引脚,配置外设参数,如下图所示。
在这里插入图片描述
在这里插入图片描述
使能对应的外部中断线EXTI LINE[15:10]
在这里插入图片描述

配置工程的相关信息参数,点击Generate Code,生成代码。
在这里插入图片描述

在这里插入图片描述
下降沿将触发中断,跳到中断服务函数(无需用户自己编写),中断服务函数检测是否发生中断,确认后清除中断标志,调用用户编写的中断回调函数。
在这里插入图片描述
在main.c外编写外部中断回调函数,如下图所示。
在这里插入图片描述

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if( GPIO_Pin == B1_EXTI_Pin)//判断外部中断源,这里没使用按键就不考虑按键消抖问题
	{
		HAL_GPIO_TogglePin(LD_GPIO_Port, LD_Pin);//翻转指示灯的状态
	}
}

将生成的hex文件烧进芯片中,注意boot0跳线,否则连接会超时。由于没有开关,用杜邦线代替开关,从PB15引一根杜邦线,连接电路。GPIO引脚初始电平是低电平,当开关接高电平时,产生上升沿触发中断,LED灯状态被翻转,灯亮;接低电平时,灯灭。
在这里插入图片描述

2)用中断的方式实现接发串口通信

上位机给STM32系统发’‘helloworld’’,上位机收到后原样发回给STM32系统。

配置串口外设,选择’‘UART1’’,设置成异步模式,无同步时钟,并设置串口通信的参数如下如所示。
在这里插入图片描述
使能串口1的中断,勾选Enabled,中断优先级使用2处的默认值。
在这里插入图片描述
用户宏定义及全局变量定义,RxFlag初始值为0,代表接收未完成。
在这里插入图片描述
在main.c中编写程序,使能接收中断。主函数什么都不做,只是静静地等待USART接收中断的产生,并在中断服务函数把数据回传。
在这里插入图片描述

HAL_UART_Receive_IT(&huart1,(uint8_t*)RxBuffer,LENTH);//使能接收中断

最后在main.c外编写外部中断回调函数,如下图所示。
在这里插入图片描述

void HAL_UART_RxClptCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance==USART1)//判断发生中断的串口
	{
		RxFlag=1;//置位,接收完成
		HAL_UART_Receive_IT(&huart1,(uint8_t*)RxBuffer,LENTH);//将字符原样发回
	}
}

将生成的hex文件烧录进芯片中后将boot0置0,打开串口调试助手,上位机给STM32系统法’‘helloworld’’,STM32系统将其原样发回,并循环这个过程。
在这里插入图片描述

二、DMA编程

1.关于DMA

1)什么是DMA

DMA(直接存储器访问)用于外设和存储器之间进行高速数据传输,DMA传输过程的初始化和启动化由CPU完成,传输过程由DMA控制器来执行,无需CPU参与,从而节省CPU资源,提高利用率。

DMA框图
在这里插入图片描述
DMA控制器独立于内核,有DMA1和DMA2两个,外设要通过DMA来传输数据,必须先给DMA控制器发送DMA请求。每个控制器有8个数据流,每个数据流可以映射到若干个通道上,每个通道对应着不同的外设请求。每一个DMA控制器用于管理一个或多个外设的存储器访问请求,但同时间只能接收一个请求,通过总线仲裁器来协调各个DMA请求的优先级,还具备16字节的FIFO功能,源数据先送入FIFO,达到FIFO的触发阈值后,再传送到目标地址。

数据流可以理解为传输数据的管道,根据传输源和传输目标的不同,可以完成外设到存储器存储器到外设存储器到存储器的数据传输。

2)DMA数据配置

  • 从哪里来到哪里去
    要关注传输来源和传输目的地。
  • 要传多少,单位是多少
    要关注传输数据的数量与单位。要想数据传输正确,源和目标地址存储的数据宽度还必须一致,而且要正确设置两边数据指针的增量模式。以串口向电脑发送数据为例,要发送的数据很多,每发完一个,存储器的地址指针应该加1,而串口数据寄存器只有一个,外设的地址指针就固定不变。
  • 什么时候能传输完成
    可以通过查询标志位和通过中断的方式来鉴别。传输分成两种模式:

普通模式
传输结束即要传输数据的数量达到零后将不再产生DMA操作。若开始新的DMA传输,需在关闭DMA通道的情况下,重新启动DMA传输。
循环模式
每轮传输结束后,要传输的数据数量将自动用设置好的初始值进行加载,并继续响应DMA请求。

  • 触发信号
    启动每一次DMA数据传输的动作。

2.实例DMA通信

STM32系统连续给上位机发送’‘hello windows!’’。

点击Add按钮,添加串口发送的数据流USART1_TX
在这里插入图片描述
双击USART1_TX,设置串口发送的DMA参数,如下图所示。
在这里插入图片描述
使能串口1的中断,中断优先级使用默认值。
在这里插入图片描述
在main.c中添加程序,如下图所示:
在这里插入图片描述

 HAL_UART_Transmit_DMA(&huart1, (uint8_t *)Senbuff, sizeof(Senbuff));//DMA传输数据
 HAL_Delay(1000);

HAL_UART_Transmit_DMA()是DMA方式的接口函数,功能是在DMA方式下发送一定量的数据,完成指定量数据的发送后,触发DMA中断。

将生成的hex文件烧录芯片,然后打开串口调试助手即可看到如下图所示结果:
在这里插入图片描述

三、总结

中断和DMA都是处理器和外部设备的数据传输方式,中断是CPU在执行程序的过程中,CPU暂停执行当前的程序转去处理突发事件,处理完毕后CPU又返回刚刚被中断的位置并继续执行。DMA是一种无须CPU的参与就可以让外设与系统内存之间进行双向数据传输的硬件机制,使用DMA可以使系统CPU从实际的I/O数据传输过程中摆脱出来,从而大大提高系统的吞吐率。两者的优缺点不尽相同,我们应该根据特定的应用场合情况去选择使用。

四、参考资料

【STM32】HAL库 STM32CubeMX教程十一—DMA (串口DMA发送接收)
零死角玩转STM32F103——指南者(秉火)

这篇关于用stm32CubeMx和HAL库实现中断与DMA通信编程的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!