内容提要
引言
1. S32K1xx系列MCU详细说明引脚功能特征(PORT和GPIO模块)
1.1 S32K1xx的PORT介绍模块配置寄存器
1.2 S32K1xx的GPIO介绍模块配置和状态寄存器
1.3 S32K1xx系列MCU的GPIO IRQ中断
2. PinSettings组件配置的S32K1xx系列MCU硬件模块
2.1 PinSettings详细说明组件属性配置
2.2 PinSettings组件API函数详解
2.3 PinSettings组件使用Tips
3. 基于S32K144-EVB的GPIO IRQ中断控制RGB LED亮灭样例工程
3.1 S32K144-EVB用户按键输入硬件设计及其PinSettings组件GPIO中断配置
3.2 S32K144-EVB的RGB LED硬件设计及其PinSettings组件GPIO输入配置
3.3 GPIO IRQ中断控制RGB LED实现亮灭功能代码
总结
引言
GPIO
--
G
eneral
P
orpurse
I
nput
O
utput,通用输入输出端口为嵌入式MCU外部信息交换实现人机交互(HMI)重要模块,MCU电影中各种功能外设模块的功能实现大多需要配置GPIO可以实现-例如,将某一个实现GPIO引脚配置为定时器模块的输入捕捉通道(
IC
)或输出比较(
OC
)通道,或发送信号作为通信外设(
TX
)、信号接收(
RX
)或者同步时钟(
CLK
)等等。可以说
GPIO
学习和使用一个MCU首先要学习和掌握的。
因此,本文首先介绍S32K1xx系列MCU的GPIO然后详细介绍功能特性S32K SDK中相应的Processor Expert 组件-
-PinSettings
配置和使用可以帮助您更好地使用它S32K的GPIO。
1. S32K1xx系列MCU详细说明引脚功能特征(PORT和GPIO模块)
S32K1xx系列MCU引脚功能由以下两个模块配置和控制:
①
PORT
--引脚端口功能复用和中断模块;
②
GPIO
--引脚做GPIO输入输出配置/控制模块;
S32K1xx系列MCU引脚信号复用框图如下,
引脚的
PAD
结构图如下,控制引脚的输出驱动(
Output Driver
)、输入接收器
(Input Receiver
)/缓冲器(
Input Buffer
)上下拉逻辑(
Pull logic
):
控制信号配置的真值表如下:
输出关闭(
obe=0
)输出缓冲器关闭,引脚pad高阻态(如果输入缓冲器不能);
输出使能(
obe=1
)时间:输出缓冲器使能,引脚pad为GPIO输出控制寄存器状态或复用外设的输出;
输入关闭(
ibe=0
)输入缓冲器关闭,内读输入值低;
输入使能(
ibe=1
)时间:输入缓冲器使能,内读输入值反映引脚pad外部输入状态;
可以通过
pue
和
pus
配置是否能引脚pad上下拉功能,具体是上拉还是下拉;
Tips
:
S32K1xx系列MCU并非所有的引脚都支持泄漏输出(
OD
), 只有配置为需要开漏结构的外设功能,才能在开漏模式下自动工作
PCR
开漏的配置位置在寄存器中没有控制。
Tips
:S32K1xx系列MCU复位后,大多数引脚的默认配置是
disable
状态,即三态(
tristate
),
若该引脚有ADC输入通道的再利用是ADC模拟信号输入,否则不会引脚GPIO也不使用任何外设功能
;
Tips
:切割包装引脚part,比如LQFP-64封装的S32K144,它没有被扇出(
Unbonded
)的引脚,用户无法使用,默认配置也是disable为了避免额外的功耗,不要擅自修改其端口配置寄存器(
PCR
);
Tips
:S32K1xx系列MCU特殊功能引脚复用后,默认配置为使能,需特别注意。
S32K1xx系列MCU特殊功能引脚如下:
①调试接口--
JTAG/SWD
引脚,SWD的
SWD_CLK
和
SWD_IO
引脚分别与JTAG的
TMS
和
TCK
复用:
②系统功能--
RESET
复位,无屏蔽中断
NMI
、时钟输出
CLKOUT:
③外部时钟/晶振--
OSC
引脚,
XTAL
与
EXTAL
:
④系统跟踪调试--
TRACE
引脚
S32K142/4/6
只有
SWO(单线输出跟踪)
:
而
S32K148
除了
SWO
之外还有
ETM(嵌入式跟踪模块)
时钟和数据信号引脚:
其中,
SWD/JTAG
调试接口的
时钟信号
--SWDCLK/JTAG_TCK,与PTC4复用,其
默认配置是下拉的,所以拉电阻不能连接到外部,否则会带来额外的功耗,特别是在低功耗模式下
。
1.1 S32K1xx的PORT介绍模块配置寄存器
① 引脚控制寄存器(PORT_PCRn)
S32K1xx系列MCU的PORT模块寄存器地址映射时,为每个端口PORT分配了32个
PCR
寄存器意味着每个端口最多支持32个引脚PIN。但实际情况不同part各组端口(PORTA/B/C/B/E)的引脚(GPIO PIN)数不同:
PCR用于配置引脚的寄存器PAD特征包括:
PE
:能否使上下拉, 1->使能,0->关闭;
PS
:选择上下拉,1->上拉(Pullup),0->下拉(Pulldown)
PFE
:可选择被动滤波器,1->使能,0->关闭;
DSE
:驱动能力选择, 当引脚配置为数字输出口时:1->强驱动,0->普通驱动;
MUX
:选择引脚外设功能, 用于引脚的复用功能, MUX = 0b000 -> 引脚disable,若有ADC重用输入通道,则为ADC输入功能;MUX = 0b0001 -> GPIO,通用输入输出功能;
LK
:写保护锁, 1 -> PCR[15:0]锁定,直到下次系统复位,才允许重新配置, 0 -> PCR[15:0]未锁定,允许重配置;
IRQC
:引脚中断配置,配置中断状态标志位置(
ISF
)置位的条件:IRQC = 0b0000 -> 中断关闭;IRQC = 0b0001 -> 上升沿触发,产生DMA请求;IRQC = 0b0010 -> 下升沿触发,产生DMA请求;IRQC = 0b0011 -> 上升沿或下降沿触发,产生DMA请求;IRQC = 0b1000 -> 低电平触发,产生CPU中断请求;IRQC = 0b1001 -> 上升沿触发,产生CPU中断请求;IRQC = 0b1010 -> 下升沿触发,产生CPU中断请求;IRQC = 0b1011 -> 上升沿或下降沿触发,产生CPU中断请求;IRQC = 0b1100 -> 高电平触发,产生CPU中断请求;其余配置为保留;
ISF
:中断状态标志位,该bit的置位条件由IRQC配置。0 -> 中断未发生;1 ->中断发生:若配置为产生DMA请求,则DMA请求传输完成后被自动清除,若配置为产生CPU中断,则该位置1,直到CPU写1清除。若配置为电平中断,则该中断标志位会保持置1直到中断电平变化;
PCR寄存器定义如下:
②
全局引脚控制寄存器(PORT_GPCL/HR)
除了PCR寄存器之外,S32K1xx的PORT模块还提供了全局引脚控制低寄存器(
PORT_GPCLR
)、全局引脚控制高寄存器(
PORT_GPCHR
)用于对通过相同功能属性配置
(
PCR
[15:0])的同
一个PORT的多个引脚进行快速配置:
每个PORT有一个
PORT_GPCLR
和一个
PORT_GPCHR
寄存器分别配置该PORT的低16个引脚和高16个引脚的PCR寄存器配置,这两个寄存器的该16-bit为写使能配置位,每个GPWE位对应一个引脚,使能(对应位为1)时,GPWD配置对该引脚的PCR寄存器写有效,否则无效:
③ 全局中断控制寄存器(PORT_GICL/HR)
此外,每个PORT还提供了全局中断控制低寄存器(
PORT_GICLR
)、全局中断控制高寄存器(
PORT_GICHR
)用于快速配置该PORT的相同中断配置(
PCR
[31:16])的多个引脚中断配置,其工作原理与全局引脚控制高低寄存器类似:
Tips
:以上全局控制寄存器提供了一种高效配置引脚PCR寄存器的方法,以便快速实现S32K1xx系列MCU引脚的配置,在实现功能安全要求的外设功能自测可以使用,以节约引脚PCR寄存器配置时间。
④ 端口中断状态标志寄存器
(
PORT_ISFR)
此外,S32K1xx系列MCU的PORT模块还提供了32-bit的中断状态标志寄存器
(
PORT_ISFR
),该寄存器每一个写1清0(w1c) 的bit位对应一个引脚的中断状态,1 ->中断发生, 0 -> 中断未发生,与相应引脚的
PCR
[
ISF
]一一对应:
⑤ 数字滤波器配置寄存器(PORT_DFER/DFCR/PORT_DFWR)
S32K1xx系列MCU的PORT模块还为每个GPIO引脚提供了一个数字滤波器,以实现对输入信号噪声过滤的作用。其通过以下寄存器进行配置:
数字滤波器使能寄存器
(
PORT_DFER
), 该寄存器每一个bit位配置相应PORT引脚的输入数字滤波器是否使能:1 -> 使能, 0 -> 关闭:
数字滤波器时钟选择寄存器(PORT_DFCR)
:该寄存器仅最低bit位有效,用于选择该PORT输入引脚数字滤波器的参考时钟:1 -> 使用低功耗时钟(LPO_CLK), 0 -> 使用总线时钟(BUS_CLK)
数字滤波器宽度配置寄存器(PORT_DFWR)
:该寄存器的仅最低5个bit位
FILT[4:0]
有效,用于配置PORT的引脚输入数字滤波器滤波宽度,只有大于FILT[4:0] 个滤波时钟周期的信号才能被MCU识别:
1.2 S32K1xx的GPIO模块配置与状态寄存器介绍
S32K1xx系列MCU的GPIO模块,为每个MCU引脚配置为通用输入输出(GPIO)功能时的输入和输出操作提供了用户接口寄存器,包括:
32-bit的
端口数据输出寄存器(PDOR)
:每个bit位对应一个GPIO引脚,1 ->输出高电平, 0 -> 输出低电平;
32-bit的
端口数据置位输出寄存器(PSOR)
:每个写1有效的bit位对应一个GPIO引脚,1 ->输出高电平, 0 -> 不影响输出电平状态;
32-bit的
端口数据清除输出寄存器(PCOR)
:每个写1有效的bit位对应一个GPIO引脚,1 ->输出低电平, 0 -> 不影响输出电平状态;
32-bit的
端口数据翻转输出寄存器(PTOR)
:每个写1有效的bit位对应一个GPIO引脚,1 ->翻转输出电平, 0 -> 不影响输出电平状态;
32-bit的
端口数据输入寄存器(PDIR)
:每个bit位对应一个GPIO引脚,1 ->输入高电平, 0 -> 输入低电平;
32-bit的
端口数据方向寄存器(PDDR)
:每个bit位对应一个GPIO引脚,1 -> 引脚数据方向为输出, 0 -> 引脚数据方向为输入;
32-bit的
端口输入关闭寄存器(PIDR)
:每个bit位对应一个GPIO引脚,1 -> 引脚输入关闭,对PDIR相应bit位为0, 0 -> 引脚配置为通用输入功能;
1.3 S32K1xx系列MCU的GPIO IRQ中断
S32K1xx系列MCU的每个GPIO引脚都有IRQ中断功能,具体配置请参考1.1小节介绍。
S32K11x
系列MCU的GPIO引脚中断向量分配如下,
所有PORT的全部GPIO引脚共用一个中断向量(Interrupt Vector)
:
S32K14x
系列MCU的GPIO引脚中断向量分配如下,
每一个PORT的若干GPIO引脚共用一个中断向量(Interrupt Vector)
:
因此,在GPIO引脚的中断ISR函数中,用户需要读取各个PORT的中断标志寄存器(
PORT
->
ISFR
)来判断具体是哪一个GPIO引脚发生了中断,然后做相应的处理并清除对应的中断标志位,具体请参考本文的
3.3
小节。
Tips
:使用时将用到的GPIO引脚中断尽量分配到同一个PORT,可以减少中断ISR,缩短查询中断的时间--仅读取一个PORT的ISFR寄存器即可进行判断。
Tips
:在基于S32K1xx SDK的S32K1xx系列MCU应用工程启动文件(
S32K1xx_Startup.s
)中,已经通过弱符号(Weak Symbol)定义了所有的外设中断ISR。
比如,在S32DS使用的GCC编译器启动文件中,S32K11x系列MCU的中断ISR定义如下:
.long PORT_IRQHandler /* Port A, B, C, D and E pin detect interrupt */
而S32K14x系列MCU的中断ISR定义如下:
.long PORTA_IRQHandler /* Port A pin detect interrupt*/.long PORTB_IRQHandler /* Port B pin detect interrupt*/.long PORTC_IRQHandler /* Port C pin detect interrupt*/.long PORTD_IRQHandler /* Port D pin detect interrupt*/.long PORTE_IRQHandler /* Port E pin detect interrupt*/
然后使用默认死循环的中断ISR(
DefaultISR
)进行了替换:
.align 1.thumb_func.weak DefaultISR.type DefaultISR, %functionDefaultISR:b DefaultISR.size DefaultISR, . - DefaultISR/* Macro to define default handlers. Default handler* will be weak symbol and just dead loops. They can be* overwritten by other handlers */.macro def_irq_handler handler_name.weak handler_name.set handler_name, DefaultISR.endm/* Exception Handlers */。。。。。。。。。。 def_irq_handler LPTMR0_IRQHandlerdef_irq_handler PORTA_IRQHandlerdef_irq_handler PORTB_IRQHandlerdef_irq_handler PORTC_IRQHandlerdef_irq_handler PORTD_IRQHandlerdef_irq_handler PORTE_IRQHandler
所以用户有两种方式写S32K1xx系列MCU的GPIO引脚中断ISR:
方法一、在任意C文件中定义与启动文件中PORT中断ISR同名的无参数无返回(void)类型函数
比如S32K14x系列MCU的PORTA中断ISR实现如下:
void PORTA_IRQHandler(void){uint32_t Port_IntFlag = 0;/* read the PORT interrupt flags*/Port_IntFlag = PINS_DRV_GetPortIntFlag(PORTA);if(Port_IntFlag & (1<<3)){/**the PTA3 PIN IRQ interrupt happaned,*add corresponding user handle code here*//* clean the PTA3 interrupt flag bit */PINS_DRV_ClearPinIntFlagCmd(PORTA,3);}}
方法二、先在任意C文件中定义无参数无返回(void)类型的指定ISR函数,然后调用Interrupt_Manager组件提供的
比如同样功能的S32K14x系列MCU的PORTA中断ISR实现如下:
先定义PTA3的中断ISR函数:
void User_Button_IRQ_ISR(void){uint32_t Port_IntFlag = 0;/* read the PORT interrupt flags*/Port_IntFlag = PINS_DRV_GetPortIntFlag(PORTA);if(Port_IntFlag & (1<<3)){/**the PTA3 PIN IRQ interrupt happaned,*add corresponding user handle code here*//* clean the PTA3 interrupt flag bit */PINS_DRV_ClearPinIntFlagCmd(PORTA,3);}}
然后,调用
InterruptManager
组件的
INT_SYS_InstallHandler()
注册该中断ISR到
PORTA
的中断向量表中:
/** install PORTA IRQ interrupt ISR*/INT_SYS_InstallHandler(PORTA_IRQn, User_Button_IRQ_ISR, NULL);
PinSettings
组件的初始化函数只是配置使能了S32K1xx系列MCU的GPIO引脚中断,用户还需要调用
InterruptManager
组件的
INT_SYS_EnableIRQ()
,使能其对应的NVIC IRQ中断:
/** enable PORTC IRQ interrupt*/INT_SYS_EnableIRQ(PORTA_IRQn);
2. PinSettings组件配置的S32K1xx系列MCU硬件模块
在S32K1xx SDK中,提供了外设驱动层(PD)的
PinSettings
组件,用于配置S32K1xx系列MCU的PORT和GPIO功能,并提供相应的底层驱动API函数。
其与
CPU
组件和
clock_manager
组件以及
interrupt_manager
组件
一起作为默认组件添加到使用SDK工程的S32K1xx系列MCU应用
工程
中,无需用户自己手动添加:
接下来,本章节就来详细介绍一下其属性配置和API函数功能以及使用Tips。
2.1 PinSettings组件属性配置详解
在SDK组件的处理器专家组件视窗(Component Inspector)中可以看到
PinSettings
组件的属性配置界面如下:
在其信号分配(
Routing
)栏,提供了按外设模块区分的MCU引脚功能复用和方向配置:
① ADC输入通道引脚映射配置
从上面的介绍可知,S32K1xx系列MCU的引脚若有ADC输入的功能,则其默认配置(
PCR
[
MUX
] = 0b0000)就是ADC输入功能,而且对于大部分ADC输入通道来说只有一个引脚映射,所以无需用户特别配置。其用户配置界面如下:
只有在S32K14x系列MCU中,为了支持BLDC/PMSM三相电机的三电阻采样方案,ADC0与ADC1之间有有交错(interleave)功能的4个ADC通道(
ADC0_CH8/9
和
ADC1_CH14/15
),需要用户进行引脚映射配置,以匹配硬件设计:
② CAN/LPI2C/LPSPI/LPUART通信模块引脚映射配置
S32K1xx系列MCU集成了多达3路
FlexCAN
通信模块,每个FlexCAN模块需要配置其发送(TXD)和接收(RXD)的引脚。默认是未使用的(
No pin routed
),
使用CAN模块时,用户必须根据实际硬件设计从下拉菜单中选择正确的引脚映射
,其用户配置界面如下:
LPI2C
模块的引脚映射配置界面如下, 由于存在多种引脚映射可能,默认是未使用的(
No pin routed
), 使用时用户需要根据实际需求配置主机请求(Host Request), 串行时钟(Serial Clock),串行数据(Serial Data)以及次串行时钟(Secondary Serial Clock)和次串行数据(Secondary Serial Data):
LPSPI
模块的引脚映射配置界面如下, 由于存在多种引脚映射可能,默认是未使用的(
No pin routed
), 使用时用户需要根据实际需求配置外设片选(PCS0~3)、串行时钟(Serial Clock),串行数据输入(Serial Data Input)和串行数据输出(Serial Data Output),并根据Master和Slave选择配置正确的信号传输方向:
LPUART
模块的引脚映射配置界面如下, 由于存在多种引脚映射可能,默认是未使用的(
No pin routed
), 使用时用户需要根据实际需求配置清除发送(Clear to Send)、请求发送(Request to Send),接收数据(RXD)和发送数据(TXD),并根据LPUART功能选择配置TXD的信号传输方向:
③ CMP模块引脚映射配置
S32K1xx系列MCU片上模拟比较器
CMP
模块,大多数功能引脚也是唯一的映射,且为模拟功能,无需用户配置,但
输入1(Analog Input 1)
和
输出(Analog Output)
以及
轮回触发输出(Round Robin Port Output Trigger)
有多个引脚映射,默认未使用的(
No pin routed
),
使用时,用户必须根据实际硬件设计从下拉菜单中选择正确的引脚映射
,其用户配置界面如下:
④ EWM模块引脚映射配置
S32K1xx系列MCU的外面看门狗检测
EWM
模块,需要配置
输入输出
信号的引脚映射。由于存在多种引脚映射可能,默认是未使用的(
No pin routed
),
使用时,用户必须根据实际硬件设计从下拉菜单中选择正确的引脚映射
,其用户配置界面如下:
⑤ FlexIO模块引脚映射配置
S32K1xx系列MCU的
FlexIO
模块,用8个数据端口,需要配置其引脚映射。由于存在多种引脚映射可能,默认是未使用的(
No pin routed
),
使用时,用户必须根据实际硬件设计从下拉菜单中选择正确的引脚映射
,其用户配置界面如下:
⑥ FlexTimer/LPTMR/RTC定时器模块引脚映射配置
S32K1xx系列MCU集成了若干
FlexTimer(FTM)
定时器模块,每个FlexTimer模块有1一个外部参考时钟输入信号,8个通道信号和4个失效输入信号可以配置引脚映射。由于存在多种引脚映射可能,默认都是未使用的(
No pin routed
),
使用时,用户必须根据实际硬件设计从下拉菜单中选择正确的引脚映射
,对应FTM通道,还需要配置其信号方向,比如用作输入捕捉(IC)功能时为方向为输入,而输出比较(OC)和PWM功能时则为输出。其用户配置界面如下:
除了FlexTimer外,S32K1xx系列MCU还有一个
LPTMR
低功耗定时器模块,其支持输入脉冲计数功能,由于存在多种引脚映射可能,默认都是未使用的(
No pin routed
使用时需要配置其外部脉冲输入信号引脚映射。其用户配置界面如下:
S32K1xx系列MCU的
RTC
定时器功能引脚配置界面如下,其支持外部32.768KHz有源时钟输入作为其工作参考时钟(Clock Input)和对RTC_CLK的输出(Clock Output), 如有使用,需要在此配置:
⑦ GPIO模块引脚映射配置
S32K1xx系列MCU的引脚用作通用
GPIO
功能时,需要通过如下界面,配置其端口引脚(
PORT
->
GPIO PIN
)
信号选择
和
方向
。默认是未使用的(
No pin routed
):
⑧ SWD/JTAG/Platform/PowerAndFround引脚映射配置
这些界面通常用户无需关心,使用其默认配置即可。
JTAG和SWD为S32K1xx系列MCU的调试接口引脚映射配置,在使用SWD调试接口时,可以将JTAG接口的
TDO
(
PTC5
)和
TDO
(
PTA10
)引脚用作其他外设功能。
在Platform界面,用户可以配置CLKOUT时钟输出引脚映射、NMI-不可屏蔽内核异常输入、RESET系统复位输入和外设晶振信号(EXTAL/XTAL)的引脚映射:
Tips
:用户需要十分小心对JTAG/SWD调试接口和Platform界面的RESET复位引脚信号映射的配置,关闭这些引脚会导致调试器连接失败。
下次连接调试器必须在PinSettings配置生效前
。
另外,在
PinSettings
组件的功能实现(
Functional Properties
)栏,提供了对每个MCU引脚的
PORT_PCR
寄存器属性配置:
其中,包括:
① Interrupt Flag
:中断标志位ISF,是否在初始化时清除(写1清0):
Don't modify
(默认配置) -> 不清除;Clear Flag -> 写1清零;
② Interrupt
:中断条件配置,具体参考前面章节介绍,默认配置为关闭中断:
Interrupt Status Flag(ISF) is disabled
:
③ Pin Mux
:引脚功能复用,具体参见前面章节介绍,默认配置为关闭引脚或者模拟信号(ADC或者ACMP输入)功能:
Pin disabled(
引脚复用功能推荐在
PinSettings
组件的Routing一栏按照外设模块功能分类进行配置
)
:
④ Lock
:运行配置锁配置,具体参考前面章节介绍,
Unlocked(
默认配置
) ->
关闭,允许运行时重新配置PCR寄存器;
locked ->
使能,禁止运行时重新配置PCR寄存器;
⑤ Pull Enable
:使能上下拉配置,
Disable(
默认配置
)
-> 关闭;Enable -> 使能;
⑥ Pull Select
:上下拉选择配置,
Pull Down(
默认配置
)
-> 下拉;Pull Up-> 上拉;
⑦ Digital Filter
:数字滤波器配置,
Disable(
默认配置
)
-> 关闭;Enable -> 使能;
⑧ Drive Strength
:电流驱动强度配置,
Low(
默认配置
)
-> 低;High-> 高(
仅对大电流IO可用,输出驱动电流可达20mA
);
⑨ Passive Filter
:被动滤波器配置,
仅对
NMI(PTD3)
和
RESET(PTA5)
引脚可用
;Enable -> 使能;
⑩ Initial Value
:GPIO输出初始化电平配置,
Low(
默认配置
)
-> 低电平;High-> 高电平;
⑪
ADC Interleave
:
ADC交错功能配置
(
仅对S32K14x系列MCU可用
):
Not muxed in SIM_CHIPCTL
(
默认配置
) ->使用默认配置;
muxed in SIM_CHIPCTL
->由
SIM_CHIPCTL配置
;
Tips
:以上
②~⑩的
PCR寄存器配置的默认配置与芯片设计相同,具体请参考S32K1xx系列MCU的参考手册附件excel--
S32K1xx_IO_Signal_Description_Input_Multiplexing.xlsx
;
如下为S32K144的引脚配置表内容:
2.2 PinSettings组件API函数详解
PinSettings
组件提供了丰富的API函数供用户调用:
通常,用户对引脚的绝多数功能配置都可以由
2.1
小节介绍的配置界面图形化方式配置,由Processor Expert生成初始化配置结果,在应用工程
Generated_Code
目录下,由
pin_mux.c/pin_mux.h
保存:
用户只需在main()函数中,完成系统时钟初始化后
拖拽(Drag & Drop)
调用初始化API- -
PINS_DRV_Init()
函数即可完成引脚配置:
若用户需要配置某个引脚的数组滤波器,则需手动调用如下API函数:
/*!* @brief Enables digital filter for digital pin muxing** This function enables digital filter feature for digital pin muxing** @param[in] base Port base pointer (PORTA, PORTB, PORTC, etc.)* @param[in] pin Port pin number*/void PINS_DRV_EnableDigitalFilter(PORT_Type * const base,uint32_t pin);/*!* @brief Disables digital filter for digital pin muxing** This function disables digital filter feature for digital pin muxing** @param[in] base Port base pointer (PORTA, PORTB, PORTC, etc.)* @param[in] pin Port pin number*/void PINS_DRV_DisableDigitalFilter(PORT_Type * const base,uint32_t pin);/*!* @brief Configures digital filter for port with given configuration** This function configures digital filter for port with given configuration** Note: Updating the filter configuration must be done only after all filters are disabled.** @param[in] base Port base pointer (PORTA, PORTB, PORTC, etc.)* @param[in] config the digital filter configuration struct*/void PINS_DRV_ConfigDigitalFilter(PORT_Type * const base,const port_digital_filter_config_t * const config);
若用户需要输出或者读取输入GPIO引脚电平,则可以调用以下API函数:
/*!* @brief Write a pin of a port with a given value** This function writes the given pin from a port, with the given value* ('0' represents LOW, '1' represents HIGH).** @param[in] base GPIO base pointer (PTA, PTB, PTC, etc.)* @param[in] pin Pin number to be written* @param[in] value Pin value to be written* - 0: corresponding pin is set to LOW* - 1: corresponding pin is set to HIGH*/void PINS_DRV_WritePin(GPIO_Type * const base,pins_channel_type_t pin,pins_level_type_t value);/*!* @brief Write all pins of a port** This function writes all pins configured as output with the values given in* the parameter pins. '0' represents LOW, '1' represents HIGH.** @param[in] base GPIO base pointer (PTA, PTB, PTC, etc.)* @param[in] pins Pin mask to be written* - 0: corresponding pin is set to LOW* - 1: corresponding pin is set to HIGH*/void PINS_DRV_WritePins(GPIO_Type * const base,pins_channel_type_t pins);/*!* @brief Get the current output from a port** This function returns the current output that is written to a port. Only pins* that are configured as output will have meaningful values.** @param[in] base GPIO base pointer (PTA, PTB, PTC, etc.)* @return GPIO outputs. Each bit represents one pin (LSB is pin 0, MSB is pin* 31). For each bit:* - 0: corresponding pin is set to LOW* - 1: corresponding pin is set to HIGH*/pins_channel_type_t PINS_DRV_GetPinsOutput(const GPIO_Type * const base);/*!* @brief Write pins with 'Set' value** This function configures output pins listed in parameter pins (bits that are* '1') to have a value of 'set' (HIGH). Pins corresponding to '0' will be* unaffected.** @param[in] base GPIO base pointer (PTA, PTB, PTC, etc.)* @param[in] pins Pin mask of bits to be set. Each bit represents one pin (LSB is* pin 0, MSB is pin 31). For each bit:* - 0: corresponding pin is unaffected* - 1: corresponding pin is set to HIGH*/void PINS_DRV_SetPins(GPIO_Type * const base,pins_channel_type_t pins);/*!* @brief Write pins to 'Clear' value** This function configures output pins listed in parameter pins (bits that are* '1') to have a 'cleared' value (LOW). Pins corresponding to '0' will be* unaffected.** @param[in] base GPIO base pointer (PTA, PTB, PTC, etc.)* @param[in] pins Pin mask of bits to be cleared. Each bit represents one pin (LSB* is pin 0, MSB is pin 31). For each bit:* - 0: corresponding pin is unaffected* - 1: corresponding pin is cleared(set to LOW)*/void PINS_DRV_ClearPins(GPIO_Type * const base,pins_channel_type_t pins);/*!* @brief Toggle pins value** This function toggles output pins listed in parameter pins (bits that are* '1'). Pins corresponding to '0' will be unaffected.** @param[in] base GPIO base pointer (PTA, PTB, PTC, etc.)* @param[in] pins Pin mask of bits to be toggled. Each bit represents one pin (LSB* is pin 0, MSB is pin 31). For each bit:* - 0: corresponding pin is unaffected* - 1: corresponding pin is toggled*/void PINS_DRV_TogglePins(GPIO_Type * const base,pins_channel_type_t pins);/*!* @brief Read input pins** This function returns the current input values from a port. Only pins* configured as input will have meaningful values.** @param[in] base GPIO base pointer (PTA, PTB, PTC, etc.)* @return GPIO inputs. Each bit represents one pin (LSB is pin 0, MSB is pin* 31). For each bit:* - 0: corresponding pin is read as LOW* - 1: corresponding pin is read as HIGH*/pins_channel_type_t PINS_DRV_ReadPins(const GPIO_Type * const base);
在GPIO输入引脚的IRQn中断ISR函数中,用户需要调用一下API函数,判断具体的中断引脚并清除相应的中断标志(ISF):
/*!* @brief Clears the individual pin-interrupt status flag.** This function clears the individual pin-interrupt status flag.** @param[in] base Port base pointer (PORTA, PORTB, PORTC, etc.)* @param[in] pin Port pin number*/void PINS_DRV_ClearPinIntFlagCmd(PORT_Type * const base,uint32_t pin);/*!* @brief Reads the entire port interrupt status flag** This function reads the entire port interrupt status flag.** @param[in] base Port base pointer (PORTA, PORTB, PORTC, etc.)* @return All 32 pin interrupt status flags*/uint32_t PINS_DRV_GetPortIntFlag(const PORT_Type * const base);/*!* @brief Clears the entire port interrupt status flag.** This function clears the entire port interrupt status flag.** @param[in] base Port base pointer (PORTA, PORTB, PORTC, etc.)*/void PINS_DRV_ClearPortIntFlagCmd(PORT_Type * const base);
其他有用的API函数还有全局引脚控制
(PINS_DRV_SetGlobalPinControl()
)和中断控制(
PINS_DRV_SetGlobalIntControl()
)配置函数:
/*!* @brief Quickly configures multiple pins with the same pin configuration.** This function quickly configures multiple pins within the one port for the same peripheral* function with the same pin configuration. Supports up to 16 pins with the lower or upper* half of pin registers at the same port.** Note: The set global interrupt control function (PINS_DRV_SetGlobalIntControl) cannot be* configured if you ever used this function at the same port** @param[in] base Port base pointer (PORTA, PORTB, PORTC, etc.)* @param[in] pins Pin mask where each bit represents one pin. For each bit:* - 0: pins corresponding to bits with value of '1' is updated with the value input* - 1: pins corresponding to bits with value of '0' is not updated with the value input* @param[in] value the config value will be updated for the pins are set to '1'* @param[in] halfPort the lower or upper half of pin registers at the same port*/void PINS_DRV_SetGlobalPinControl(PORT_Type * const base,uint16_t pins,uint16_t value,port_global_control_pins_t halfPort);/*!* @brief Quickly configures multiple pins with the same interrupt configuration.** This function quickly configures multiple pins within the one port for the same peripheral* function with the same interrupt configuration. Supports up to 16 pins with the lower or* upper half of pin registers at the same port.** Note: The set global pin control function (PINS_DRV_SetGlobalPinControl) cannot be* configured if you ever used this function at the same port** @param[in] base Port base pointer (PORTA, PORTB, PORTC, etc.)* @param[in] pins Pin mask where each bit represents one pin. For each bit:* - 0: pins corresponding to bits with value of '1' is updated with the value input* - 1: pins corresponding to bits with value of '0' is not updated with the value input* @param[in] value the config value will be updated for the pins are set to '1'* @param[in] halfPort the lower or upper half of pin registers at the same port*/void PINS_DRV_SetGlobalIntControl(PORT_Type * const base,uint16_t pins,uint16_t value,port_global_control_pins_t halfPort);
2.3 PinSettings组件使用Tips
调用
PinSettings
组件的API函数时,需要注意以下事项:
① API函数参数是PORT_Type 还是GPIO_Type ?
若是PORT_Type ,则合法的参数为: PORTA/PORTB/PORTC/PORTD/PORTE;
/* PORT - Peripheral instance base addresses *//** Peripheral PORTA base address */#define PORTA_BASE (0x40049000u)/** Peripheral PORTA base pointer */#define PORTA ((PORT_Type *)PORTA_BASE)/** Peripheral PORTB base address */#define PORTB_BASE (0x4004A000u)/** Peripheral PORTB base pointer */#define PORTB ((PORT_Type *)PORTB_BASE)/** Peripheral PORTC base address */#define PORTC_BASE (0x4004B000u)/** Peripheral PORTC base pointer */#define PORTC ((PORT_Type *)PORTC_BASE)/** Peripheral PORTD base address */#define PORTD_BASE (0x4004C000u)/** Peripheral PORTD base pointer */#define PORTD ((PORT_Type *)PORTD_BASE)/** Peripheral PORTE base address */#define PORTE_BASE (0x4004D000u)/** Peripheral PORTE base pointer */#define PORTE ((PORT_Type *)PORTE_BASE)/** Array initializer of PORT peripheral base addresses */#define PORT_BASE_ADDRS { PORTA_BASE, PORTB_BASE, PORTC_BASE, PORTD_BASE, PORTE_BASE }/** Array initializer of PORT peripheral base pointers */#define PORT_BASE_PTRS { PORTA, PORTB, PORTC, PORTD, PORTE }
若是GPIO_Type ,则合法的参数为: PTA/PTB/PTC/PTD/PTE;
/* GPIO - Peripheral instance base addresses *//** Peripheral PTA base address */#define PTA_BASE (0x400FF000u)/** Peripheral PTA base pointer */#define PTA ((GPIO_Type *)PTA_BASE)/** Peripheral PTB base address */#define PTB_BASE (0x400FF040u)/** Peripheral PTB base pointer */#define PTB ((GPIO_Type *)PTB_BASE)/** Peripheral PTC base address */#define PTC_BASE (0x400FF080u)/** Peripheral PTC base pointer */#define PTC ((GPIO_Type *)PTC_BASE)/** Peripheral PTD base address */#define PTD_BASE (0x400FF0C0u)/** Peripheral PTD base pointer */#define PTD ((GPIO_Type *)PTD_BASE)/** Peripheral PTE base address */#define PTE_BASE (0x400FF100u)/** Peripheral PTE base pointer */#define PTE ((GPIO_Type *)PTE_BASE)/** Array initializer of GPIO peripheral base addresses */#define GPIO_BASE_ADDRS { PTA_BASE, PTB_BASE, PTC_BASE, PTD_BASE, PTE_BASE }/** Array initializer of GPIO peripheral base pointers */#define GPIO_BASE_PTRS { PTA, PTB, PTC, PTD, PTE }
② API函数参数是Pin Mask还是PIN Number?
比如写GPIO输出的以下两个API函数:
void PINS_DRV_WritePin(GPIO_Type * const base,pins_channel_type_t pin,pins_level_type_t value);
和
void PINS_DRV_WritePins(GPIO_Type * const base,pins_channel_type_t pins);
PINS_DRV_WritePin()的第二个参数pin为Pin Number,而PINS_DRV_WritePins()的第二个参数pins为Pin Mask:
所以要在PTA3上输出高电平,以上两个函数的调用如下:
PINS_DRV_WritePin(PTA, 3, 1);/*output high on PTA3*/PINS_DRV_WritePins(PTA, 1<<3 );/*output high on PTA3*/
而要在PTA3上输出低电平,则调用如下:
PINS_DRV_WritePin(PTA, 3, 0);/*output low on PTA3*/PINS_DRV_WritePins(PTA, 0<<3 );/*output low on PTA3*/
Tips
:以上API函数中均是对
GPIO
->
PDOR
寄存器的操作,不同之处在于前者是
读改写
的操作,不会影响同一个PORT的其他引脚输出状态,而后者则是直接将值写入
GPIO
->
PDOR
寄存器,会影响同一个PORT的其他引脚输出状态;
Tips
:对GPIO引脚输出状态控制时,更为推荐使用如下API函数,其分别对
GPIO
->
PSOR
寄存器(
输出
高
电平
)、
GPIO
->
PCOR
寄存器(
输出
低
电平
)和
GPIO
->
PTOR
寄存器(
翻转
输出电平
)的pin mask操作,更为高效快捷(
具体请参考1.2小节相关寄存器介绍
):
void PINS_DRV_SetPins(GPIO_Type * const base,pins_channel_type_t pins);void PINS_DRV_ClearPins(GPIO_Type * const base,pins_channel_type_t pins);void PINS_DRV_TogglePins(GPIO_Type * const base,pins_channel_type_t pins);
③ 减少Processor Expert生成的引脚配置代码量和引脚初始化时间
将
PinSettings
组件的Settings栏 -> Generate configured Pins only选择为 “
yes
”,则仅生成配置与默认复位配置不同的引脚配置数据,从而减少生成的引脚初始配置代码量,同时也将减少引脚初始化时间;否则(选择为“
NO
”),将为每个引脚都生成初始化配置参数:
3. 基于S32K144-EVB的GPIO IRQ中断控制RGB LED亮灭样例工程
为了帮助大家更好的理解本文所讲内容,接下来,将以S32K144-EVB为例,介绍如何配置使用GPIO引脚输入中断和输出高低电平。
3.1 S32K144-EVB的用户按键输入硬件设计及其PinSettings组件GPIO中断配置
S32K144-EVB的2个用户按键输入电路设计如下:
相应的GPIO引脚映射如下:
按键
S32K144 GPIO端口
SW2
PTC12
SW3
PTC13
首先,在
PinSettings
组件的
Routing
栏
GPIO
中配置
PTC12
和
PTC13
为方向(Direction)为
输入
(Input):
然后,在
PinSettings
组件的
Functional Properties
栏,配置
PTC12
和
PTC13
的中断条件为上升沿触发CPU IRQ中断并使能内部下拉及数字滤波器:
3.2 S32K144-EVB的RGB LED硬件设计及其PinSettings组件GPIO输入配置
S32K144-EVB的
3
个用户RGB LED电路设计如下:
相应的GPIO引脚映射如下:
RGB LED
S32K144 GPIO端口
RED
PTD15
GREEN
PTD16
BLUE
PTD0
首先,在
PinSettings
组件的
Routing
栏
GPIO
中配置
PTD0
、
PTD15
和
PTD16
为输出:
然后,在
PinSettings
组件的
Functional Properties
栏,配置
PTD0
、
PTD15
和
PTD16
的初始值(Initial Value)为
High
,从而保证RGB LED在GPIO初始化后为熄灭状态:
3.3 GPIO IRQ中断控制RGB LED亮灭功能代码实现
首先,定义用户按键和RGB LED引脚PORT和GPIO PIN如下:
#define BUTTON_PORT PORTC /*PORT_Type*/#define SW2_PIN 12#define SW3_PIN 13#define LED_GPIO PTD /*GPIO_Type*/#define BLUE_PIN 0#define RED_PIN 15#define GREEN_PIN 16
然后, 编写PORTC中断ISR函数如下,实现功能为:读取PORTC中断标志位,判断:若发生了SW2中断(用户按下),则翻转GPIO闪烁蓝色RGB LED,并清除相应的引脚中断标志;若发生了SW3中断(用户按下),则翻转GPIO闪烁红色RGB LED,并清除相应的引脚中断标志:
/************************************************************* the PORTC IRQ interrupt ISR* toggle RGB LED according to different user button press** SW2-->toggle blue LED* SW3-->toggle red LED** use API--PINS_DRV_ClearPinIntFlagCmd() to clear GPIO pin* interrupt flag independently to avoid interrupt missing***********************************************************/void User_Button_IRQ_ISR(void){uint32_t Port_IntFlag = 0;/* read the PORT interrupt flags*/Port_IntFlag = PINS_DRV_GetPortIntFlag(BUTTON_PORT);if(Port_IntFlag&(1<
最后,调用
Interrupt_Manager
组件的以下API函数安装(
INT_SYS_InstallHandler()
)以上中断ISR函数并使能
PORTC
中断(
INT_SYS_EnableIRQ()
)如下:
/** install PORTC IRQ interrupt ISR*/INT_SYS_InstallHandler(PORTC_IRQn, User_Button_IRQ_ISR, NULL);/** enable PORTC IRQ interrupt*/INT_SYS_EnableIRQ(PORTC_IRQn);
总结
本文详细介绍了S32K1xx系列MCU的端口(PORT)和通用输入输出(GPIO)功能特性,以及如何使用S32K1xx SDK提供的Processor Expert
PinSettings
组件配置MCU引脚的PORT和GPIO功能以及外设功能复用和引脚映射,并基于S32K144-EVB硬件设计详细介绍了其提供的用户API函数使用方法和使用Tips。