CameraLink Base/Medium/Full带宽、端口映射与调试避坑 简介围绕Camera Link相机输出Base、Medium、Full三种模式的接口配置这份文档面向工业相机与图像采集卡选型、调试及视觉系统集成人员帮助厘清不同模式下Channel Link路数、并行视频位宽、相机控制与串行通信线对的差异。内容从Camera Link标准产生背景和Channel Link技术优点切入说明其基于LVDS多路复用的连接方式依次展开基本模式、中级模式、完整模式的收发器配置、最高28/56/84位并行传输能力与线缆使用特点并涉及端口A至H的定义和分配。压缩包内为1个doc文件约168KB便于按主题查阅。已有2116人学习下载。读者可据此核对相机与采集卡接口是否匹配理解三种模式在带宽、连接与布线上的取舍为高分辨率工业视觉方案设计和现场排错提供参考。1. 从一台 8K 线扫相机说起Base、Medium、Full 三档到底差在哪去年帮某实验室调一台线扫相机8K 像素、12 位输出相机铭牌写着 CameraLink采集卡也标 CameraLink插上去就是黑屏。翻了两天才发现不在代码而在模式相机按 Base 输出采集卡默认按 Full 的三组通道轮询第二、三组端口上全是悬空数据帧有效信号对不上图像自然出不来。搜 CameraLink 的资料网络上铺天盖地是 26-pin 引脚表讲清楚 Base、Medium、Full 这三档怎么选、带宽怎么算、端口怎么铺的反而少。这三档不是速度档位开关是实打实的 1 组、2 组、3 组 Channel Link 通道装几组就只传几组像素位多出来的位宽拿钱也买不到。2. Channel Link 与 LVDS 的底子为什么带宽按 28 位一档往上加2.1 一组 Channel Link 就是 28 位并行转 4 对 LVDSCameraLink 的物理层不是什么自研黑科技是把一组 Channel Link 收发器搬过来用。发送端收进 28 位单端 CMOS/TTL 并行信号加 1 路时钟做 7:1 串行化拆成 4 对 LVDS 数据流加 1 对 LVDS 时钟流一共 5 对差分线接收端再把 4 路串行数据连同恢复出来的时钟还原成 28 位并行数据和一个同步时钟。所以一组通道的原始位宽被钉死在 28 位这就是后面所有模式划分的物理天花板。LVDS 本身的电气参数决定了它能跑多远差分摆幅 350mV 左右靠差分对抵消共模噪声跳变快、功耗低理论极限在 1.9Gbps 量级。Channel Link 把 4 对数据线一起用单组能到 2.38Gbps。这个数字不是随便写的它等于像素时钟乘 7 再乘 4 对85MHz × 7 × 4 ≈ 2.38Gbps。看懂了这条乘法后面算带宽就不用查表了。线缆侧的收益也很直观。同样传 28 位数据传统 RS-422 方案要在线上挂 56 只终端电阻换成 Channel Link 只要 11 只4 对数据线 8 只、1 对时钟线 2 只、加最多 1 只地。终端电阻少意味着连接器可以做小、屏蔽要求可以降、线缆能大批量做这才是 CameraLink 当年能统一工业相机接口的真实原因——不是性能碾压是把整条链路的成本压下来了。2.2 三档模式复用的是同一套东西只是叠加了几组标准把 28 位拆开用24 位给像素数据端口 A、B、C 各 8 位剩下 4 位塞视频使能信号——LVAL行有效、FVAL帧有效、DVAL数据有效和一个 Spare分别落在串行器的第 24、25、26、23 号引脚上。这个分配在三种模式下都一样只是通道组数不同。模式Channel Link 组数像素端口有效像素位宽线缆根数典型每周期像素数8 位Base1A、B、C24 位13Medium2AF48 位26Full3AH64 位28注意 Full 那一行三组 28 位加起来是 84 位但第三组只引出 G、H 两个端口共 16 位像素数据剩余位宽没有定义成像素槽。所以 Full 的有效像素位是 24 24 16 64 位不是 84 位。很多选型表上写「84 位」指的是通道位宽总和拿它去算像素率会算高一截这是血泪经验。还有一条容易被忽略相机控制信号 CC1CC4 和串行通信 SerTC、SerTFG 走的是独立的 RS-644 LVDS 差分对不占 Channel Link 的 28 位而且在三种模式下永远只有一组。这 4 对控制加 2 对串口加上第一组 Channel Link 的 5 对正好 11 对差分塞满一个 26-pin MDR。第二组、第三组没地方放了所以 Medium 和 Full 必须上第二根线缆这就是它们要两根线的全部原因。2.3 把带宽算成 MB/s像素时钟、tap 数与位深的三角关系选型时最常被问的一句是「我这台相机能不能接 Base 卡」。答案不在相机分辨率而在这三个数的乘积像素时钟、每时钟输出的像素数tap、单像素位深。三者乘积不能超过模式给出的位宽预算。用代码把这件事算清楚改参数就能复用# CameraLink 三档模式的位宽预算与实际吞吐估算 MODES { # ports: 有效像素端口数每端口 8 位; cables: 需要几根 MDR 线缆 Base: {groups: 1, ports: 3, cables: 1}, Medium: {groups: 2, ports: 6, cables: 2}, Full: {groups: 3, ports: 8, cables: 2}, } def budget(mode, clock_mhz85, bits_per_pixel8): m MODES[mode] payload_bits m[ports] * 8 # Base 24 / Medium 48 / Full 64 pixel_rate payload_bits / bits_per_pixel # 每周期能塞几个像素 max_taps int(pixel_rate) # 必须向下取整不能取半像素 gbps payload_bits * clock_mhz / 1000.0 # 有效像素带宽 mbyte gbps * 1000 / 8 # 换算成 MB/s return { mode: mode, payload_bits: payload_bits, max_taps: max_taps, clock_mhz: clock_mhz, payload_gbps: round(gbps, 2), mbyte_per_s: round(mbyte, 1), cables: m[cables], } for mode in (Base, Medium, Full): for bits in (8, 10, 12): r budget(mode, clock_mhz85, bits_per_pixelbits) print(f{r[mode]:6s} {bits:2d}bit - {r[max_taps]} tap, f{r[payload_gbps]} Gbps, {r[mbyte_per_s]} MB/s, {r[cables]} 根线) # 相容性判断相机需要的 tap 数超过预算就是接不上不是调参能救的 need 4 # 相机手册标称 4 tap bits 12 for mode in (Base, Medium, Full): ok need * bits MODES[mode][ports] * 8 print(f{need} tap x {bits} bit 能否跑 {mode}: {ok})这段逻辑里有两个参数必须理解清楚。clock_mhz不是相机标称的帧率是像素时钟常见档位 40/66/85MHz对应收发器芯片的不同速度等级85MHz 是 3.3V 器件里比较通用的一档。bits_per_pixel要按真实输出位深填不能按「反正 8 位够用」拍脑袋12 位像素在 Base 模式下最多只能塞 2 个 tap24/122想跑 4 tap 12 位必须上 Medium。跑出来的结论很直观85MHz 下 Base 的有效像素带宽约 2.04Gbps、255MB/sMedium 约 4.08Gbps、510MB/sFull 约 5.44Gbps、680MB/s。拿相机的「分辨率 × 位深 × 帧率」直接和这三个数比比看任何选型表都快。提示算完带宽还要留 20% 余量。像素时钟是标称值实际相机内部 PLL 会有偏差采集卡侧的时钟恢复也有抖动贴着上限跑在长线缆上很容易偶发丢行。选型的三步走先按位深和 tap 数算出每周期需要的位宽卡进 24/48/64 三档再看相机像素时钟是否超过采集卡收发器等级最后确认采集卡是否支持所需的线缆根数和通道分组。三步里任何一步不过换卡比调参便宜。3. 端口分配不是顺序的AH 八个端口怎么落到真实像素3.1 端口是 8 位逻辑字和 TX/RX 引脚编号是错位的这是 CameraLink 里最容易翻车的一处。直觉上端口 A 的 8 位应该接着串行器的 TX0TX7实际标准给的映射是打乱的A0 接 TX/RX0、A1 接 1、A2 接 2、A3 接 3、A4 接 4、A5 接 6、A6 接 27、A7 接 5。B 端口更乱7、8、9、12、13、14、10、11。C 端口15、18、19、20、21、22、16、17。为什么要这么排因为 28 位信号在 PCB 上走线时要兼顾串行器引脚顺序、连接器引脚顺序和差分对的分组最终选了一个对布线最友好的方案代价是逻辑位序被打散。这个映射由标准固定改不了只能在 FPGA 或采集卡固件里按表重排。同组内端口复用也是这个逻辑端口 D 与端口 A 共用同一批 TX/RX 引脚端口 E 与 B 相同端口 F 与 C 相同第二组通道的 G、H 也一样复用 A、B 的引脚。所以「端口」是逻辑槽位「引脚」是物理通道一组 28 位里能塞下三个 8 位端口加 4 位控制靠的就是这种复用。3.2 从 1 tap 到 8 tap像素怎么铺到端口上单像素输出时只用了端口 A像素的 bit0bit7 依次落到 A0A7。双 tap 时第一个像素走 A、第二个走 B。三 tap 走 A/B/C。这就是 Base 模式的上限。Medium 再加一组D/E/F 承接第 46 个像素。Full 再加 G/H凑到 8 个。位深超过 8 位时一个像素要跨两个端口。常见的 10 位、12 位相机会把低 8 位放一个端口、高位放另一个端口剩余高位补零或填其他信息。这里没有强制规定不同厂商的打包方式可能不同必须以相机手册的「Pixel Format / Tap Geometry」章节为准。我见过一家相机把 12 位拆成「低 8 位在 A、高 4 位在 B 的低 4 位」也见过反过来的接错就是灰度值整体错位但图像轮廓还在特别迷惑人。3.3 用脚本把映射表生成出来对帧格式时直接用手工抄映射表容易出错尤其是要写 FPGA 解串模块或者配置采集卡的端口重排寄存器时。下面这段把标准和常用 tap 配置一起生成输出可以直接贴进约束文件或配置表# CameraLink 端口位 - Channel Link 串行器引脚号单组 28 位基准 PORT_PIN { A: [0, 1, 2, 3, 4, 6, 27, 5], B: [7, 8, 9, 12, 13, 14, 10, 11], C: [15, 18, 19, 20, 21, 22, 16, 17], } # 复用关系第二组 G/H 与第一组 A/B 同引脚D/E/F 同 A/B/C REUSE {D: A, E: B, F: C, G: A, H: B} # 视频使能与杂项位同样落在 28 位里不占像素端口 CTRL_PIN {Spare: 23, LVAL: 24, FVAL: 25, DVAL: 26} def dump(mode_taps): mode_taps: 每周期像素槽列表如 [A,B,C,D] 表示 4 tap used [] for idx, port in enumerate(mode_taps): base REUSE.get(port, port) # 映射回复用前的基础端口 pins PORT_PIN[base] used.append((idx, port, base, pins)) print(ftap{idx} - Port{port} (复用 {base}) 引脚: {pins}) # 校验像素端口 控制位不能超过 28 total len(mode_taps) * 8 len(CTRL_PIN) assert total 28, f位宽超限: {total} 28需要升一档模式 print(f本组占用 {total}/28 位剩余 {28 - total} 位) print( Base 3 tap 8bit ) dump([A, B, C]) print( Medium 6 tap 8bit ) dump([A, B, C, D, E, F]) print( Full 8 tap 8bit跨两组通道) dump([A, B, C, D, E, F, G, H])REUSE这个字典是关键它体现「D 和 A 共用引脚」这条规则assert那行是后悔药tap 配多了会直接抛异常而不是悄悄生成一张错的表。实际对帧格式时还要把每个 tap 的像素顺序和相机的 Tap Geometry 对齐比如 4 tap 相机常见的排列是 A/B/C/D 或 A/C/B/D 交替这个顺序错了图像会出现规律性条纹肉眼一看就知道是排布问题而不是链路问题。注意G、H 只在 Full 模式的第三组通道上出现且第三组只引出 16 位。写解串逻辑时如果按 8 个端口 × 8 位 64 位去分配缓冲区第三组的高 8 位要显式填零或丢弃否则拼出来的行会整体偏移。4. 连接器、线缆与四条控制线硬件侧最容易翻车的地方4.1 26-pin MDR 的引脚分组11 对差分怎么分连接器用 26-pin MDRMini D Ribbon针脚分配是标准固定的临时拿别的连接器替代基本没戏。26 根针的分组逻辑是第一组 Channel Link 5 对4 数据 1 时钟占 10 针相机控制 CC1CC4 共 4 对占 8 针串口 SerTC/SerTFG 共 2 对占 4 针剩下 4 针是内外屏蔽。功能组差分对数说明第一组 Channel Link54 对数据 1 对时钟承载 A/B/C 端口相机控制 CC1CC44采集卡输出、相机输入低电压差分串行通信 SerTC/SerTFG2一发一收异步串口内屏蔽2 针推荐在相机端接数字地第二组 / 第三组 Channel Link5 5只在第二根线缆上出现第二根线缆的结构更简单Medium 只用 5 对第二组Full 用 10 对第二组 第三组剩下的是屏蔽和空脚。所以 Full 模式的两根线缆不能随便互换——第一根带控制和串口第二根纯数据插反了相机连指令都收不到。4.2 线缆选型只看三个参数长度、屏蔽、双绞标准给的边界是 10 米实际工程里我一般按 35 米设计超过 5 米就要开始怀疑。这不是保守是 LVDS 在 85MHz 像素时钟下7:1 串行化后单对线上的符号率已经到 595Mbps 量级线缆的插入损耗和差分 skew 直接吃掉眼图余量。选型看三点。长度成品线有 1m、2m、3m、5m、7m、10m 几档别自己剪线压接MDR 的压接工艺对阻抗一致性要求很高手工做的接头在 85MHz 下十有八九出问题。屏蔽必须是双绞加整体屏蔽结构每对差分线单独双绞外层再包一层屏蔽内屏蔽按标准推荐接相机侧数字地采集卡侧通过 0Ω 电阻下地。双绞时钟对和数据对不能随意并排走时钟对要单独包地或者远离数据对否则时钟串到数据对上就是全屏随机噪声。没用到的差分对必须处理。标准明确推荐在两端各接 100Ω 终端电阻因为悬空的差分对在高频下就是天线反射回来的能量会耦合到相邻对上。Base 相机接 Full 采集卡时第二、三组通道全悬空如果采集卡侧没做内部终端出图随机丢行几乎是必然的。4.3 控制信号与串口CC1CC4 的默认含义和最小通信配置4 对控制线是采集卡输出、相机输入具体含义由相机制造商定义但行业里有一套约定俗成的默认用法调试时先按这个试信号常见定义有效电平/边沿CC1外触发 EXSYNC下降沿触发一帧/一行CC2像素重置 PRIN低电平有效CC3扫描方向 FORWARD高电平正向低电平翻转CC4厂商自定义看手册这套默认不是标准强制的接上去没反应先别怀疑硬件翻相机手册确认 CC 极性。我踩过一次 CC1 极性搞反的坑触发信号发出去相机一动不动示波器量电平完全正常最后发现相机要的是上升沿而采集卡默认下降沿改个寄存器就好。串口那边简单得多2 对 LVDSSerTC 是采集卡发、相机收SerTFG 反过来。协议用异步串口格式1 起始位、8 数据位、1 停止位、无校验无握手最小波特率 9600。标准要求采集卡厂商提供 API 让用户通过动态库管理串口同时建议提供一个终端程序能收发字符串或短文件。实际用起来多数采集卡会把相机串口映射成系统里的一个串口设备或者封装成 SDK 里的 SerialPort 对象两种都行看厂商实现。调试阶段建议先用 9600 波特率握手通了再往上提。有些相机支持到 115200 甚至更高但高波特率对线缆和终端匹配更敏感链路本身还没验证稳的时候提波特率出问题分不清是串口配置错还是物理层不行。5. 避坑与排查Base 相机插上 Full 采集卡为什么一片黑5.1 现象图像全黑或全零帧有效信号一直不来原因通常不在物理连接在通道分组。采集卡默认按 Full 的三组通道轮询第一组的 FVAL 来了但它还在等第二、三组的使能拼帧状态机卡在半路。另一种情况是采集卡有「通道选择」参数出厂默认 Channel 1而相机接的是另一个物理口。解决先把采集卡配置改成 Base / 单通道模式观察 FVAL 和 LVAL 是否出现。如果采集卡支持通道自动检测让它跑一次自检不支持的手动指定第一组通道。确认出图后再逐级往上加模式一次只改一个参数。5.2 现象图像整体正常但左右半幅错位或者出现规律性的竖条纹原因基本可以锁定在 tap 排布或端口位序。4 tap 相机常见两种几何像素按 A/B/C/D 顺序轮转或者 A/C 一组、B/D 一组交替。两种都合法但采集卡的解析必须和相机一致。另一种是端口位序没按标准重排直接按 TX/RX 顺序当成了 A0A7结果每个字节内部的位是乱的。解决用渐变测试图或者棋盘格图看错位规律。如果错位周期等于 tap 数是 tap 几何问题改采集卡的 tap 顺序参数如果整幅图像的灰度值都不对但轮廓正确是位序问题按第 3 章的表重排。手边没有测试图的话拿一张均匀灰卡正常应该是一条直线位序错了会出现阶梯。5.3 现象跑几分钟后开始随机丢行重新插拔线缆能好一阵这是典型的物理层余量不足。三种常见诱因线缆超过 5 米、不是标准双绞屏蔽结构、没用到的差分对悬空没接终端。随机丢行的特点是跟温度和时间相关冷机好好的跑热了开始出因为线缆损耗随温度上升。解决先换一根短的标准线缆排除线材再把像素时钟降一档85MHz 降到 66MHz看是否消失如果降频就好了说明链路余量不够要么换线要么降频。悬空对补 100Ω 终端相机端和采集卡端都要。做完这三步还在丢查一下相机和采集卡的供电地是不是同一路地电位差大了 LVDS 共模范围会被顶出去。5.4 现象串口发指令没回应或者回的是乱码乱码优先查波特率和帧格式没回应优先查线序和极性。CameraLink 的串口是交叉连接的采集卡的 SerTC 输出接相机的串口输入SerTFG 反过来两端都标着 SerTC/SerTFG 但方向相反画板子时接成同名对同名就废了。解决先用示波器或者逻辑分析仪抓 SerTC 上看有没有波形没有就是采集卡侧没发出去查 SDK 的端口号是否选对有波形但相机不回把 SerTC 和 SerTFG 对调试试。波特率从 9600 起步帧格式固定 8N1不要开流控——标准里根本没有硬件流控线。5.5 现象12 位相机在 Base 模式下图像高位丢失灰度只有 0255常见误解是「Base 模式 24 位12 位像素能跑 2 个 tap肯定没问题」。问题出在打包方式有些相机在 Base 模式下只启用端口 A 传低 8 位高 4 位放在端口 B 的低 4 位剩下的 4 位空着采集卡如果按 16 位对齐去取取到的就是错位的数据。解决翻相机手册的 Pixel Format 章节确认 12 位是「低位对齐打包」还是「高位对齐打包」在采集卡的像素格式里选对应项。实在找不到对应项就自己在 FPGA 或上位机里做位移和拼接用一张 12 位渐变的测试图验证正常应该从 0 平滑到 4095出现台阶就是位移量错了。6. 上电前的五步核对把像素时钟、tap 数与端口映射一次对平链路调通之后我把每次新项目的上电检查固化成了五步顺序不能乱因为后面每一步都依赖前一步的结论。第一步确认相机输出的模式和 tap 数读相机寄存器或者看铭牌不要凭印象第二步按第 2 章的算法核一遍位宽预算tap 数乘位深必须小于等于 24/48/64第三步确认采集卡的通道分组和线缆根数匹配Base 一根、Medium/Full 两根第二根只走数据第四步串口握手9600 8N1 发一条读寄存器指令能回就说明控制和通信链路都活着第五步才去跑图像先用均匀光看直方图再用渐变图看位序。串口握手这一步可以脚本化省得每次开终端敲import serial # 采集卡把相机串口映射成系统串口设备时9600 8N1 无流控是最小可用配置 # Linux 下常见 /dev/ttyUSB0Windows 下常见 COM3按设备管理器/udev 实际改 def handshake(port, cmd: bytes, expect_len8): with serial.Serial(port, baudrate9600, bytesize8, parityserial.PARITY_NONE, stopbits1, timeout0.3) as ser: ser.reset_input_buffer() ser.write(cmd) # 指令字节按相机手册的寄存器读命令填 resp ser.read(expect_len) if not resp: print(f{port}: 无回应先查 SerTC/SerTFG 是否交叉、波特率是否一致) else: print(f{port}: 收到 {len(resp)} 字节 - {resp.hex( )}) return resp # 示例读相机型号寄存器字节内容以厂商手册为准这里只演示调用结构 handshake(/dev/ttyUSB0, bytes([0x01, 0x00, 0x00]))这段代码的价值不在功能在把「有没有回应」这件事变成可重复的一行输出。timeout设 0.3 秒是有讲究的太短了相机还没处理完就超时太长了链路断了也要等半天才报错。reset_input_buffer是防止上一次残留数据混进来调试阶段被这个坑过一次——缓冲里存着上次的半个响应拼接出来像是相机回了乱码白查了两小时线序。还有一个小技巧值得记验证端口位序不要用实拍图用相机自带的测试图发生器很多工业相机内置渐变、棋盘格、灰阶几种图案。图案是相机内部生成的不经过镜头和光照出问题就 100% 是链路和解析的问题把变量砍掉一半。我一般先用水平渐变看位序出现阶梯就是位移错再用棋盘格看 tap 几何错位周期等于 tap 数就说明排布对不上。从那以后我每次接新相机不管对方说得多肯定上电前都强制走一遍这五步尤其是第二步的位宽预算用脚本算一遍只要十秒钟比事后怀疑人生划算得多。希望帮到你。本文还有配套的精品资源点击获取