
车载环视项目里有颗IMU需要把姿态数据通过UART实时回传域控制器摄像头到域控之间只拉了一根同轴电缆视频走GMSL链路串口单独走线就要多一对双绞线既增加成本又不好过EMC。最后我用MAX96763/MAX96752F这对GMSL2串行器/解串器把UART封装进控制通道里一根同轴同时搞定视频、电源和串口。这篇就把我在这个项目里的完整调试过程、寄存器配置和踩坑记录整理出来给后面做类似GMSL UART传输的朋友一个参考。1. 为什么要在车载摄像头里用GMSL传串口数据1.1 车载摄像头系统的通信困境车载摄像头模组通常由三部分组成图像传感器Sensor、串行器Serializer、以及一颗负责逻辑控制的MCU或ISP。Sensor输出的MIPI CSI-2信号经过串行器变成高速差分信号通过同轴电缆传到域控制器一侧再由解串器恢复成MIPI信号交给SoC处理。问题在于摄像头模组里除了图像往往还有陀螺仪、加速度计、温湿度传感器、甚至麦克风等外设。这些外设的数据绝大多数是UART或I2C接口。I2C通常用来做寄存器读写速度慢但双向可用GMSL天生就支持远程I2C。UART则是很多传感器的主接口比如某些IMU模块固定输出UART数据帧或者你希望保留一路调试串口到摄像头端方便在车上直接抓日志。传统做法的确可以单独拉一对线但车载环境里线束每增加一根都是成本、重量和失效风险的叠加。尤其是摄像头在车外后视镜、保险杠这类位置连接器针脚非常宝贵往往只有4Pin或者6Pin视频占了差分对和电源剩下的pin根本不够再走UART。1.2 GMSL2控制通道能做什么GMSL2本身在设计时就考虑了这种需求它的控制通道不只是给I2C用的。在GMSL2链路里控制通道采用时分复用方式承载多种数据类型包括I2C、UART和GPIO。MAX96763和MAX96752F内部都集成了UART接口配置好寄存器之后远端串行器的UART RX/TX会和控制通道绑定数据直接以包的形式传送到对端解串器的UART引脚上对外表现就是一根“透明”的串口线。这个方案相比单独走线有几个优势复用现有同轴电缆不用额外增加线束和连接器pin。链路自带CRC校验GMSL2控制通道的UART数据有错误检测比裸UART走线抗干扰能力强很多。远端供电可以走POCPower over Coax摄像头端不需要单独拉电源整根同轴既有数据又有电。1.3 几种串口回传方案的对比在方案选型阶段我也对比过其他做法列个表方便大家看方案传输介质额外成本抗干扰能力适用场景UART独立走线双绞线或单线线束、连接器pin一般长距离易受干扰线束冗余充足时CAN/CAN-FD回传双绞线需要CAN收发器强适合车载已有CAN网络可接入RS485回传双绞线需要485收发器强工业级长距离UART over GMSL2同轴电缆无额外硬件强带CRC摄像头链路已存在考虑到摄像头本身就用GMSL链路上行传输视频下行控制通道带宽本来就有富余用UART over GMSL2是最省事的路径不用新增总线节点也不用改整个EE架构。2. 搭建链路前的硬件细节引脚、电平和POC供电2.1 MAX96763与MAX96752F的角色划分MAX96763是GMSL2串行器放在摄像头端。它支持2路MIPI CSI-2输入或者1路并口输入输出经过内部串行化后从OUT/OUT-差分引脚发出。MAX96752F是GMSL2解串器放在域控制器端接收差分信号后恢复成MIPI CSI-2输出给SoC。串口信号在这对芯片里走的是“UART输入/输出引脚”和“控制通道”之间的桥接。具体到引脚MAX96763有URX和UTX引脚MAX96752F也有UARTA_TX/UARTA_RX有些型号叫UTXP/UTXN要看封装和数据手册。连接方式如下摄像头端MCU的UART_TX接到MAX96763的URX串行器接收外部数据摄像头端MCU的UART_RX接到MAX96763的UTX串行器输出数据给MCU域控端SoC/MCU的UART_RX接到MAX96752F的UART_TX引脚域控端SoC/MCU的UART_TX接到MAX96752F的UART_RX引脚数据流向就是远端MCU发数据 → MAX96763 URX → 控制通道封装传输 → MAX96752F解包 → UART_TX引脚输出 → 域控端MCU接收。反方向同理。2.2 UART电平匹配问题这是很容易忽略的一点。MAX96763和MAX96752F的UART引脚电平取决于VIO引脚的供电电压常见是1.8V或3.3V。如果你的MCU是5V电平直接连上去会灌电流甚至烧坏芯片引脚。我当时用的MCU是3.3V电平VIO正好也配的3.3V所以可以直连。如果电平不一致处理方法是用电平转换芯片如TXS0108E或者串电阻分压。串口通常速率不高分压电阻就能解决但要注意上升沿变缓可能影响波特率容差我建议还是用电平转换芯片更稳妥。2.3 POC供电的关键元件选型GMSL链路要用同轴电缆同时传视频和供电必须在串行器端和解串器端加POC网络。这个热搜词“gmsl poc功能实现方法”其实就是问这个。POC的基本结构是在信号通路里加入电感让直流电源从电感注入让视频信号从电容耦合两者在电缆上叠加。MAX96763端和MAX96752F端的POC电路结构类似差异主要在取电方向摄像头端MAX96763侧同轴输入既包含视频信号2.5G或3Gbps的高速差分信号也包含直流电源。需要先经过隔直电容把视频信号耦合给串行器的OUT引脚同时用POC电感把直流成分分离出来送给后级稳压器变成MCU和Sensor需要的电压。域控端MAX96752F侧电源从板端直接注入到同轴电缆视频信号从同轴电缆通过隔直电容进入解串器的IN引脚直流电源经过POC电感注入。元件选型方面POC电感是核心。GMSL2的信号速率很高3Gbps的链路基频大概在1.5GHz附近所以电感不能选普通功率电感要选自谐振频率远高于信号频段的专用POC电感。我这边用了Murata的LQW21FT系列1uH到4.7uH都试过最终根据电源电流选了2.2uH那款。隔直电容用0402封装100nF的高频陶瓷电容注意耐压要满足电源电压。元件推荐型号/参数说明POC电感Murata LQW21FT2R2M102.2uH自谐振频率1GHz隔直电容100nF 0402 X7R耐压根据电源电压选50V电源去耦电容10uF100nF1nF覆盖低频到高频去耦有个坑要提醒POC电感的直流电阻DCR不能太大否则远端负载一拉电流电压跌落很多。摄像头端如果电流有300mADCR若为0.5Ω线上就要掉0.15V加上线缆本身的压降后端稳压器输入可能不足。2.4 线束和连接器的选择同轴电缆在车载里常用FAKRA或Mini-FAKRA连接器也有用HSDHigh Speed Data连接器的。FAKRA有机械防呆插拔方便缺点是体积大Mini-FAKRA体积小适合后视镜这类空间受限的位置。我项目里用的是Mini-FAKRA一串一解之间线束长度大概3米RG174规格实测信号损耗在可接受范围内。3. 先让视频链路工作I2C初始化与LOCK建立3.1 I2C地址的配置与访问机制GMSL2的I2C访问有个特点域控端的主机I2C总线首先连接的是本地解串器MAX96752F然后通过解串器的控制通道把I2C请求转发给远端串行器MAX96763。从主机的角度看远端串行器就像挂在同一条I2C总线上的另一个从设备只是它位于线缆另一端而已。MAX96763的I2C地址由ADDR引脚的上下拉决定默认7位地址常见是0x20或者0x22对应8位地址0x40或0x44取决于你的板子。MAX96752F默认7位地址常见是0x40或0x428位地址0x80或0x84。我在代码里统一用8位地址即地址左移一位的写法。3.2 初始化配置步骤整个初始化分三步配置本地解串器、远程访问串行器、最后统一使能UART。第一步先确认I2C能通。读一下器件ID寄存器MAX96763的DEV_ID寄存器读回应该是0x63MAX96752F读回应该是0x52。如果读不到大概率是I2C地址接错了或者芯片没有正常上电。第二步配置链路参数。GMSL2的链路需要两端都工作在同样的模式包括GMSL2模式、转速档位、自定义速率等。我项目里用默认的3Gbps档位没有改动自定义速率相关的分频寄存器。第三步是看LOCK信号。LOCK是链路建立成功的标志可以通过寄存器0x0006的bit3读取也可以直接看解串器的LOCK引脚电平。这一步很关键如果LOCK不置位后面的I2C远端访问全部白搭。// 伪代码初始化配置流程 #define ADDR_DES 0x80 // MAX96752F #define ADDR_SER 0x40 // MAX96763 // 1. 复位并确认器件ID if (i2c_read(ADDR_DES, 0x0001) ! 0x52) error; if (i2c_read(ADDR_SER, 0x0001) ! 0x63) error; // 2. 配置本地解串器 i2c_write(ADDR_DES, 0x0006, 0x08); // LOCK请求 i2c_write(ADDR_DES, 0x0008, 0xE0); // 使能VIDEO/I2C/UART i2c_write(ADDR_DES, 0x0015, 0x08); // UART引脚功能映射 // 3. 远程访问串行器此时链路需要已经LOCK i2c_write(ADDR_SER, 0x0006, 0x08); i2c_write(ADDR_SER, 0x0008, 0xE0); i2c_write(ADDR_SER, 0x0015, 0x08); // 4. 检查远端LOCK状态 if (!(i2c_read(ADDR_SER, 0x0006) 0x08)) error;3.3 LOCK建不上的排查顺序我遇到过几次LOCK不上的情况按照以下顺序排查基本都能找到问题检查同轴电缆连接用万用表测一下中心导体和屏蔽层是否有短路或断路。POC网络中的电感如果虚焊直流是通的但高速信号过不去LOCK也会失败。检查I2C地址是否冲突如果总线上还有其他设备用了相同地址通信会乱掉。检查电源时序MAX96763和MAX96752F都需要先给AVDD和IOVDD供电再开始I2C配置。如果上电不稳定导致芯片内部寄存器状态异常可以先软件复位写0x0010复位寄存器再重新配置。降低控制通道速率长线缆情况下控制通道速率太高会导致反向通道解调失败。可以把控制通道速率从默认的1Mbps降到500kbps试试。4. UART over GMSL2的核心原理和完整寄存器配置4.1 控制通道是怎么把UART数据搬过去的GMSL2的控制通道是一种双向半双工的时分复用链路。它把时间分成固定时隙每个时隙分配给I2C、UART、GPIO或者远程寄存器读写。MAX96763内部的UART控制器接收到远端MCU发来的数据后先把UART字节缓存起来等到控制通道轮到UART时隙时打包发送到线缆另一端MAX96752F收到后解包再通过UART引脚发送给域控端MCU。因为控制通道是半双工的所以UART传输也具有半双工特性。这就意味着同一时刻只能有一端发送数据。如果两端同时往对方发数据数据会丢失或乱码。实际使用中如果你的业务通信是请求-响应模式问题不大如果是两端同时主动上报数据就要设计流控或者错峰机制。UART over GMSL2的另一个特性是收发延迟比直连UART大。原因是数据要经过“UART采样 → 控制通道封装 → 传输 → 解包 → 重新发送”这个过程。实测下来115200波特率下数据从一端到另一端的单向延迟大约在几百微秒到一两毫秒之间。对于IMU这类周期性上报数据完全不是问题但如果你要做字节级实时同步控制就要评估这个延迟是否可接受。4.2 寄存器配置表以下配置表来自我实际调试使用的版本注意MAX96763和MAX96752F有多个后缀版本寄存器位定义可能会有差异拿到新板子后建议对着数据手册的寄存器地图核对一遍。地址寄存器名配置值说明0x0006PHY_LINK_CTRL0x08置位LOCK请求建立链路0x0008PHY_LINK_CFG0xE0使能VIDEO_EN、UART_EN、I2C_EN0x0015PIN_CFG0x08将对应引脚配置为UART功能0x0110UART_CTRL0x00UART参考时钟选择自动模式0x0111UART_DIV_L手动分频时配置波特率分频系数低字节0x0112UART_DIV_H手动分频时配置波特率分频系数高字节MAX96752F侧的配置表和MAX96763基本一致使用的也是0x0006、0x0008、0x0015这几个寄存器。不过我这边实测有一处差异MAX96752F的UART使能位在0x0008的bit6但在某些版本上UART映射需要额外在0x0018寄存器里做引脚功能切换。如果你在MAX96752F上配完0x0008和0x0015还是收不到数据可以查一下数据手册里GPIO功能复用表。4.3 波特率分频的配置逻辑UART的波特率不是随便设的它取决于芯片的参考时钟源和分频系数。MAX96763和MAX96752F的UART模块通常使用PCLK或者外部晶振作为时钟基准通过分频得到目标波特率。芯片内部对于UART分频有一个推荐的计算公式分频值 参考时钟频率 / (目标波特率 × 16)举个例子如果参考时钟是108MHz目标波特率是115200那么分频值 108000000 / (115200 × 16) 58.59。分频寄存器只能写整数所以实际分频系数可能是58或者59对应实际波特率会有一定偏差。58分频时实际波特率 108000000 / (58 × 16) 116379偏差约为1%。UART本身允许的波特率误差通常在±2%以内所以这个偏差还能接受。如果你的目标波特率恰好算出个偏心率很大的分频值比如分频值落在x.5附近那实际波特率和目标波特率可能偏差达到3%以上会导致偶发乱码。解决办法有两个一是换一个能被整除的波特率二是改用芯片的内部FRL时钟作为时钟源让分频更精确。我在项目里用的是115200波特率按上述计算偏差在允许范围内跑了整车上电测试没有出现乱码问题。如果你的系统里UART波特率是自定义的建议先按公式算一遍偏差超过2%就要考虑换时钟源或者改波特率。4.4 完整配通一个UART通道的步骤把前面所有配置串起来完整步骤就是给MAX96763和MAX96752F正常上电确认I2C可读。配置视频链路参数包括MIPI通道数、数据速率映射让链路LOCK建立。在本地MAX96752F上使能UART_EN和引脚映射。通过I2C远程访问远端MAX96763同样使能UART_EN和引脚映射。配置UART波特率分频如果用自动模式可以跳过。用回环方式验证把远端MAX96763的UTX和URX短接域控端MCU发送一串数据看是否能原样收回来。这样能确认链路本身没问题排除了远端MCU程序的影响。远端MCU接入真实数据域控端抓包验证数据完整性。5. 实测数据和踩坑记录丢字节、波特率漂移和链路诊断5.1 NORMAL工况下的实测数据摄像头端MCU以100Hz频率每10ms一帧通过UART发送IMU姿态数据每帧8字节波特率1152008N1格式。域控端接收端用DMA方式接收实测连续运行24小时接收总帧数864万帧丢帧数为0误码率为0。这个结果说明UART over GMSL2在正常工况下非常稳定链路能力和直连UART几乎没有差别。需要注意的是我这里I2C访问频率很低只有启动时配置寄存器用了几十次平时基本不发I2C请求所以控制通道的UART资源非常充裕。5.2 踩坑一UART使能了但收不到任何数据现象是链路LOCK正常视频画面正常但域控端UART引脚上没有信号。排查过程先是拿示波器测MAX96752F的UART_TX引脚发现一直是高电平没有任何跳变。然后用I2C读MAX96752F的0x0008寄存器确认UART_EN置位是成功的。再读远端的0x0008也是成功的。问题出在引脚复用上。原来的硬件设计里MAX96752F的某些GPIO引脚默认是I2C地址配置引脚或者GPIO输入输出功能需要在0x0015寄存器里把对应引脚切换成UART功能。我配完0x0015之后UART引脚就开始有输出了。这个坑提醒我GMSL芯片的引脚功能复用非常多寄存器配置顺序不能乱先配功能复用再配使能位否则可能出现状态锁存不对。5.3 踩坑二高负载I2C访问导致UART丢字节有段时间需要频繁通过GMSL2控制通道读写远端MCU的寄存器大概每1ms读写一次I2C事务同时UART也在以115200波特率传输数据。结果UART这边开始偶发丢字节一帧数据里少几个字节CRC校验直接崩了。原因就是控制通道的带宽是共享的。GMSL2控制通道虽然有1Mbps的速率但UART和I2C都往里面塞数据I2C事务一旦频繁UART数据包就得等下一个时隙芯片内部的UART FIFO溢出导致丢字节。解决办法有两个方向一是降低I2C访问频率把每1ms一次改成每10ms一次二是提高控制通道速率或者调整UART和I2C的时隙分配权重。我实际采用了前者因为I2C在这里只是做状态轮询10ms一次的频率完全够用。5.4 踩坑三线缆屏蔽层接地不良导致的偶发误码有次在做整车级测试时发现UART偶发误码而且只在车辆经过颠簸路面时出现。查了很长时间最后发现是同轴电缆屏蔽层在连接器处的接地端子松动导致GMSL2链路在高频振动下出现瞬断。虽然视频信号有纠错机制看不出来但UART数据包对链路质量更敏感误码就暴露出来了。这个问题的排查思路是先用GMSL2芯片的错误计数器寄存器查看链路误码情况确认是链路物理层问题而不是UART配置问题再逐步检查连接器和线缆。5.5 链路诊断手段总结现象可能原因检查方法UART完全无输出UART_EN未使能或引脚复用错误检查0x0008、0x0015寄存器偶发丢字节I2C/UART争抢控制通道带宽降低I2C访问频率乱码波特率分频偏差过大计算分频值选择更匹配的波特率颠簸路况下误码屏蔽层接地不良或连接器松动检查线缆和连接器读错误寄存器LOCK丢失POC供电不足测量远端供电电压和纹波6. 工程化的一点经验项目做完之后复盘有几个地方如果再重新设计一遍我会做得更好。第一个是硬件上一定要预留UART回环测试点。UART回环只需要把TX和RX短接成本几乎为零但调试时能快速区分问题出在“链路层”还是“MCU应用层”。如果没有测试点每次排查都要动烙铁效率很低。第二个是寄存器配置尽可能参数化、模块化。GMSL2这类芯片的寄存器数量动辄两三百个如果初始化代码全部散在main函数里后面维护和移植都是灾难。建议做成配置表驱动把“寄存器地址-值-注释”写成结构体数组方便对照数据手册修改。第三个是关注控制通道带宽预算。UART虽然默认只有9600或115200波特率但控制通道除了UART还要承载I2C和远程GPIO。如果系统里同时有多个外设要通过控制通道访问最好提前算一下带宽避免后期功能多了才发现性能瓶颈。最后有一点建议如果项目有量产计划进入整车测试之前就要优先测GMSL链路在实车电磁环境下的误码表现不要只依赖实验室的短接线缆测试。UART over GMSL2在静态环境下确实很稳定但车载环境更考验的是连接器和线束的可靠性链路的问题往往是机械问题而不是芯片问题。