4.2 GPIO模块的编程结构
为了实现快速入门,下面利用MCU的一个引脚控制一只发光二极管LED,如图4-2所示。为此,需要掌握配置引脚具体功能的可控制引脚高低电平输出的GPIO模块的基本用法。
4.2.1 端口与GPIO模块——对外引脚与内部寄存器
1. 100引脚LQFP封装MSR432P401R的GPIO引脚概述
MSR432P401R的大部分引脚具有多重复用功能,本节给出作为GPIO功能时的编程结构。100引脚封装的MSR432P401R芯片的GPIO引脚分为11个端口,标记为1~10和J,共84个引脚。端口作为GPIO引脚时,逻辑1对应高电平,逻辑0对应着低电平。GPIO模块使用系统时钟,从实时性细节来说,当作为通用输出时,高/低电平出现在时钟上升沿/下降沿。每个端口实际可用的引脚数因封装不同而有差异,下面给出各端口可作为GPIO功能的引脚数目及引脚名称。
(1)1口有8个引脚,分别记为P1.0~P1.7。
(2)2口有8个引脚,分别记为P2.0~P2.7。
(3)3口有8个引脚,分别记为P3.0~P3.7。
(4)4口有8个引脚,分别记为P4.0~P4.7。
(5)5口有8个引脚,分别记为P5.0~P5.7。
(6)6口有8个引脚,分别记为P6.0~P6.7。
(7)7口有8个引脚,分别记为P7.0~P7.7。
(8)8口有8个引脚,分别记为P8.0~P8.7。
(9)9口有8个引脚,分别记为P9.0~P9.7。
(10)10口有6个引脚,分别记为P10.0~P10.5。
(11)J口有6个引脚,分别记为PJ.0~PJ.5。
处理器使用零等待方式,以最高性能访问通用输入输出。GPIO支持8位、16位。在运行、等待、调试模式下,GPIO工作正常;在停止模式下,GPIO停止工作。
2. GPIO的寄存器地址分析
每个GPIO口均有12个寄存器,11个GPIO口共有132个寄存器。1~10和J各GPIO口寄存器的基地址分别为4000_4C00h、4000_4C01h、4000_4C20h、4000_4C21h、4000_4C40h、4000_4C41h、4000_4C60h、4000_4C61h、4000_4C80h、4000_4C81h,4000_4CA0,每两个端口具有相同基地址,如P1、P2基地址相同,PJ不与其他口共用基地址。如表4-1所示,各GPIO口的主要12个寄存器分别是数据输入寄存器(PxIN)、数据输出寄存器(PxOUT)、数据方向寄存器(PxDIR)、上下拉使能寄存器(PxREN)、驱动选择寄存器(PxDS)、复用选择寄存器(PxSEL0,PxSEL1)、功能同变化寄存器(PxSELC)、中断标志寄存器(PxIFG)、中断边沿选择寄存器(PxIES)、中断向量寄存器(PxIV)及中断使能寄存器(PxIE)。除中断向量寄存器为16位寄存器外,其他寄存器都是8位寄存器。基地址相邻的两个口,它们的GPIO寄存器相互交错地排列在一起。例如,P1和P2口的输入输出寄存器排列为P1IN、P2IN、P1OUT、P2OUT,其他寄存器也是如此交错排列。
表4-1 PT1寄存器
4.2.2 GPIO基本编程步骤与基本打通程序
1. GPIO基本编程步骤
要使芯片某一引脚为GPIO功能,并定义为输入/输出,随后进行应用,其基本编程步骤如下。
(1)通过GPIO模块的“复用选择寄存器”(SEL0和SEL1)设定其为GPIO功能(即令SEL0、SEL1对应的位清零)。
(2)若是输出引脚,则通过设置“数据输出寄存器”来指定相应引脚输出低电平或高电平,对应值为0或1。
(3)通过GPIO模块相应口的“数据方向寄存器”来指定相应引脚为输入或输出功能。若指定位为0,则为对应引脚输入;若指定位为1,则为对应引脚输出。
(4)若是输入引脚,则通过“数据输入寄存器”获得引脚的状态。若指定位为0,表示当前该引脚上为低电平;若指定位为1,则当前引脚上为高电平。
2. 理解GPIO基本编程步骤举例——基本打通程序
举例说明:设P2口的2引脚接一只发光二极管,高电平点亮。现在要点亮这只发光二极管,步骤如下。
1)计算数据方向寄存器P2DIR、数据输出寄存器P2OUT的地址
(1)从4.2.1节的端口控制模块可知,P2端口的基地址为0x40004C01u,其中,后缀u表示无符号数,给出不优化的32位指针变量gpio2_ptr:
vuint_8 *gpio2_ptr=(vuint_8 *)0x40004C01u;
(2)计算给出PT2的数据方向寄存器、输出寄存器、复用寄存器0和复用寄存器1的地址。
参考表4-1,PT2的数据方向寄存器地址=基地址+偏移量,PT2的数据输出寄存器地址=基地址+偏移量,PT2的复用寄存器0地址=基地址+偏移量,PT2的复用寄存器1地址=基地址+偏移量:
vuint_8 *gpio2_PDIR=(vuint_8*)(gpio2_ptr+4); vuint_8 *gpio2_POUT=(vuint_8*)(gpio2_ptr+2); vuint_8 *gpio2_SEL0=(vuint_8*)(gpio2_ptr+10); vuint_8 *gpio2_SEL1=(vuint_8*)(gpio_ptr+12);
2)设置P2.2引脚为GPIO输出引脚并输出数据
(1)令功能复用寄存器的相应位令SEL0寄存器的第三位为0,SEL1寄存器的第三位为0,其他位保持:
*gpio2_SEL0&=~(1<<2); *gpio2_SEL1&=~(1<<2);
(2)通过PT2的输出寄存器相应位赋0,使PT2|(2)引脚输出高电平:
*gpio2_POUT&=(1<<2);
(3)通过令PT2的方向寄存器相应位为1,定义PT2|(2)引脚为输出:
*gpio2_ptr->PDIR|=(1<<2);
这样这只发光二极管就亮起来了。这种编程方法的样例在本书网上教学资源的“..\ch04-Light\MSP432-Light(Simple)\06_NosPrg\main.c”文件中可以看到,用记事本即可打开该文件查看。安装开发环境参考网上教学资源中<01-Document >文件夹下关于软件工具使用方法的说明,利用开发环境,编译该工程,将机器码下载到硬件评估系统中,可以执行该程序。特别值得注意的是,可以采用单步调试的方式观察执行情况,以便理解实际映像寄存器与硬件是如何关联对应的,这样就理解了软件是如何控制硬件的。
不论如何,学到这里,应该进行实验。通过实验,理解基本原理,学会软件、硬件工具的使用与基本调试方法。
需要进一步说明的是,这样编程只是为了理解GPIO的基本编程方法,实际并不使用。芯片那么多引脚,不可能这样编程,要把对底层硬件的操作用构件把它们封装起来,给出函数名与接口参数,供实际编程时使用。下节将阐述底层驱动构件的封装方法与基本规范。
视频讲解