4. S32K3最小应用工程搭建
在HIL闭环验证中,被测控制器必须首先是一个“能跑起来、能被观测、能被激励”的真实固件。S32K3作为NXP面向汽车电子的MCU,其最小应用工程的目标不是功能完整,而是建立一条从时钟、GPIO、CAN、ADC到PWM的可验证链路:HIL台架通过CAN发送指令,固件解析后驱动PWM输出,同时ADC采集反馈量并回传CAN,形成闭环。本节以S32 Design Studio(S32DS)为工具,围绕这一目标展开工程搭建与基础外设配置。
4.1 工程创建与时钟树配置
启动S32DS后,选择File → New → S32DS Project from Example,在S32K3系列中选择S32K344的Hello World或Blinky示例作为起点,命名为S32K3_HIL_Minimal。工程创建后,首要任务是配置时钟。S32K3的时钟由MC_CGM、PLL和FXOSC等模块构成,典型配置为:外部晶振16 MHz,经PLL倍频至160 MHz作为系统时钟,AIPS分频后为外设提供80 MHz时钟。在Peripherals工具中打开Clock Configuration,依次设置FXOSC为16 MHz、PLL倍频因子为10、系统时钟源选择PLL,并确认CORE_CLK为160 MHz、AIPS_PLAT_CLK为80 MHz。配置完成后点击Update Code,S32DS会自动生成Clock_Ip_Cfg.c中的时钟初始化代码。
AIPS_PLAT_CLK是否与CAN模块的时钟源一致。4.2 GPIO与PWM配置
GPIO用于状态指示和HIL数字量交互。在Peripherals中启用PORT和GPIO驱动,选择PTA0为输出(连接LED),PTB1为输入(连接HIL数字激励)。配置PTA0为推挽输出、初始电平低,PTB1为上拉输入。生成代码后,在main.c中调用GPIO_Ip_WritePin和GPIO_Ip_ReadPin即可操作。
PWM用于模拟执行器驱动信号。S32K3的eMIOS模块可产生多路PWM。以eMIOS_0的通道0为例,配置为OPWMB模式,周期寄存器EMIOS_CADDR设为20000,占空比初始为50%,即比较值10000。时钟源选择AIPS_PLAT_CLK的80 MHz,经预分频后得到1 MHz计数时钟,则PWM周期为20 ms(50 Hz),适合驱动舵机或模拟传感器。在eMIOS配置界面中设置Prescaler为80、Period为20000、Duty Cycle为50%,生成代码后通过EMIOS_DRV_SetDutyCycle动态调整占空比。
4.3 CAN与ADC配置
CAN是HIL闭环的核心通信通道。S32K3集成FlexCAN模块,配置CAN_0为经典CAN模式,波特率500 kbps。在FlexCAN配置中,设置Prescaler为8、Time Segment 1为15、Time Segment 2为4、Sync Jump Width为4,采样点约87.5%。使能接收邮箱MB0,ID为0x100,用于接收HIL指令;发送邮箱MB1,ID为0x200,用于回传ADC采样值。生成代码后,在main.c中注册接收回调,当收到0x100报文时解析第一个字节作为PWM占空比指令。
ADC用于采集模拟反馈量。配置ADC_0的通道SE0,参考电压VREFH为5 V,分辨率12位。在Adc配置中设置Conversion Time为1 μs,触发源选择软件触发。生成代码后,在main循环中调用Adc_StartGroupConversion并读取结果,将12位结果转换为电压值:Voltage = (Result / 4095) * 5.0。该电压值通过CAN报文0x200回传至HIL上位机。
4.4 固件主循环与HIL闭环逻辑
外设初始化完成后,main函数进入主循环。以下为关键代码片段,展示CAN接收、PWM更新和ADC回传的闭环逻辑:
/* 主循环:HIL闭环控制 */
while (1) {
/* 1. 检查CAN接收 */
if (FlexCAN_Ip_GetRxFifoStatus(CAN_0, &rxMsg) == FLEXCAN_STATUS_SUCCESS) {
if (rxMsg.msgId == 0x100) {
uint8_t dutyCmd = rxMsg.data[0]; /* 0~100 */
uint32_t compare = (dutyCmd * 20000) / 100;
EMIOS_DRV_SetDutyCycle(EMIOS_0, 0, compare);
}
}
/* 2. 启动ADC转换并读取 */
Adc_StartGroupConversion(ADC_0, 0);
while (Adc_GetGroupStatus(ADC_0, 0) != ADC_STATUS_COMPLETED);
uint16_t adcResult = Adc_ReadGroup(ADC_0, 0, 0);
float voltage = (adcResult / 4095.0f) * 5.0f;
/* 3. 通过CAN回传ADC电压值 */
FlexCAN_Ip_MsgInfoType txMsg;
txMsg.msgId = 0x200;
txMsg.dataLength = 2;
txMsg.data[0] = (uint8_t)(adcResult >> 8);
txMsg.data[1] = (uint8_t)(adcResult & 0xFF);
FlexCAN_Ip_SendMsg(CAN_0, &txMsg);
/* 4. GPIO状态翻转(心跳指示) */
GPIO_Ip_WritePin(PTA0, !GPIO_Ip_ReadPin(PTA0));
OsIf_TimeDelay(10); /* 10 ms循环周期 */
}
该循环以10 ms为周期运行,HIL上位机每10 ms发送一次0x100指令,固件更新PWM占空比,同时ADC采集并回传0x200报文。上位机通过对比发送的占空比指令与回传的ADC电压值,即可判断闭环是否正常。例如,当指令占空比为50%时,若ADC采集的是PWM输出经RC滤波后的电压,理论值应为2.5 V,允许±0.1 V误差。
4.5 编译、下载与验证
点击Build编译工程,确认无错误后通过Debug Configuration选择PEMicro或J-Link调试器,将固件下载至S32K344开发板。验证步骤如下:
- 用示波器测量
PTA0,应观察到10 ms周期方波,表明主循环运行正常。 - 用CAN分析仪发送
0x100报文,数据域[0x32, 0x00, ...](占空比50%),示波器测量PWM输出引脚,应观察到20 ms周期、50%占空比的方波。 - CAN分析仪应收到
0x200报文,数据域为ADC原始值。若ADC输入接2.5 V,则原始值约为2048(0x0800),报文数据为[0x08, 0x00]。 - 改变
0x100报文占空比指令为0x64(100%),PWM输出应变为常高电平,ADC回传值随实际输入电压变化。
VREFH是否接5 V、通道引脚是否悬空或短路。