内容提要 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--General Porpurse Input Output,通用输入输出端口是嵌入式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的引脚功能由以下两个模块配置和控制:② GPIO--引脚做GPIO功能时的输入输出配置/控制模块;引脚的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的特殊功能引脚复用后默认配置都是使能的,需要特别注意。①调试接口--JTAG/SWD引脚,SWD的SWD_CLK和SWD_IO引脚分别与JTAG的TMS和TCK复用:②系统功能--RESET复位、不可屏蔽中断NMI、时钟输出CLKOUT:③外部时钟/晶振--OSC引脚, XTAL与EXTAL:S32K142/4/6只有SWO(单线输出跟踪):而S32K148除了SWO之外还有ETM(嵌入式跟踪模块)的时钟和数据信号引脚:其中, SWD/JTAG调试接口的时钟信号--SWDCLK/JTAG_TCK,与PTC4复用,其默认配置是下拉的,所以不能再外部接上拉电阻,否则会带来额外的功耗,尤其是在低功耗模式下要特别注意。1.1 S32K1xx的PORT模块配置寄存器介绍S32K1xx系列MCU的PORT模块寄存器地址映射时,为每一个端口PORT分配了32个PCR寄存器,意味着每个端口最多支持32个引脚PIN。但是实际不同part各组端口(PORTA/B/C/B/E)的引脚(GPIO PIN)数不同: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寄存器配置时间。此外,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 */
.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, %function DefaultISR: 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_IRQHandler def_irq_handler PORTA_IRQHandler def_irq_handler PORTB_IRQHandler def_irq_handler PORTC_IRQHandler def_irq_handler PORTD_IRQHandler def_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实现如下: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。在SDK组件的处理器专家组件视窗(Component Inspector)中可以看到PinSettings组件的属性配置界面如下:在其信号分配(Routing)栏,提供了按外设模块区分的MCU引脚功能复用和方向配置:从上面的介绍可知,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的信号传输方向:S32K1xx系列MCU片上模拟比较器CMP模块,大多数功能引脚也是唯一的映射,且为模拟功能,无需用户配置,但输入1(Analog Input 1)和输出(Analog Output)以及轮回触发输出(Round Robin Port Output Trigger)有多个引脚映射,默认未使用的(No pin routed),使用时,用户必须根据实际硬件设计从下拉菜单中选择正确的引脚映射,其用户配置界面如下:S32K1xx系列MCU的外面看门狗检测EWM模块,需要配置输入输出信号的引脚映射。由于存在多种引脚映射可能,默认是未使用的(No pin routed),使用时,用户必须根据实际硬件设计从下拉菜单中选择正确的引脚映射,其用户配置界面如下: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), 如有使用,需要在此配置: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;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); 调用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?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*/
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个用户按键输入电路设计如下:按键 | 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电路设计如下: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<<SW2_PIN)) /*if SW2 pressed*/ { /*toggle blue LED*/ PINS_DRV_TogglePins(LED_GPIO, 1<<BLUE_PIN); /*clear pin interrupt flag*/ PINS_DRV_ClearPinIntFlagCmd(BUTTON_PORT,SW2_PIN); }
if(Port_IntFlag&(1<<SW3_PIN)) /*if SW3 pressed*/ { /*toggle red LED*/ PINS_DRV_TogglePins(LED_GPIO, 1<<RED_PIN); /*clear pin interrupt flag*/ PINS_DRV_ClearPinIntFlagCmd(BUTTON_PORT,SW3_PIN); } } 最后,调用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。-------------------------------------
|