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中的时钟初始化代码。

时钟配置是后续所有外设的基础。若CAN波特率计算异常,首先应检查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上位机。

S32K3最小应用工程 — HIL闭环信号链 HIL上位机 CAN指令 / 数据采集 FlexCAN_0 — 500 kbps RX: 0x100 (指令) | TX: 0x200 (反馈) 采样点 87.5% | Prescaler=8, TSeg1=15, TSeg2=4 S32K344 内核 — 160 MHz PLL: FXOSC 16 MHz × 10 | AIPS_PLAT_CLK: 80 MHz GPIO PTA0 → LED输出 PTB1 ← HIL数字输入 推挽输出 / 上拉输入 eMIOS_0 PWM 周期: 20000 (20 ms) 占空比: 50% → 可调 预分频=80 → 1 MHz ADC_0 通道 SE0, 12位 VREFH = 5.0 V Voltage = Result/4095×5.0 ADC反馈回传 PWM驱动输出至执行器/示波器 CAN通信 GPIO PWM ADC

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回传值随实际输入电压变化。
若CAN通信失败,优先检查终端电阻(120 Ω)是否匹配、波特率是否一致、采样点是否在75%~87.5%之间。若ADC回传值恒为0或4095,检查VREFH是否接5 V、通道引脚是否悬空或短路。