文章目录
一、中断
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——指南者(秉火)