EmbeddedSystemDevelopment嵌入式系统与应用第9章STM32外部中断设计9.1GPIO键盘设计9.2GPIO外部中断EXTI设计9.1GPIO键盘设计每个GPIO引脚都可配置为8种模式。GPIO端口如何进行键盘设计?下面两种办法效果一样。一是采用上拉输入模式,按键在没按下的时候,默认为高电平。–PE5–key1–PE6–key2二是直接采用浮空输入模式,在芯片外部接上拉电阻。按键原理图实现LED反转,main()函数intmain(void){/*configtheled*/LED_GPIO_Config();LED1(ON);/*configkey*/Key_GPIO_Config();while(1){if(Key_Scan(GPIOE,GPIO_Pin_5)==KEY_ON){/*LED1反转*/GPIO_WriteBit(GPIOC,GPIO_Pin_3,(BitAction)((1-GPIO_ReadOutputDataBit(GPIOC,GPIO_Pin_3))));}}}读取PC3的当前输出电平当前状态反相后写入到PC3实现LED反转,main()函数1、关于Led灯的代码,把前面写的led.c和led.h文件复制一份添加到工程就可以了。2、启动文件调用了SystemInit()将系统时钟SYSCLK配置为72MHz。3、接着进入到main函数,第一步先调用了在LED灯例程中编写的LED_GPIO_Config(),配置LED用到的I/O。4、再使用LED1(ON)宏,把LED设置为点亮状态。5、配置按键用到的I/O口Key_GPIO_Config函数。6、按键检测函数,按键时调用GPIO_WriteBit函数,实现灯反转。设计按键函数头文件bsp_key.h#ifndef__KEY_H//条件编译#define__KEY_H#includestm32f10x.h#defineKEY_ON0//按键按下标志#defineKEY_OFF1//无按键标志voidKey_GPIO_Config(void);uint8_tKey_Scan(GPIO_TypeDef*GPIOx,u16GPIO_Pin);#endif设计按键函数Key_GPIO_Config()#includebsp_key.hvoidKey_GPIO_Config(void){GPIO_InitTypeDefGPIO_InitStructure;/*开启按键端口GPIOE(PE5)的时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;GPIO_Init(GPIOE,&GPIO_InitStructure);}跟LED的GPIO初始化函数LED_GPIO_Config()类似。可用符号|同时配置多个:GPIO_Pin_5|GPIO_Pin_6;按键检测函数Key_Scan()/**输入:GPIOx、GPIO_Pin:待读取的端口、引脚*输出:KEY_OFF(没按下按键)、KEY_ON(按下按键)*/u8Key_Scan(GPIO_TypeDef*GPIOx,u16GPIO_Pin){/*检测是否有按键按下*/if(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin)==KEY_ON){Delay(10000);//延时消抖if(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin)==KEY_ON){while(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin)==KEY_ON);returnKEY_ON;}//等待按键释放elsereturnKEY_OFF;elsereturnKEY_OFF;}}检测是否有按键按下库函数GPIO_ReadInputDataBit(端口号,引脚号);返回引脚数据,0为低电平,KEY_ON,可能有按键按下,调用延时函数消抖;否则返回1为高电平,KEY_OFF,表示按键没有被按下。延时之后再次读取该引脚数据,若依然为低电平,表明确实有按键被按下了;否则返回KEY_OFF,表示没按键。while循环调用GPIO_ReadInputDataBit(),等待按键释放,条件变为假退出循环,返回表示按键被按下的标志KEY_ON。同理,通过输入不同的实参,来检测其它按键的引脚。这就是库的魅力!作业:课下任务1、进一步熟悉GPIO,掌握GPIO设计。2、掌握GPIO键盘实验,实验报告。9.2GPIO外部中断EXTI设计EXTI(Externalinterrupt):通过GPIO检测输入脉冲,引起中断事件,打断原来的代码执行流程,进入到中断服务函数,处理完后,再返回到中断之前的代码中执行。STM32的所有GPIO都可以用作外部中断源,可把按键轮询检测改为由中断来处理,大大提高软件执行的效率。Cortex内核具有强大的异常响应系统,能够打断当前代码执行流程的事件分为异常exception和中断interrupt,用一个异常向量表管理起来,编号为0~15的称为内核异常,而16以上的则称为外部中断。STM32向量表,优先级从-3至6的中断向量称为系统异常,优先级为负的不能设置优先级,如复位Reset、不可屏蔽中断NMI、硬错误Hardfault。从优先级7开始的称为外部中断,优先级可自行设置。STM32中断向量表STM32中断向量表-详见参考手册GPIO外部中断EXTI中断控制器NVIC属于Cortex内核的器件,能配置16种中断向量,超过16个中断向量时,必然有2个以上的中断向量是使用相同的中断种类。注意:相同种类的中断不能嵌套。GPIO与EXTI的连接方式:PAx~PGx端口的中断事件都连接到了EXTIx,可以分时复用。可以配置为下降沿中断,上升沿中断和上升下降沿中断这三种模式。EXTI最普通的应用就是接上一个按键,设置为下降沿触发,用中断来检测按键。外部中断0与NVIC的关系EXTI寄存器EXTI寄存器结构:typedefstruct{vu32IMR;vu32EMR;vu32RTSR;vu32FTSR;vu32SWIER;vu32PR;}EXTI_TypeDef;EXTI库函数NVIC寄存器NVIC库函数NVIC配置misc库中NVIC_Init()函数对NVIC初始化,用到NVIC_InitTypeDef结构体,其中四个成员:–NVIC_IRQChannel参数来选择将要配置的中断向量;–NVIC_IRQChannelCmd参数来进行使能(ENABLE)或关闭(DISABLE)该中断;–NVIC_IRQChannelPreemptionPriority成员要配置中断向量的抢占优先级;–NVIC_IRQChannelSubPriority需要配置中断向量的响应优先级。NVIC只可配置16种中断向量的优先级:编号越小,优先级别越高;抢占优先级:是指打断其它中断,会出现嵌套中断;响应优先级:先处理响应优先级高的中断;中断检测按键实验硬件连接:PE5–key1、PE6–key2,key1按下时,进入线中断处理函数,LED1状态取反。配置工程环境:–除使用GPIO和RCC片上外设;–还要使用exti片上外设,stm32f10x_exti.c包含了支持exti配置和操作的函数;–misc.c文件则包含了NVIC的配置函数;本实验中还会在stm32f10x_it.c中编写中断服务函数。Main函数配置好LED用到的I/O后,调用LED1()点亮一盏LED灯;配置中断,等待中断发生。intmain(void){/*configtheled*/LED_GPIO_Config();LED1(ON);/*extilineconfig*/EXTI_PE5_Config();/*waitinterrupt*/while(1){}}配置外部中断exti.cEXTI_PE5_Config()函数,配置PE5为线中断口,并设置中断优先级。主要步骤:–1.使能EXTIx线的时钟和第二功能AFIO时钟–2.配置EXTIx线的中断优先级–3.配置EXTI中断线I/O–4.选定要配置为EXTI的I/O口线和I/O口的工作模式–5.EXTI中断线工作模式配置EXTI_PE5_Config()函数8.voidEXTI_PE5_Config(void)9.{10.GPIO_InitTypeDefGPIO_InitStructure;11.EXTI_InitTypeDefEXTI_InitStructure;13./*configtheextiline(PE5)clockandAFIOclock*/14.RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE|RCC_APB2Periph_AFIO,ENABLE);16./*configtheNVIC(PE5)*/17.NVIC_Configuration();//NVIC初始化配置19./*EXTIlinegpioconfig(PE5)*/20.GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;21.GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;//上拉输入EXTI_PE5_Config()函数_续22.GPIO_Init(GPIOE,&GPIO_InitStructure);24./*EXTIline(PE5)modeconfig*/25.GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource5);//PE5设置为EXTI输入线26.EXTI_InitStructure.EXTI_Line=EXTI_Line5;27.EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;28.EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;//下降沿触发中断29.EXTI_InitStructure.EXTI_LineCmd=ENABLE;30.EXTI_Init(&EXTI_InitStructure);31.}GPIO端口的复用功能AFIOAFIO(alternate-functionI/O),GPIO除了用作普通的输入输出(主功能),还可以作为片上外设的复用输入输出,如串口,ADC,这些就是复用功能。GPIO还有重映射功能:重映射功能是指把原来属于A引脚的默认复用功能,转移到了B引脚进行使用(当然B引脚具有这个重映射功能)。当把GPIO用作EXTI外部中断或使用重映射功能的时候,必须开启AFIO时钟。代码的第14行,开启了AFIO的时钟。NVIC初始化配置EXTI_PE5_Config()调用了NVIC_Configuration()函数来配置NVIC控制器。8.staticvoidNVIC_Configuration(void)9.{10.NVIC_InitTypeDefNVIC_InitStructure;12./*Configureonebitforpreemptionpriority*/13.NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);15./*配置P[A|B|C|D|E]5为中断源*/16.NVIC_InitStructure.NVIC_IRQChannel=EXTI9_5_IRQn;17.NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;18.NVIC_I