stm32 -- 中断

📅 2026/8/6 16:30:38
stm32 -- 中断
tags:“#中断”“#stm32”“#中断优先级”“#外部中断”“#NVIC”“#串口”“#舵机”“#按键”date: 2026-08-04中断的基础概念1单片机中断编程常规程序 – 突发事件 – 处理突发事件 – 继续常规程序其中突发事件称为中断源处理突发事件的代码叫做中断响应函数2突破了按部就班的做事儿方式能够更快的响应突发事件3回顾之前的闪灯实验和串口接收实验[[LED闪灯实验]] [[简单数据接收实验]]4串口接收数据的时候存在两级缓冲区一级缓冲和二级缓冲如果发送过来的数据不及时处理就会丢失5思路main(){while(1){//亮//延迟//灭//延迟}}void中断响应函数{// 读取数据//处理数据}闪灯程序正常进行当接收到串口的数据时调用中断响应函数对数据进行处理处理过后继续闪灯程序。当中断发生时硬件会自动调用中断响应函数中断优先级中断优先级分组0~15从高到低抢占优先级子优先级。![[5077253bbfe0ed20cc27d9cf3d991807.jpg]]中断优先级就是中断的紧急程度根据程序设计的需求自己设置的抢占优先级高的可以中断嵌套响应优先级高的可以优先排队中断排队规则优先级越高排队越靠前优先级相同时按照中断号排队。中断嵌套在程序执行过程中如果发生中断单片机会调用对应的中断服务函数。若在该函数执行期间又产生了新的紧急中断且该中断无法等待排队系统便会打断当前中断服务函数的执行转而处理新的中断。这种在一个中断内部嵌套另一个中断的现象称为中断嵌套。发生中断嵌套的条件新中断的抢占优先级更高。当中断发生的时候如果来了另外的中断信号当新来的中断的抢占优先级更高数字更小的时候就发生中断嵌套如果新来的中断抢占优先级更低那就要排队分组方式NVIC 通过 AIRCR 寄存器的 PRIGROUP 位把 4 位优先级拆分为抢占优先级 子优先级常用分组为分组 22 位抢占 2 位子如 CubeMX 默认配置分组编号PRIGROUP 值抢占优先级位数子优先级位数抢占优先级范围子优先级范围00110400~151100130~10~72101220~30~33110310~70~14111400~150说明抢占优先级 数字越小优先级越高可发生中断嵌套子优先级 同抢占优先级下排队顺序不能打断嵌套分组 4 时没有子优先级响应优先级全为 0依靠中断号排队EXTI外部中断1Extern Interrupt监测指定GPIO口的电平信号当其指定的GPIO口产生电平变化时EXTI将立刻向NVIC发送中断申请经过NVIC裁决后即可中断CPU主程序使CPU执行EXTI对应的中断程序支持的触发方式上升沿下降沿双边沿软件触发支持所有IO口,但是相同的Pin不能同时触发中断通道数16个GPIO_Pin外加PVD输出RTC闹钟USB唤醒以太网唤醒触发响应方式中断响应/事件响应事件响应当外部中断检测到引脚电平变化的时候触发事件外部中断的信号就不会通向CPU而是通向其他外设用来触发其他外设的操作比如触发ADC转换触发DMA等。2AFIO复用IO口AFIO主要用于引脚复用功能的选择和重定义在stm32中AFIO主要完成两个任务复用功能引脚重映射中断引脚选择NVIC模块1NVIC是单片机内部的一个模块全称是Nested Vectored Interrupt Controller --嵌套向量中断控制器负责管理单片机的中断。2![[00f9637b298ed228563fb94994b80f6e.jpg]]中断使能对应中断后面打上勾就相当于使能了这个中断。2图中的四个方框表示中断优先级。蓝色线可以移动控制抢占优先级和子优先级。![[Pasted image 20260724152848.png]]优先级分组![[Pasted image 20260724153433.png]]仲裁电路用来管理中断嵌套和中断排队的逻辑。中断响应函数存储在单片机的flash里面串口中断实验1实验目的通过串口调试助手控制板载LED的闪烁速度发送1是慢闪2是正常3是快闪2复习一下闪灯实验和UART串口实验[[LED闪灯实验]] [[简单数据接收实验]][[简单数据发送实验]]1.板载LED是与PC13引脚连接采用开漏接法。向pc13引脚写1是熄灭0是点亮 2.UART分别有一个发送引脚TX一个接收引脚RX对于UART1PA9引脚是TX引脚PA10引脚是RX引脚连接的时候USBtoTTL模块的RX和PA9相连TX和PA10相连GND引脚接地。 3.在发送实验中用到了HAL_UART_Transmit的编程接口。3第一步先实现LED的闪烁1.通过闪灯实验我们知道我们通过HAL_GPIO_WritePin向PC13引脚写1或者0同时通过HAL_Delay延迟函数来控制LED的闪灯频率。2![[Pasted image 20260725112319.png]]一般把全局变量的声明写在Private variables下面一对begin和end中间。3.在Private variables位置声明一个变量blinkinterval我们可以通过改变这个值来改变延迟的大小从而控制闪灯的频率。/* USER CODE BEGIN PV */staticuint32_tblinkinterval1000;/* USER CODE END PV */intmain(){while(1){HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);HAL_Delay(blinkinterval);HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);HAL_Delay(blinkinterval);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}}首先我们点击魔术棒选项选择c/c把代码优化关掉等会要调试。然后点击调试按钮。在view的watch windows选项选择watch1在下方窗口输入我们想监控的变量这里是blinkinterval然后右键将十六进制关掉。![[Pasted image 20260725114309.png]]第一个就是十六进制的选项![[Pasted image 20260725114327.png]]通过改变value的值可以看到LED闪烁的频率的变化。4)设置UART。选择异步模式其他参数保持默认比如波特率。重点在于NVIC SETTING是和过去的实验不同的地方。![[Pasted image 20260725115300.png]]串口1全局中断打勾enable5中断的使用方法 – 新的编程接口。HAL_StatusTypeDefHAL_UART_Receive_IT(UART_HandleTypeDef*huart,uint8_t*pData,uint16_tSize)作用通过串口以中断方式接收指定数量的数据非阻塞参数 huart填写串口句柄的指针参数 pData指向接收缓冲区的指针参数 Size 填写要接收数据的数量以字节为单位返回值返回操作结果HAL_OK 表示启动成功其他返回值表示失败。与HAL_UART_Receive阻塞式不同HAL_UART_Receive_IT不会等待数据接收完成而是注册中断后立即返回CPU 可以继续执行其他代码。当数据接收完成后硬件触发中断HAL 库会自动调用回调函数HAL_UART_RxCpltCallback需要在用户代码中实现该回调函数在里面处理接收完成后的逻辑。/* 在 while 循环前调用启动中断接收 */HAL_UART_Receive_IT(huart1,datarcvd,1);/* 在用户代码区重写回调函数 */voidHAL_UART_RxCpltCallback(UART_HandleTypeDef*huart){/* 判断是哪个串口触发的中断 */if(huarthuart1){/* 在这里处理接收到的数据 */if(datarcvd0){HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);}elseif(datarcvd1){HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);}/* 重新开启中断接收准备接收下一个数据 */HAL_UART_Receive_IT(huart1,datarcvd,1);}}关键点中断接收只生效一次每完成一次接收后如果想继续接收后续数据必须在回调函数中再次调用HAL_UART_Receive_IT重新开启中断。右边文件夹处有个drivers/stm32打开之后点击uart.c文件在文件的2622行![[Pasted image 20260725121145.png]]ctrlG可以检索到这个位置。weak弱方法可以覆盖这是我们要写的回调函数的函数原型我们写的函数名应和这个函数名完全一致。回调函数程序。voidHAL_UART_RxCpltCallback(UART_HandleTypeDef*huart){if(huarthuart1)// 固定的写法判断传进来的句柄是不是串口1{if(datarcvd1){blinkinterval1000;}elseif(datarcvd2){blinkinterval300;}elseif(datarcvd3){blinkinterval50;}HAL_UART_Receive_IT(huart1,datarcvd,1);}}总结1中断就是让cpu停止当前程序先去处理中断响应函数处理完响应函数之后继续先前的程序。2HAL_UART_Receive_IT这个编程接口的作用通过串口接收一个数据的同时触发中断调用回调函数。中断接收触发之后相当于派一个员工守在门口等着当有数据来的时候他就接收数据触发中断调用回调函数 他在等待的时候不影响cpu主程序的正常执行。3中断接收函数只生效一次若想完成接收后继续接收就需要在回调函数内再调用一次中断接收函数再派一个员工蹲守。当GPIO引脚检测到电平变化时会自动调用中断响应函数沿的方向由引脚电平的跳变方向决定与按下/抬起无关上升沿 Rising电平从低→高按键接GND上拉时松开低→高上升沿下降沿 Falling电平从高→低按键接GND上拉时按下高→低下降沿双边沿上升沿和下降沿都会触发本项目按键接 GND 上拉按下为低电平故配置 Falling edge下降沿触发