通用输入输出接口.ppt
第五章 通用输入输出(GPIO),目 录,GPIO简介|数字量输入/输出GPIO,GPIO是通用型输入/输出(General Purpose I/O)的简称,主要用于工业现场需要用到数字量输入/输出的场合,例如:,继电器、LED、蜂鸣器等的控制;传感器状态、高低电平等信息的输入等。,目 录,GPIO特性描述|I/O结构,大部分GPIO为推挽输出,具有完整I2C功能的是开漏结构;,管脚可承受最大5V的输入电压。,正常拉出灌入电流为4mA,短 时间极限值40mA;,GPIO特性描述|通用输入输出,所有GPIO寄存器位于AHB总线上,可以进行高性能的 CPU快速访问,支持Cortex-M3位带操作;,GPIO允许进行DMA数据操作。,可配置为上拉/下拉电阻、开漏和中继模式;,LPC1700系列Cortex-M3有5组GPIO,多达70个通用I/O管脚(100管脚封装);,GPIO特性描述|中断,LPC1700系列Cortex-M3的P0和P2还具有中断功能,P0和P2每个引脚都可配置为上升沿、下降沿或双边沿中断。,GPIO中断还具有掉电唤醒功能,目 录,GPIO输入输出|I/O相关寄存器,LPC1700系列Cortex-M3具有5个端口,所以具有5组控制寄存器。一个GPIO引脚在某一时刻,只受4个位的控制,这4个位分布在该GPIO所属端口的4个控制寄存器中。,GPIO输入输出|I/O相关寄存器,LPC1700系列Cortex-M3的高速GPIO口还可通过一些字节和半字访问的寄存器来控制,如FIOxDIR0/1/2/3、FIOxSET0/1/2/3、FIOxCLRL/U等。,GPIO相关寄存器描述,PINSELx,FIOxDIR,FIOxCLR,FIOxPIN,FIOxSET,in,out,1,0,GPIO相关寄存器描述FIOxPIN,该寄存器反映了当前引脚的状态。FIOxPIN中的x对应于某一个端口,如P1口对应于FIO1PIN。所以芯片存在多少个端口,就有多少个IOxPIN分别与之对应。写该寄存器会将值保存到输出寄存器,具体使用稍后介绍。注意:无论引脚被设置为输入还是输出模式或者配置为其他可选的数字功能,都不影响引脚状态的读出。,PINSELx,FIOxDIR,FIOxCLR,FIOxPIN,FIOxSET,in,out,1,0,GPIO相关寄存器描述FIOxDIR,当引脚设置为GPIO输出模式时,可使用该寄存器控制引脚的方向。向某位写入1使对应引脚作为输出功能,写入0时作为输入功能。作为输入功能时,引脚处于高阻态。,PINSELx,FIOxDIR,FIOxCLR,FIOxPIN,FIOxSET,in,out,1,0,GPIO相关寄存器描述FIOxSET,当引脚设置为GPIO输出模式时,可使用该寄存器从引脚输出高电平。向某位写入1使对应引脚输出高电平。写入0无效。从该寄存器读回的数据为GPIO输出寄存器的值。该值不反映外部环境对引脚的影响。,PINSELx,FIOxDIR,FIOxCLR,FIOxPIN,FIOxSET,in,out,1,0,GPIO相关寄存器描述FIOxCLR,当引脚设置为GPIO输出模式时,可使用该寄存器从引脚输出低电平。向某位写入1使对应引脚输出低电平。写入0无效。注意:读取该寄存器无效,不能读回输出寄存器的值。,GPIO输入输出|I/O功能框图,IN,OUT,1,0,GPIO,PINSELx,FIOxDIR,FIOxSET,FIOxCLR,FIOxPIN,FIOxMASK,输出置位寄存器,模式选择寄存器,功能选择寄存器,端口屏蔽寄存器,输出清零寄存器,端口方向控制寄存器,管脚值寄存器,复位后默认所有GPIO为上拉输入模式,GPIO输入输出|I/O屏蔽寄存器,采用屏蔽寄存器FIOxMASK来屏蔽某些位,可以让软件在一个写操作过程中设置GPIO相应的位而又不影响到其他的管脚。,u=电平不变,GPIO输入输出|I/O操作流程,FIOxPIN,GPIO输入,GPIO输出,1,高电平,1,输出操作流程,输入操作流程,1,使用GPIO注意要点,引脚设置为输出方式时,输出状态由FIOxSET和FIOxCLR中最后操作的寄存器决定;大部分GPIO输出为推挽方式(个别引脚为开漏输出),正常拉出/灌入电流均为4mA(短时间极限值40mA);复位后默认所有GPIO为输入模式。,.LPC_PINCON-PINSEL0.,C代码:,PINSEL0,FIO0DIR,FIO0CLR,FIO0PIN,FIO0SET,in,out,1,0,GPIO应用示例设置P0.0输出高电平,P0.0,.uint32_t PinStat;LPC_PINCON-PINSEL0.,C代码:,PINSEL0,FIO0DIR,FIO0CLR,IO0PIN,FIO0SET,in,out,1,0,GPIO应用示例读取P0.0引脚状态,P0.0,FIO0PIN,#define DataBus 0 xFF PINSEL0.,使用FIOxSET和FIOxCLR实现:,GPIO应用示例输出多位数据至IO口,在需要将多位数据同时输出到某几个IO口线时,通常使用FIOxSET和FIOxCLR来实现,在某些情况下也可以使用FIOxPIN寄存器实现。后者可以在多个IO口上直接输出0和1电平。本例将8位无符号整形变量Data的值输出到P0.0P0.7。,数据输出线:,#define DataBus 0 xFF PINSEL0.,GPIO应用示例输出多位数据至IO口,在需要将多位数据同时输出到某几个IO口线时,通常使用IOxSET和IOxCLR来实现,在某些情况下也可以使用IOxPIN寄存器实现。后者可以在多个IO口上直接输出0和1电平。本例将8位无符号整数变量Data的值输出到P0.0P0.7。,使用FIOxPIN实现:,数据输出线:,GPIO应用程序示例控制LED,int main(void)unsigned long i;LPC_GPIO2-FIODIR=0 x0000000F;/设置方向为输出 LPC_GPIO2-FIOSET=0 x0000000F;/初始化输出高电平,关闭指示灯while(1)LPC_GPIO2-FIOCLR=0 x0000000F;/输出低电平,点亮指示灯 for(i=1000000;i 0;i-);LPC_GPIO2-FIOSET=0 x0000000F;/输出高电平,关闭指示灯 for(i=1000000;i 0;i-);,GPIO应用程序示例控制按键,int main(void)unsigned long i;/设置方向为输出,P2.11、P2.12方向的输入 LPC_GPIO2-FIODIR=0 x0000000F;/初始化输出高电平,关闭指示灯 LPC_GPIO2-FIOSET=0 x0000000F;while(1)/判断按键1 P2.11是否按下及处理程序 if(LPC_GPIO2-FIOPIN),GPIO应用程序示例控制按键,/切换LED1的状态/原来输出为高电平,则改为输出低电平 if(LPC_GPIO2-FIOPIN),GPIO应用示例状态机控制按键,一般的按键输入软件接口程序非常简单,在程序中一旦检测到按键输入口为低电平(有时可能为高),便采用软件延时的方法来进行消抖,然后再次检测按键输入,如果再次确认为低电平则表示有按键按下,转入执行按键处理程序。如果延时后检测的电平为高电平则放弃本次按键检测,重新开始一次按键检测过程。在简单的系统中这种方法比较可以用,但是在复杂的系统实时性要求较高的系统中这种方法的CPU利用率比较低,造成资源的浪费。另外,由于在不同的产品系统中对按键功能的定义和使用方式也会不同,而且是多变的,加上在测试和按键处理的同时,MCU还要同时处理其他的任务(如显示、计算、计时等),因此编写键盘和按键接口的处理程序需要掌握有效的分析方法,具备较高的软件设计能力和程序编写的技巧。而采用状态机的方法是一种比较好的方法。,GPIO应用示例状态机控制按键,可将将按键抽象为3个状态:(1)未按下,假定为S0(2)确认有键按下,假定为S1(3)键释放状态,假定为S2。在一个系统中按键的操作是随机的,因此系统软件中要对按键进行循环查询。在按键检测过程中需要进行消抖处理,消抖的延时处理一般要10ms或20ms,因此取状态机的时间序列为10或20ms,这样不仅可以跳过按键消抖的影响,同时也远小于按键的稳定闭合时间,不会将按键过程丢失。,GPIO应用示例状态机控制按键,假定键按下时端口电平为0,未按下时为1(或者相反)。通过状态机实现按键检测的过程如下:首先,按键的初始态为S0,当检测到输入为1时,表示没有键按下,保持S0。当按键输入为0时,则有键按下,转入状态S1:按键确认状态。在S1状态时,如果输入的信号为1,则表示刚才的按键操作为干扰,则状态跳转到S0;如果输入信号为0,则表示确实有键按下,此时可以读取键状态,产生相应的按键标志或者将该事件存入消息队列。同时状态机切换到S2状态:按键释放状态。在S2状态,如果输入信号为高电平,表明按键释放,则切换到S0,否则保持S2状态。,GPIO应用示例状态机控制按键,/定义读取按键状态的宏,按键按下返回0,没有按下返回1#define key_input(LPC_GPIO2-FIOPIN)/读按键I/O电平,GPIO应用示例状态机控制按键,switch(key_state)casekey_state_0:/按键初始态 if(!key_press)/键被按下,状态转换到键确认态 key_state=key_state_1;break;,GPIO应用示例状态机控制按键,casekey_state_1:/按键确认态 if(!key_press)/按键仍按下,状态转换到键释放态 key_state=key_state_2;else/按键已抬起,转换到按键初始态 key_state=key_state_0;break;,GPIO应用示例状态机控制按键,case key_state_2:/按键释放态 if(key_press)/按键已释放,转换到按键初始态 key_state=key_state_0;/按键有按下,并且已经释放,按键确认输出为“1”key_return=1;break;default:break return key_return;,GPIO应用示例状态机控制按键,如何实现按键的长按和短按呢?,GPIO应用示例状态机控制按键,可将将按键抽象为4个状态:(1)未按下,假定为S0(2)确认有键按下,假定为S1(3)键稳定按下状态,假定为S2(4)键释放状态,假定为S3。,GPIO应用示例状态机控制按键,假定键按下时端口电平为0,未按下时为1(或者相反)。通过状态机实现按键检测的过程如下:首先,按键的初始态为S0,当检测到输入为1时,表示没有键按下,保持S0。当按键输入为0时,则有键按下,转入状态S1。在S1状态时,如果输入的信号为1,则表示刚才的按键操作为干扰,则状态跳转到S0;如果输入信号为0,则表示确实有键按下,此时可以读取键状态,产生相应的按键标志或者将该事件存入消息队列。同时状态机切换到S2状态。在S2状态,如果输入信号为1,则没有键按下,切换到S3;如果输入信号为0,则保持S2状态,并进行计数。如果计数值超过一定的门限值,则可以认为该按键为长按键事件或者键一直按下状态,如果未超过门限值,则认为是短按键事件,保持S2状态。在S3状态,如果输入信号为高电平,则切换到S0.,GPIO的主要功能有:1、设置引脚的方向;2、引脚输出高电平;3、引脚输出低电平,4、读取引脚的电平状态。,GPIO应用示例库函数的设计,/*GPIO模块宏定义*/定义端口名称#define GPIO_P0 0#define GPIO_P1 1#define GPIO_P2 2#define GPIO_P3 3#define GPIO_P4 4/定义端口方向名称#define IN 0#define OUT 1,GPIO应用示例库函数的设计,/*GPIO模块宏定义*/定义每个端口的引脚序号#define GPIO_Pin_0(unsigned int)0 x00000001)#define GPIO_Pin_1(unsigned int)0 x00000002)#define GPIO_Pin_2(unsigned int)0 x00000004)#define GPIO_Pin_3(unsigned int)0 x00000008)#define GPIO_Pin_4(unsigned int)0 x00000010)#define GPIO_Pin_5(unsigned int)0 x00000020)#define GPIO_Pin_6(unsigned int)0 x00000040),GPIO应用示例库函数的设计,/*函数名称:GPIO_GetPointer()*函数功能:获取指向选定端口的结构体的指针*入口参数:portNum:端口号,用GPIO_Px表示,x表示04*出口参数:pGPIO:指向选定端口的结构体的指针*其他:内部函数,不被外部调用,仅供本模块调用*/static LPC_GPIO_TypeDef*GPIO_GetPointer(unsigned char portNum)LPC_GPIO_TypeDef*pGPIO=NULL;/定义指向GPIO结构体的指针并初始化为0 switch(portNum)case 0:pGPIO=LPC_GPIO0;break;case 1:pGPIO=LPC_GPIO1;break;case 2:pGPIO=LPC_GPIO2;break;case 3:pGPIO=LPC_GPIO3;break;case 4:pGPIO=LPC_GPIO4;break;default:break;return pGPIO;,GPIO应用示例库函数的设计,/*函数名称:GPIO_SetDir()*函数功能:设置引脚方向*入口参数:portNum:端口号,用GPIO_Px表示,x表示04 pinNum:引脚号,用GPIO_Pin_x表示,x表示031 dir:引脚方向,用IN和OUT表示*出口参数:无*其他:同时设置多个引脚可以通过引脚号的或操作*/void GPIO_SetDir(unsigned char portNum,unsigned int pinNum,unsigned char dir)/获取指向要设定端口结构体的指针 LPC_GPIO_TypeDef*pGPIO=GPIO_GetPointer(portNum);if(dir)/方向为输出 pGPIO-FIODIR|=pinNum;else/方向为输入 pGPIO-FIODIR,GPIO应用示例库函数的设计,/*函数名称:GPIO_SetPin()*函数功能:设置引脚输出高电平*入口参数:portNum:端口号,用GPIO_Px表示,x表示04 pinNum:引脚号,用GPIO_Pin_x表示,x表示031*出口参数:无*其他:同时设置多个引脚可以通过引脚号的或操作*/void GPIO_SetPin(unsigned char portNum,unsigned int pinNum)/获取指向要设定端口结构体的指针 LPC_GPIO_TypeDef*pGPIO=GPIO_GetPointer(portNum);pGPIO-FIOSET=pinNum;/输出高电平,GPIO应用示例库函数的设计,/*函数名称:GPIO_ClrPin()*函数功能:设置引脚输出低电平*入口参数:portNum:端口号,用GPIO_Px表示,x表示04 pinNum:引脚号,用GPIO_Pin_x表示,x表示031*出口参数:无*其他:同时设置多个引脚可以通过引脚号的或操作*/void GPIO_ClrPin(unsigned char portNum,unsigned int pinNum)/获取指向要设定端口结构体的指针 LPC_GPIO_TypeDef*pGPIO=GPIO_GetPointer(portNum);pGPIO-FIOCLR=pinNum;/输出低电平,GPIO应用示例库函数的设计,/*函数名称:GPIO_ReadPin()*函数功能:读取引脚电平值*入口参数:portNum:端口号,用GPIO_Px表示,x表示04 pinNum:引脚号,用GPIO_Pin_x表示,x表示031*出口参数:val:返回引脚电平,1表示高电平,0表示低电平*其他:采用FIOPIN读取引脚状态*/unsigned char GPIO_ReadPin(unsigned char portNum,unsigned int pinNum)unsigned char val;/返回引脚电平,1表示高电平,0表示低电平/获取指向要设定端口结构体的指针 LPC_GPIO_TypeDef*pGPIO=GPIO_GetPointer(portNum);if(pGPIO-FIOPIN,GPIO应用示例库函数的设计,#include LPC17xx.h/包含器件头文件int main(void)unsigned long i;/设置引脚P2.0和P2.11为GPIO功能 LPC_PINCON-PINSEL4=LPC_PINCON-PINSEL4,GPIO应用示例库函数的设计,while(1)/判断按键KEY1P2.11是否按下及处理程序 if(!(GPIO_ReadPin(GPIO_P2,GPIO_Pin_11)/如果有按键按下/延时时间较短可能出现连击 for(i=100000;i 0;i-);/软件延时去抖动 if(!(GPIO_ReadPin(GPIO_P2,GPIO_Pin_11)/按键依然按下/等待按键释放 while(!(GPIO_ReadPin(GPIO_P2,GPIO_Pin_11);/切换LED1的状态:原来输出为高电平,则改为输出低电平 if(GPIO_ReadPin(GPIO_P2,GPIO_Pin_0)GPIO_ClrPin(GPIO_P2,GPIO_Pin_0);else/原来输出为低电平,则改为输出高电平 GPIO_SetPin(GPIO_P2,GPIO_Pin_0);,GPIO应用示例库函数的设计,OVER,