S32K3系列GPIO及其中断使用介绍
- 1. 例程介绍
- 1.1 例程选择:
- 1.2 选择依据:
- 2. GPIO的使用
- 2.1 通用GPIO
- 2.2 常用API简介
- 3. GPIO中断的配置与使用
- 3.1 在driver中添加如下模块:
- 3.2 新增引脚
- 3.3 配置IntCtrl_Ip_1模块
- 3.4 配置Siul2_Icu_1模块
- 3.5 软件配置
- 3.6 中断相关API
- 4. 注意事项
- 4.1 Debugger:
- 4.2 Debug
- 4.3 遗留问题
- 5. S32K3相关文章
- 5.1 [S32K3_Timer(PIT & STM)使用介绍]()
本文基于
S32K3xx芯片和S32 Design Studio for S32 Platform开发平台,介绍GPIO的
LLD(Low Level Driver)层的开发。
基于MCAL的开发请参考
1. 例程介绍
1.1 例程选择:
1.2 选择依据:
Dio打开后的外设层次如图:
Siul2打开的外设层次如图:
2. GPIO的使用
2.1 通用GPIO
- 对引脚的电平控制需要在diver中添加如下模块:
- 增加GPIO
- 单击SIUL2模块,会显示出所有具有该功能的引脚,单击想要使用的引脚,选择模式并选择输出输出方向。如下如所示:
2.2 常用API简介
/*操作引脚的高低电平变换:*/
void Siul2_Dio_Ip_WritePin
(
Siul2_Dio_Ip_GpioType * const base, /* PORT基地址 */
Siul2_Dio_Ip_PinsChannelType pin, /* 对应引脚号 */
Siul2_Dio_Ip_PinsLevelType value/* 写1为高电平输出,写0为低电平输出 */
)
/*操作引脚的高低电平变换:*/
void Siul2_Dio_Ip_TogglePins
( Siul2_Dio_Ip_GpioType * const base,
Siul2_Dio_Ip_PinsChannelType pins )
PORT说明:
S32K3的每个PORT的GPIO按照高16位、低16位分开控制,比如PORTA,其高16位和低16位基地址不同:
/** Peripheral PTA base address */
#define PTA_L_HALF ((Siul2_Dio_Ip_GpioType *)(&(IP_SIUL2->PGPDO0)))
#define PTA_H_HALF ((Siul2_Dio_Ip_GpioType *)(&(IP_SIUL2->PGPDO1)))
PINS说明:
基于port的说明,意味着我们能能同时一次性的控制16个pin(高16位or低16位),这些位(16 + 16)与32位引脚一一对应,在对应的位写1,则表示对应的引脚被置位高电平,写0,则表示对应的引脚被置位低电平。
例子:
#define LED_GREEN_PTA30_PIN 14u
Siul2_Dio_Ip_TogglePins(LED_GREEN_PTA30_PORT, 1 << LED_GREEN_PTA30_PIN);/*左移14位后,即表示PTA30这个引脚电平被翻转*/
//读引脚电平
Siul2_Dio_Ip_PinsLevelType Siul2_Dio_Ip_ReadPin
(
const Siul2_Dio_Ip_GpioType * const base, /* PORT基地址 */
Siul2_Dio_Ip_PinsChannelType pin /* 对应引脚号 */
)
/* 一次性读一个PORT的电平,仅配置为input的有效 */
Siul2_Dio_Ip_PinsChannelType Siul2_Dio_Ip_ReadPins
(
const Siul2_Dio_Ip_GpioType * const base /* PORT基地址 */
)
3. GPIO中断的配置与使用
3.1 在driver中添加如下模块:
IntCtrl_Ip_1是通用中断的基础配置,任何需要使用中断的地方都需要加入这个模块。
Siol2_Icu_1是Siul2模块的中断,即GPIO的中断配置。
3.2 新增引脚
将相应的引脚设置为中断输入模式,其他设置保持默认即可。
3.3 配置IntCtrl_Ip_1模块
根据不同的需求,此模块有两种配置方式,分别对应后文中IntCtrl_Ip模块软件配置的两种方式。
方式一:
IntCtrl_Ip_1模块保持默认配置,不在Interrupt Controller中添加instance
Generic Interrupt Settings中相应的中断也不需要添加Handler
通过后文中的软件单独打开需要使用的中断即可。
方式二:
使用Interrupt Controller
首先添加一个instance
使能你要使用的中断
注意选择与你使用的通道相对应的中断向量,选择依据参考数据手册,如下图所示:
如果有需要,可以设置该中断的优先级,默认为0。
优先级的value越小,优先级越高。如果设置的优先级value相同,则表格中顺序靠前的先执行。最大可设置16级优先级(4bit)。
正确添加Handler的名称:
后面的回调函的名字需要与对应外设的peripheral_Ip_Irq.c或者peripheral_Ip.c中的中断名字一致。比如GPIO的就要选择Siul2_Icu_Ip_Irq.c文件中的SIUL2_EXT_IRQ_8_15_ISR填入。
3.4 配置Siul2_Icu_1模块
- 根据引脚配置相应的硬件中断通道:
注意:引脚与中断通道有对应关系,要选择引脚对应的通道
- 选择引脚检测边沿的模式及制定回调函数的名称:
- 当然,如果有多个中断,要注意选择对应的instance和channel,一一对应即可。同时记得修改最大channel的数量
3.5 软件配置
1. 首先,在main.c中加入相应的头文件:
#include "Siul2_Icu_Ip.h"
#include "Siul2_Icu_Ip_Irq.h"
#include "IntCtrl_Ip.h"
#include "Clock_Ip.h"
2. 配置时钟
Clock_Ip_InitClock(&Mcu_aClockConfigPB[0]);
在Mcu_aClockConfigPB[0]中打开了很多时钟,如SIUL0_CLK时钟】
3. IntCtrl_Ip模块配置
这里有两种方式去使能不同peripheral的中断:
方式一:
不同的peripheral单独使能,如下为单独使用GPIO模块的中断。
IntCtrl_Ip_InstallHandler(SIUL_1_IRQn, &SIUL2_EXT_IRQ_8_15_ISR, NULL_PTR);
IntCtrl_Ip_EnableIrq(SIUL_1_IRQn);/*使能Siul中断*/
不同的通道对应不同的Siul2中断向量,有4个中断向量可供选择:
根据不同的中断通道请求选择不同的中断向量:
方式二:
调用以下接口,一起使能所有peripheral的中断
IntCtrl_Ip_Init(&IntCtrlConfig_0);
IntCtrl_Ip_ConfigIrqRouting(&intRouteConfig);
函数参数就是我们在图形化配置中配置的内容,在generate/src IntCtrl_Ip_Cfg.c中的两个结构体,其描述了所有中断的情况,与图形化界面中的两个表示一一对应的。
4. Siul2模块配置
初始化Icu驱动
Siul2_Icu_Ip_Init(0,&Siul2_Icu_Ip_0_Config_PB_BOARD_InitPeripherals);
第一个参数对应instance
第二个参数Siul2_Icu_Ip_0_Config_PB_BOARD_InitPeripherals在Siul2_Icu_Ip_SA_BOARD_InitPeripherals_PBcfg.c中,是根据对Siol2_Icu_1模块的配置生成的代码。因此在generate/src文件夹中。
5. 使能引脚相应通道的Icu中断和中断回调函数
Siul2_Icu_Ip_EnableInterrupt(0,13);
Siul2_Icu_Ip_EnableNotification(0,13);
以上第一个参数是instance,第二个参数是引脚的channel。
6. 初始化引脚(也可以放在前面,与前面的初始化内容相互独立,无先后顺序之分)
Siul2_Port_Ip_Init(NUM_OF_CONFIGURED_PINS0, g_pin_mux_InitConfigArr0);
IO初始化。
7. 编写回调函数
此回调函数与Siol2_Icu_1模块中配置的一致,需单独在应用层编写其实现。此函数指针在Icu初始化(Siul2_Icu_Ip_Init(0,&Siul2_Icu_Ip_0_Config_PB_BOARD_InitPeripherals);)时被注册,在相应的中断发生时,会自动被调用。
3.6 中断相关API
/*此API位于IntCtrl_Ip.c中,用于为某个中断(eIrqNumber)注册一个处理函数(pfNewHandler)。*/
void IntCtrl_Ip_InstallHandler( IRQn_Type eIrqNumber,
const IntCtrl_Ip_IrqHandlerType pfNewHandler,
IntCtrl_Ip_IrqHandlerType* const pfOldHandler
/* 使能相应的中断(eIrqNumber) */
void IntCtrl_Ip_EnableIrq(IRQn_Type eIrqNumber);
/* Icu模块初始化 */
Siul2_Icu_Ip_StatusType Siul2_Icu_Ip_Init(uint8 instance, const Siul2_Icu_Ip_ConfigType* userConfig)
/*Icu模块中断使能*/
void Siul2_Icu_Ip_EnableInterrupt(uint8 instance, uint8 hwChannel)
/*Icu模块user callback function使能。User callback function is registered in function Siul2_Icu_Ip_Init()*/
void Siul2_Icu_Ip_EnableNotification(uint8 instance, uint8 hwChannel)
/* 设置通道的检测状态,上升沿、下降沿、双边沿 */
Void Siul2_Icu_Ip_SetActivationCondition(uint8 instance, uint8 hwChannel, Siul2_Icu_Ip_EdgeType edge)
4. 注意事项
4.1 Debugger:
当使用开发板的micro USB调试时,在新建工程时,应将Debugger选择为:GDB PEMicro DebuggeringInterface
否则,在使用S32DS进行烧录时会报如下错误:
4.2 Debug
调试时建议关掉优化,否则调试时的断点执行与实际情况不一致:本来不该进的断点会进。
优化关闭入口:
右键工程,点击:properties
4.3 遗留问题
Icu Measurement mode有多种模式,目前只用到signal edge detect,其他几种模式还没有去探索怎么用(文档里面也没找到用法说明)。个人猜测,其他几种模式不是用于GPIO模块的,更可能是timer或者ADC要用的功能。
另外一个问题是没有看到GPIO的高电平、低电平中断检测,高低电平的中断几乎用不到,暂时不去研究了。
5. S32K3相关文章
5.1 S32K3_Timer(PIT & STM)使用介绍