为了实现快速入门,我们将利用 MCU 的一个引脚控制一盏如图4-2所示的发光二极管(LED)。为此,需要掌握配置引脚具体功能的端口控制模块(PORT),以及可控制引脚高低电平输出的GPIO模块的基本用法。
一个 MCU 内部硬件模块的编程结构是指该模块包含哪些寄存器,以及这些寄存器的作用、含义与功能,它们是构建MCU底层驱动构件的基础。
S32K144的大部分引脚具有复用功能,可以通过端口控制模块提供的寄存器编程指定其为某一具体功能,端口控制模块简称PORT模块。
PORT模块内含3类寄存器,分别是:引脚控制寄存器(Pin Control Register)、全局引脚控制寄存器(Global Pin Control Register)和中断状态标志寄存器(Interrupt Status Flag Register)。
1.寄存器映像地址分析
S32K144芯片有5个端口(A~E),每个端口有32个引脚控制寄存器PORTx_PCRn(其中x=A~E,n=0~31)、2个全局引脚控制寄存器(PORTx_GPCLR、PORTx_GPCHR)、1个中断状态标志寄存器(PORTx_ISFR)。以下地址分析计算均为十六进制,为书写简化起见,在不引起歧义的情况下,略去十六进制的前缀0x。
每个端口有32个引脚控制寄存器PORTx_PCRn,端口x的基地址=4004_9000+x×1000(x=A~E,对应0~4)。端口x的每个引脚控制寄存器PORTx_PCRn的地址=4004_9000+x×1000+n×4(x=A~E,对应0~4,n=0~31)。这样5个端口共5×32=160个引脚控制寄存器,每个引脚控制寄存器的地址很容易计算出来。例如,PORTA_PCR1的地址=4004_9000+0×1000+1×4=4004_9004。
每个端口有2个全局引脚控制寄存器:全局引脚控制寄存器(低)PORTx_GPCLR,地址=4004_9080+x×1000(x=A~E,对应0~4);全局引脚控制寄存器(高)PORTx_GPCHR,地址=4004_9084+x×1000(x=A~E,对应0~4)。
每个端口的有1个中断状态标志寄存器,地址=4004_90A0+x×1000(x=A~E,对应0~4)。
2.相关名词解释
(1)模拟引脚(Analog Pin)是指不能够配置成 GPIO 的引脚,如 RESET、EXTAL 及XTAL等引脚。S32K144的所有模拟引脚在芯片内部都由静电阻抗器(Electro-Static Discharge, ESD)保护二极管连接到VSS和VDD。
(2)数字引脚(Digital Pin)是指能够被配置成GPIO的引脚,所有的数字引脚都会通过一个ESD保护二极管连接到VSS。
(3)无源滤波器(Passive Filter)是由电容器、电抗器和电阻器组合而成的,具有无功补偿和调压的功能,可滤除一次或多次谐波,最简单的无源滤波器结构是将电感与电容串联。
(4)引脚驱动能力(Drive Strength)是指引脚输出或输入电流的承受能力,一般用 mA来度量。
(5)转换速率(Slew Rate)是指电压在高低电平间转换的时间间隔,一般用ns来度量。
(6)数字输出(Digital Output)是指芯片引脚只能输出高电平(逻辑1)和低电平(逻辑0)两个电压值。
(7)数字输入(Digital Input)是指芯片引脚只能接收并识别高电平(逻辑1)和低电平(逻辑0)两个电压值。
(8)引脚复用槽(Pin Muxing Slot)是指信号复用装置与引脚之间的接口,引脚通过连接不同的引脚复用槽可以配置成不同的功能。
(9)w1c是指对某位写1而使得该位清0,俗称写1清0。
3.引脚控制寄存器(PORTx_PCRn)
重点掌握本寄存器的使用,重中之重是掌握本寄存器D10~D8(MUX),即引脚复用控制位段,它决定了引脚复用何种功能。
每个端口的每个引脚均有一个对应的引脚控制寄存器,可以配置引脚中断或 DMA传输请求、配置引脚为GPIO功能或其他功能、配置是否启用上拉或下拉、配置选择输出引脚驱动能力,以及配置选择输入引脚是否使用内部滤波等。
其中X表示复位后状态不确定。下面介绍有关功能说明,未说明的位或字段均为保留字段(只读,值为0)。
D24(ISF):中断状态标志,在数字引脚模式下有效。当ISF =0时,未检测到引脚中断;当ISF =1时,表示检测到引脚中断。向该位写1,可清除中断状态标志。如果引脚配置为DMA请求方式,在完成 DMA请求传输后,将自动清除中断状态标志;如果引脚配置为电平触发的中断,若引起中断的电平一直有效,该标志将一直保持置1,即使被清除后也会立即置1。
D19~D16(IRQC):用于中断配置,在数字引脚模式下有效。当 IRQC=0000时,关闭引脚中断DMA请求。当IRQC=0001~0011时,分别对应上升沿(0001)、下降沿(0010)、沿跳变(0011)触发DMA请求;0100为保留;当IRQC=1000~1100时,分别对应逻辑低电平(逻辑0)、上升沿、下降沿、沿跳变、高电平(逻辑1)触发引脚中断;其他值保留。特别注意,并不是所有S32K144的引脚均可配置为中断功能,只有A端口、D端口的引脚具有上述中断功能。
D15(LX):锁定寄存器标志位。当LX=0时,表示引脚控制寄存器字段[15:0]未被锁定;当LX=1时,表示引脚控制寄存器字段[15:0]被锁定,无法更新,直到下一次系统复位为止。
D10~D8(MUX):引脚复用控制(读/写),不是所有引脚支持都引脚复用槽。当MUX=000时,表示引脚不配置(模拟引脚);当 MUX =001时,表示引脚配置为通用输入/输出(GPIO)功能;当MUX =010~111时,分别配置引脚的功能为第2到第7功能。附录A给出了S32K144引脚复用功能情况。
D6(DSE):驱动能力使能位,表明引脚被配置为数字输出时的驱动能力,在数字引脚模式下有效。当DSE=0时,表示低驱动能力;当DSE=1时,表示高驱动能力。由《S32K数据手册》可知,S32K144的低驱动能力是5 mA,高驱动能力是18 mA,但并不是所用引脚均可配置成高驱动能力,在实际使用时,需查数据手册。
D4(PFE):无源滤波使能位,在数字引脚模式下有效。当PFE= 0时,表示相应的引脚禁止无源输入滤波;当PFE=1时,表示相应的引脚启用无源输入滤波。具体滤波性能需参考《S32K 数据手册》,若该手册未给出无源滤波性能,可以不启用此功能,必要时自行外接滤波电路。
D1(PE):上拉或下拉使能位,在数字引脚模式下有效。当 PE=0时,表示相应的引脚关闭内部上拉或下拉电阻;当 PE=1时,表示相应的引脚启用内部上拉或下拉电阻,引脚作为数字输入。
D0(PS):上拉或下拉选择,在数字引脚模式下有效。当PS=0时,如果PE=1,引脚下拉电阻使能;当PS=1时,如果PE=1,引脚上拉电阻使能。S32K144内部上拉电阻或下拉电阻大小为20~50 kΩ。
4.全局引脚控制寄存器
读者只需了解本寄存器即可。
每个端口的全局引脚控制寄存器有2个,分别为 PORTx_GPCLR、PORTx_GPCHR,为只写寄存器,读出总为0。每个寄存器的高16位称为全局引脚写使能字段(Global Pin Write Enable,GPWE),低16位称为全局引脚写数据字段(Global Pin Write Data,GPWD)。如果GPWE=0xFFFF,则GPWD的16位字段就被写入全局引脚控制寄存器的低16位中。S32K144芯片每个端口有32个引脚控制寄存器,可分为2组:低引脚控制寄存器组(15~0)和高引脚控制寄存器组(31~16),全局引脚控制寄存器 PORTx_GPCLR 配置低引脚控制寄存器组(15~0),全局引脚控制寄存器PORTx_GPCHR配置高引脚控制寄存器组(31~16),这样可以一次配置16个功能相同的引脚,提高编程效率。GPWE的16位字段对应16个引脚控制寄存器,如果GPWE字段的部分位为0,则引脚控制寄存器组中对应的引脚控制寄存器不被配置。全局引脚控制寄存器不能配置引脚控制寄存器的高16位,因此不能使用该功能配置引脚中断。
5.中断状态标志寄存器(PORTx_ISFR)
读者需要基本理解本寄存器。
在数字引脚模式下,每个引脚的中断模式可以独立配置,在引脚控制寄存器IRQC字段可配置选择:中断禁止(复位后默认),高电平、低电平、上升沿、下降沿、沿跳变触发中断,上升沿、下降沿、沿跳变触发DMA请求。PORTx_ISFR支持在低功耗模式下唤醒。
每个端口的中断状态标志寄存器(PORTx_ISFR)对应该端口的32个引脚,相应位为1时表明配置的中断已经被检测到,反之没有。各位都具有写1清0特性。
1.S32K144的GPIO引脚
S32K144的大部分引脚具有多重复用功能,可以通过4.2.1节给出的寄存器编程来设定使用其中某一种功能,本节给出作为GPIO功能时的编程结构。100引脚封装的S32K144芯片的GPIO引脚分为5个端口,分别标记为A、B、C、D、E,共含89个引脚。端口作为GPIO引脚时,逻辑1对应高电平,逻辑0对应着低电平。GPIO模块使用的是系统时钟,从实时性细节来说,当作为通用输出时,高/低电平出现在时钟上升沿。每个端口实际可用的引脚数因封装不同而有不同,下面给出了各端口可作为GPIO功能的引脚数目及引脚名称:
(1)A端口有18个引脚,分别记为PTA0~17。
(2)B端口有18个引脚,分别记为PTB0~17。
(3)C端口有18个引脚,分别记为PTC0~17。
(4)D端口有18个引脚,分别记为PTD0~17。
(5)E端口有17个引脚,分别记为PTE0~16。
处理器使用零等待方式,以最高性能访问通用输入/输出。GPIO寄存器支持8位、16位及32位接口。在运行、等待、调试模式下,GPIO工作正常;在停止模式下,GPIO停止工作。
2.GPIO寄存器
每个GPIO端口均有6个寄存器,5个GPIO端口共有30个寄存器。A、B、C、D、E各端口的寄存器的基地址分别为400F_F000h、400F_F040h、400F_F0080h、400F_F0C0h 和400F_F100h,所以各端口基地址相差40h。每个GPIO端口的7个寄存器分别是数据输出寄存器、输出置1寄存器、输出清0寄存器、输出反转寄存器、数据输入寄存器、数据方向寄存器和数据输入禁止寄存器。其中数据输出寄存器的地址就是端口的基地址,其他寄存器的地址依次加4。所有寄存器均为32位宽度,复位时均为0000_0000h。表4-1给出了A端口的6个寄存器的基地址、偏移地址、绝对地址、寄存器名、访问特性、功能描述,其他各端口的功能与编程方式完全一致,只是相应的寄存器名与寄存器地址不同,只要把寄存器名中的A分别改为B、C、D、E即可,地址可按上述给出的规律计算。
表4-1 PORTA寄存器
1.GPIO基本编程步骤
要求芯片某一引脚为GPIO功能,并定义为输入或输出,随后进行应用,基本编程步骤如下。
(1)通过端口控制模块(PORT)的引脚控制寄存器 PORTx_PCRn 的引脚复用控制字段(MUX)设定该端口为GPIO功能(即令MUX=001)。
(2)通过 GPIO模块相应口的数据方向寄存器来指定相应引脚为输入或输出引脚。若指定位为0,则相应的引脚为输入引脚;若指定位为1,则为相应的引脚为输出引脚。
(3)若是输出引脚,则通过设置数据输出寄存器来指定相应引脚输出的是低电平还是高电平,对应值为0或1。亦可通过输出置1寄存器、输出清0寄存器、输出反转寄存器来改变引脚状态,请参考表4-1中关于寄存器的说明。
(4)若是输入引脚,则通过数据输入寄存器可获得引脚的状态。若指定位为0,表示当前该引脚上为低电平;若为1,则为高电平。
2.理解GPIO基本编程步骤实例——基本打通程序
举例说明:设PORTB端口的4引脚接一个发光二极管(LED),低电平点亮(按图4-2所示的接法)。现在要点亮这个LED,步骤如下:
(1)计算引脚控制寄存器PCR、数据方向寄存器PDDR、数据输出寄存器PDOR的地址。
① 计算PORTB端口的4引脚控制寄存器地址。从4.2.1节介绍的端口控制模块可知, PORTB端口的引脚控制寄存器基地址为0x4004A000u,其中后缀u表示无符号数,给出未优化的32位指针变量portB_ptr:
volatile uint_32 *portB_ptr =(uint_32*)0x4004A000u;
PORTB端口的19引脚控制寄存器地址为基地址+偏移量为:
volatile uint_32 *portB_PCR_4= portB_ptr + 4;
由于定义了32位指针,portB_ptr加1相当于地址加4,portB_ptr加19代表了portB_ptr地址加上19×4。
② 计算 PORTB 端口的数据方向寄存器、数据输出寄存器的地址。PORTB 端口(作为GPIO功能)的基地址为0x400FF040u。
volatile uint_32 *gpioB_ptr =(uint_32*)0x400FF040u;
参考表4-1,PORTB端口的数据方向寄存器地址为基地址+偏移量,PORTB端口的数据输出寄存器地址为基地址+偏移量。
volatile uint_32 *portB_PDDR =gpioB_ptr+5;
volatile uint_32 *portB_PDO =gpioB_ptr+0;
(2)设置PORTB端口的4引脚为GPIO输出引脚并输出数据。
① 令相应引脚控制寄存器的10~8位(MUX位段)为001,其他位保持不变。
*portB_PCR_4&=0b1111 1111 1111 1111 1111 1000 1111 1111; //清MUX位段
*portB_PCR_4|= 0b0000 0000 0000 0000 0000 0001 0000 0000;
② 通过令PORTB端口的数据方向寄存器相应位置1,定义PORTB4引脚为输出引脚。
*portB_PDDR |=(1<<4);
③ 通过对PORTB端口的数据输出寄存器相应位清0,使PORTB4引脚输出低电平。
*portB_PDO &=~(1<<4);
这样这个发光二极管就能亮起来了。在本书网上光盘的“..\ch04-Light\S32K144_Light(Simple)\06_NosPrg\main.c”文件中可以看到该实例的代码,用记事本就可打开该文件。安装开发环境时,请参考网上光盘中<01-Document>文件夹下关于软件工具使用方法的说明,利用开发环境编译该工程,将机器码下载到硬件评估系统中即可执行该程序。特别要注意的是,可以采用单步调试的方式观察执行的情况,以便理解实际映像寄存器与硬件是如何关联对应的,这样就可以理解软件是如何控制硬件的。
学到这里就应该进行实验,通过实验理解基本原理,学会软/硬件工具的使用与基本调试方法。
需要进一步说明的是,这样编程只是为了理解 GPIO的基本编程方法,在实际中并不使用。芯片有那么多引脚,不可能像这样编程,通常要用构件把对底层硬件的操作封装起来,给出函数名与接口参数,供实际编程时使用。4.3节将阐述底层驱动构件封装方法与规范。