尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

零基础STM32入门教程--08-中断

零基础STM32入门教程--08-中断 STM32按键中断实验标准库专栏STM32F103入门教程环境Keil‑MDK STM32F103 标准库3.5版本什么叫中断CPU 放下当前任务去处理突发事件处理完返回继续执行原程序。例如你在看书没有打扰的情况下看一个小时后结束。当看书进行到30分钟的时候电话响了。第一种情况,你去接了电话通话5分种后结束然后继续看书30分钟。第二种情况你不接电话等到书看完后再来处理电话问题。第一种情况说明你是支持中断第二种说明你不支持中断。假如这个电话对你很重要你又没有接到这种情况当然不希望发生。用中断功能处理紧急重要的事情普通的事情顺序处理。一、STM32F103 中断分类内核异常Reset 复位NMI 不可屏蔽中断HardFault 硬件错误异常MemManage 存储器管理错误BusFault 总线错误UsageFault 使用错误SysTick 系统滴答定时器内核定时器中断外设中断定时器中断串口中断 USART/UARTDMA 中断ADC 中断SPI 中断I2C 中断CAN 中断-USB 中断外部中断外部引脚电平触发来自芯片外面信号。上面很多的名词初学可能没有见过先不用过多理会。本节主要是使用外部中断来处理按键事件。二、外部中断2.1 EXTI中断线比如PA0,PB1,PC2这些引脚的电平突然由高变低或由低变高会触发一个中断事件这个事件就会去执行一个函数我们的一部份工作就在这个函数里面执行。由于中断的数量太多必须要有一套中断机制来一层层来处理。简单说一下比如PB12有没有配置为中断使能是低电平触发还是高电平触发如果有多个中断来要先处理哪一个中断这么多的中断事件要调用哪个中断函数等等GPIO的引脚有很多个某一个GPIO引脚是如何挂到中断线上如果GPIOX0~15,X是A,B,C,D,E,F,G。如果每个引脚都有独立的中断线,那么要16*7112根中断线,这样太浪费资源。STM32F10X的外部中断如下图设计图上看出EXTI0只能连接所有端口的 0 号引脚PA0, PB0, PC0…以此类推。EXTI 线映射16 根 EXTI 线EXTI0~EXTI15 对应 GPIO_PIN0~15多个 GPIO 可以映射到同一根 EXTI。这里面有个问题如果PA0,PB0同时使能中断会发生什么问题大家可以自己测试。(实际项目不能这么做!)2.2 NVIC 嵌套向量中断控制器Nested Vectored Interrupt Controller。你可以把它形象地理解为微控制器内部的“中断交通指挥中心”。它的主要职责是管理微控制器中所有的中断和异常确保系统能够高效、实时地响应各种突发事件。包含中断优先级管理、支持中断嵌套、向量跳转、自动现场保护与恢复等功能。优先级分组:抢占优先级和子优先级如下图。一共可以分为5个组一共5个bit可以用来配置。 根据不同的不组可以有不同的抢占优先级和子优先级。初学建议使用优先级分组NVIC_PriorityGroup_4,只有0~15一共16个抢占不用考滤子优先级的问题。抢占优先级决定能不能抢别人数字越小越能抢。子优先级不能抢别人只有多个中断同时到来时用来排先后顺序。三、工程与程序编写上面说的这些可能不太好理解程序可以帮助理解。3.1 工程复制复制上节课KEY整个工程文件夹重命名为EXTI同时把工程文件KEY.uvprojx重命名为EXTI.uvprojx双击打开工程。软件开发的好处有一条就是程序复用。比如测试稳定的函数后面可以一直用新写的函数也要长期测试稳定才能放到项目里面。3.2 添加中断驱动文件在工程目录EXTI\Hardware文件夹下新建子文件夹Exti。Keil工程右键Hardware分组 →Add New Item to Group Hardware新建exit.c,exti.h文件。exti.h#ifndef __EXTI_H //防止重复包含编译报错 #define __EXTI_H void exit_init(void); #endifexit.c#include exti.h #include stm32f10x.h #include stdio.h void exit_init(void) { EXTI_InitTypeDef exti_init_structure; //外部中断初始化结构体 NVIC_InitTypeDef nvic_init_structure; //嵌套向量中断控制器初始化结构体 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//外部中断需要使能AFIO时钟 GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource12); exti_init_structure.EXTI_Line EXTI_Line12; //外部中断线12 PB12只能接到 EXTI_Line12 exti_init_structure.EXTI_Mode EXTI_Mode_Interrupt; //中断模式 exti_init_structure.EXTI_Trigger EXTI_Trigger_Rising; //上升沿触发,接下时电平由低到高转变 exti_init_structure.EXTI_LineCmd ENABLE; //中断线使用 EXTI_Init(exti_init_structure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器 nvic_init_structure.NVIC_IRQChannel EXTI15_10_IRQn; //使能按键所在的外部中断通道 nvic_init_structure.NVIC_IRQChannelPreemptionPriority 0x0; //抢占优先级0 nvic_init_structure.NVIC_IRQChannelSubPriority 0x00; //子优先级 nvic_init_structure.NVIC_IRQChannelCmd ENABLE; //使能外部中断通道 NVIC_Init(nvic_init_structure); } //中断函数 void EXTI15_10_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line12) ! RESET){ //有效中断 EXTI_ClearITPendingBit(EXTI_Line12); //清除LINE12线路挂起位 printf(EXTI_Line12 中断 \r\n);//这里只是测试实际项目最好不要在中断里面打印 } }EXTI15_10_IRQHandler这是一个外部中断函数这个函数的名称是不能改变的。打开startup_stm32f10x_md.s;External Interrupts DCD WWDG_IRQHandler;Window Watchdog DCD PVD_IRQHandler;PVD through EXTI Line detect DCD TAMPER_IRQHandler;Tamper DCD RTC_IRQHandler;RTC DCD FLASH_IRQHandler;Flash DCD RCC_IRQHandler;RCC DCD EXTI0_IRQHandler;EXTI Line0DCD EXTI1_IRQHandler;EXTI Line1DCD EXTI2_IRQHandler;EXTI Line2DCD EXTI3_IRQHandler;EXTI Line3DCD EXTI4_IRQHandler;EXTI Line4DCD DMA1_Channel1_IRQHandler;DMA1 Channel1DCD DMA1_Channel2_IRQHandler;DMA1 Channel2DCD DMA1_Channel3_IRQHandler;DMA1 Channel3DCD DMA1_Channel4_IRQHandler;DMA1 Channel4DCD DMA1_Channel5_IRQHandler;DMA1 Channel5DCD DMA1_Channel6_IRQHandler;DMA1 Channel6DCD DMA1_Channel7_IRQHandler;DMA1 Channel7DCD ADC1_2_IRQHandler;ADC1_2 DCD USB_HP_CAN1_TX_IRQHandler;USB High Priority or CAN1 TX DCD USB_LP_CAN1_RX0_IRQHandler;USB Low Priority or CAN1 RX0 DCD CAN1_RX1_IRQHandler;CAN1 RX1 DCD CAN1_SCE_IRQHandler;CAN1 SCE DCD EXTI9_5_IRQHandler;EXTI Line9..5DCD TIM1_BRK_IRQHandler;TIM1 Break DCD TIM1_UP_IRQHandler;TIM1 Update DCD TIM1_TRG_COM_IRQHandler;TIM1 Trigger and Commutation DCD TIM1_CC_IRQHandler;TIM1 Capture Compare DCD TIM2_IRQHandler;TIM2 DCD TIM3_IRQHandler;TIM3 DCD TIM4_IRQHandler;TIM4 DCD I2C1_EV_IRQHandler;I2C1 Event DCD I2C1_ER_IRQHandler;I2C1 Error DCD I2C2_EV_IRQHandler;I2C2 Event DCD I2C2_ER_IRQHandler;I2C2 Error DCD SPI1_IRQHandler;SPI1 DCD SPI2_IRQHandler;SPI2 DCD USART1_IRQHandler;USART1 DCD USART2_IRQHandler;USART2 DCD USART3_IRQHandler;USART3 DCD EXTI15_10_IRQHandler;EXTI Line15..10DCD RTCAlarm_IRQHandler;RTC Alarm through EXTI Line DCD USBWakeUp_IRQHandler;USB Wakeup fromsuspend上面就是中断向量表如果你不知道中断函数是哪来的可以到这里找。函数名称是一样的函数的返回值和参数都是VOID.上面的EXTI_GetITStatus和EXTI_ClearITPendingBit 这些函数从哪来?右键这个函数弹出菜单-Go To Definition of …就会跳到stm32f10x_exti.c文件里面的这个函数有些英文说明翻译一下。初学不用看这个函数的具体实现但有知道这个函数的功能。/** * brief Checks whether the specified EXTI line is asserted or not. * param EXTI_Line: specifies the EXTI line to check. * This parameter can be: * arg EXTI_Linex: External interrupt line x where x(0..19) * retval The new state of EXTI_Line (SET or RESET). */ITStatusEXTI_GetITStatus(uint32_tEXTI_Line){ITStatus bitstatusRESET;uint32_tenablestatus0;/* Check the parameters */assert_param(IS_GET_EXTI_LINE(EXTI_Line));enablestatusEXTI-IMREXTI_Line;if(((EXTI-PREXTI_Line)!(uint32_t)RESET)(enablestatus!(uint32_t)RESET)){bitstatusSET;}else{bitstatusRESET;}returnbitstatus;}3.3 添加标准库外设文件stm32f10x_exti.c到工程用到哪个外设就添加对应的库文件。3.4 添加头文件搜索路径把Hardware\Exti加入包含路径。3.5 main.c主函数#include stm32f10x.h #include led.h #include delay.h #include key.h #include usart.h #include exti.h #include stdio.h int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);// 设置中断优先级分组4 led_init(); delay_init(); usart1_init(115200); key_init(); exit_init(); while(1) { led_on(); delay_ms(1000); led_off(); delay_ms(1000); } }3.6 接线的方式和上一课是相同的只是程序修改了。3.7 程序效果有时按一下串口会打印一次EXTI_Line12 中断有时按一下可能会打印多次。如果在中断里面做延时滤波效果可能会好一些。实际项目最好不要在中断里面延时。实际项目中多数用定时器中断作为按键的判断。下节课讲定时器!资料下载参考资料网盘链接: https://pan.baidu.com/s/1BrH0JbUY6z7j7gAihTa4Dw提取码: qnws本节课完整工程例程网盘链接: https://pan.baidu.com/s/1rl6EIqi9m6kQ1JFjuSqINg提取码: bumc
返回列表