4. 车身控制I/O驱动开发

车身控制器(BCM)与区域控制器(ZCU)的I/O驱动层,本质上是把RH850的GPIO、定时器、ADC与比较器等外设资源,映射为对车灯、继电器、MOSFET、开关输入的确定性控制与诊断。与通用MCU的“点灯”不同,车规I/O驱动必须同时满足三件事:负载驱动能力与拓扑正确、输入信号在电气噪声下可判定、输出通道在开路/短路/过温时能被识别并上报。本节以RH850/F1x系列(如F1KM、F1KH)的PORT、TAUJ、ADC12、CMP等模块为参照,给出寄存器级的实现思路。

一、高边与低边驱动的拓扑与寄存器映射

低边驱动(Low-Side Driver)用N沟道MOSFET把负载一端接地,负载另一端接常电(KL30)。MCU的PORT引脚经栅极驱动或直接驱动MOSFET栅极,输出高电平导通。高边驱动(High-Side Driver)用P沟道MOSFET或N沟道+电荷泵把负载接向KL30,MCU输出低电平导通。两种拓扑的故障语义不同:低边对地短路会持续导通,高边对地短路则可能烧毁MOSFET,因此高边通道通常需要额外的电流检测或温度反馈。

在RH850上,驱动引脚应优先分配到具备大电流能力的PORT组,并关闭内部上拉/下拉以避免与外部栅极电阻分压。以PORTn寄存器为例,方向寄存器PDRn的对应位写1设为输出,输出数据寄存器PODn写1/0决定电平,端口模式寄存器PMCn选择复用功能。若使用PWM调光,则把该引脚切到TAUJ的TOUT通道,由TAUJ0.CDRm与TAUJ0.CNTA控制占空比,此时PODn不再直接决定输出。

/* 低边驱动:P8_0 输出高电平导通 */
PORT.PMC8  &= ~(1u << 0);   /* 复用为GPIO */
PORT.PM8   &= ~(1u << 0);   /* 缓冲器使能 */
PORT.PDR8  |=  (1u << 0);   /* 方向:输出 */
PORT.POD8  |=  (1u << 0);   /* 输出高,MOSFET导通 */

/* 高边驱动:P8_1 输出低电平导通 */
PORT.PMC8  &= ~(1u << 1);
PORT.PDR8  |=  (1u << 1);
PORT.POD8  &= ~(1u << 1);   /* 输出低,PMOS导通 */

二、继电器与MOSFET控制的时序约束

继电器线圈是感性负载,关断瞬间会产生反向电动势。若直接用MCU引脚驱动,必须外接续流二极管与三极管/MOSFET,MCU只提供基极或栅极电流。寄存器层面要关注两点:一是上电初始化时先把PODn置为关断电平,再配置PDRn为输出,避免上电毛刺导致继电器误吸合;二是关断后要留出续流时间,典型继电器释放时间约5~10 ms,期间不应立即再次吸合,否则触点抖动会缩短寿命。

MOSFET控制则更强调栅极电阻与开关频率的匹配。以车灯PWM调光为例,若PWM频率取200 Hz、栅极电阻100 Ω、栅极电荷Qg约20 nC,则单次开关时间约2 μs,占空比分辨率在8位下足够。TAUJ配置时,TAUJ0.CDRm写入比较值,TAUJ0.CNTA从0计数到CDR值时翻转TOUT,需保证CDR值大于最小开关时间对应的计数值,否则会出现占空比失真。

继电器与MOSFET的关断顺序建议统一为:先关PWM输出,再拉PODn到关断电平,最后按需关闭通道使能,避免感性负载在PWM边沿叠加反向尖峰。

三、输入滤波与去抖的寄存器级实现

车身开关(门锁、雨刮、灯光)多为机械触点,抖动时间约1~10 ms。RH850的PORT模块本身不提供数字去抖,需在软件或定时器中实现。常用做法是用TAUJ或OSTM产生1 ms周期中断,在中断中对输入引脚采样并做移位滤波:连续N次采样一致才更新状态。N取8时,去抖时间约8 ms,可覆盖大多数触点抖动。

/* 1ms周期中断中的8次移位去抖 */
static uint8_t hist[PORT_IN_NUM];
static uint8_t stable[PORT_IN_NUM];

