中断是处理器和外部设备的数据传输方式,一方通过申请中断的方式与另一方进行数据传输,收发双方可以同时进行工作。中断可以解决快速的CPU与慢速的外部设备之间传送数据时速度匹配问题,使CPU可以分时为多个外部设备服务和实时处理各种随机突发事件,提高计算机的利用率和可靠性。
中断服务程序:在响应一个特定中断的时候,处理器会执行的一个函数。
STM32的单个外设通常具备若干个可以引起中断的中断源,这些中断源通过指定的中断通道向内核申请中断,由于中断通道有限,多个中断源可能会共享一个中断通道。
GPIO引脚中断通道分配
STM32的中断优先级分为抢占优先级和子优先级,比较顺序为抢占优先级>>子优先级>>优先级编号(编号越小,优先级越高)。
STM32中断优先级分组
HAL_库初始化函数将优先级设置为第4组,公16级抢占优先级,没有子优先级。0号为最高,15号为最低。
HAL库外部中断处理流程
服务程序的属性定义为"weak",如果该函数没有在其他文件中定义,则使用该函数,否则则使用用户定义的函数。编程时相关参数设置和初始化工作在stm32CubeMx中完成,用户主要关注中断服务程序和外部中断回调函数的编写。
采用中断模式编程,当开关接高电平时,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灯状态被翻转,灯亮;接低电平时,灯灭。
上位机给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(直接存储器访问)用于外设和存储器之间进行高速数据传输,DMA传输过程的初始化和启动化由CPU完成,传输过程由DMA控制器来执行,无需CPU参与,从而节省CPU资源,提高利用率。
DMA框图
DMA控制器独立于内核,有DMA1和DMA2两个,外设要通过DMA来传输数据,必须先给DMA控制器发送DMA请求。每个控制器有8个数据流,每个数据流可以映射到若干个通道上,每个通道对应着不同的外设请求。每一个DMA控制器用于管理一个或多个外设的存储器访问请求,但同时间只能接收一个请求,通过总线仲裁器来协调各个DMA请求的优先级,还具备16字节的FIFO功能,源数据先送入FIFO,达到FIFO的触发阈值后,再传送到目标地址。
数据流可以理解为传输数据的管道,根据传输源和传输目标的不同,可以完成外设到存储器、存储器到外设和存储器到存储器的数据传输。
普通模式
传输结束即要传输数据的数量达到零后将不再产生DMA操作。若开始新的DMA传输,需在关闭DMA通道的情况下,重新启动DMA传输。
循环模式
每轮传输结束后,要传输的数据数量将自动用设置好的初始值进行加载,并继续响应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——指南者(秉火)