void Debounce_1ms(void)
{
    for (uint8_t i = 0; i < PORT_IN_NUM; i++) {
        uint8_t s = (PORT.PPR[i] >> PIN[i]) & 1u;
        hist[i] = (uint8_t)((hist[i] << 1) | s);
        if (hist[i] == 0xFFu)      stable[i] = 1u;
        else if (hist[i] == 0x00u) stable[i] = 0u;
    }
}

若输入是模拟量(如雨量、光照),则用ADC12采样后做滑动平均或中值滤波。ADC12的转换结果存放在ADCRn寄存器,需注意参考电压与采样时间配置:采样时间过短会导致高阻信号源采样不足,表现为读数偏低且随通道切换跳变。

四、输出诊断反馈与故障判定

输出诊断通常有三条路径:一是通过MOSFET的电流检测引脚接ADC,读取负载电流判断开路(电流≈0)或短路(电流超限);二是通过比较器CMP监测漏极电压,低边驱动关断时若漏极仍为低,说明对地短路;三是通过驱动芯片的故障引脚接GPIO,读取过温/过流标志。寄存器层面,ADC通道需配置ADCSR的扫描模式与ADCR结果寄存器,CMP需配置CMPnCTL的参考电压与输出极性。

判定逻辑建议做成状态机:每个输出通道维护“期望状态”与“实际反馈”,当两者不一致且持续超过诊断窗口(如50 ms)时置故障标志。故障标志应可被上层读取并支持清除,清除前需确认负载已关断,避免带故障重新导通。

RH850 车身I/O驱动:输出通道与诊断反馈信号链 RH850 MCU PORT.PDRn / PODn 方向与输出电平 TAUJ0.CDRm / CNTA PWM占空比与频率 ADC12.ADCRn 负载电流采样 CMPnCTL 漏极电压比较 OSTM / TAUJ 1ms 去抖采样节拍 故障标志与状态机 驱动级 低边 N-MOSFET 高电平导通 · 续流二极管 高边 P-MOSFET 低电平导通 · 电荷泵 继电器驱动 三极管/MOSFET + 续流 栅极驱动与保护 栅极电阻 · 过流/过温 负载与反馈 车灯 / 电机 / 继电器线圈 KL30 常电供电 电流检测电阻 → ADC12 采样 漏极电压节点 → CMP 比较 驱动芯片 FAULT → GPIO 读取 开路 / 短路 / 过温判定 1ms 采样 → 8次移位滤波 控制输出 驱动负载 诊断反馈 去抖节拍

五、一个可复用的通道配置与诊断判定示例

下面给出一个通道级配置结构,把方向、PWM、诊断阈值与去抖参数集中管理,便于在多个输出通道间复用。参数为教学示例,实际项目需按负载规格调整。

typedef struct {
    uint8_t  port;        /* PORT组号 */
    uint8_t  pin;         /* 引脚号 */
    uint8_t  active_high; /* 1=高有效(低边), 0=低有效(高边) */
    uint16_t pwm_period;  /* TAUJ周期计数值 */
    uint16_t pwm_duty;    /* 占空比计数值 */
    uint16_t oc_thresh;   /* 过流ADC阈值 */
    uint16_t ol_thresh;   /* 开路ADC阈值 */
    uint8_t  debounce_n;  /* 去抖采样次数 */
} IoChannelCfg;

/* 诊断判定:期望导通但电流低于开路阈值,持续50ms → 开路 */
if (expect_on && (adc_val < cfg.ol_thresh)) {
    if (++fault_cnt >= 50u) { fault_flag |= FAULT_OPEN; }
} else if (expect_on && (adc_val > cfg.oc_thresh)) {
    if (++fault_cnt >= 50u) { fault_flag |= FAULT_OVER_CURRENT; }
} else {
    fault_cnt = 0u;
}

实际调试时,建议先用示波器观察栅极波形与负载电流波形,确认开关沿无异常振铃;再用可调负载模拟开路与短路,验证诊断窗口是否在预期时间内置位。若诊断误报,优先检查ADC采样时刻是否落在PWM关断期间——在导通期间采样才能反映真实负载电流。

高边驱动关断时,若负载端存在残余电压,CMP比较结果可能短暂误判为短路。诊断窗口应避开开关沿,或在软件中加入沿后屏蔽时间(如200 μs)。

把以上四部分串起来,I/O驱动层的寄存器操作就不再是零散的位写,而是一条从“配置方向与PWM”到“驱动负载”再到“采样反馈与故障判定”的完整链路。下一阶段可在此基础上加入低功耗唤醒与端口保持逻辑,使车身控制器在休眠电流与唤醒响应之间取得平衡。