ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

菊花链与星形走线怎么选?从SPI到DDR的PCB拓扑实战指南

菊花链与星形走线怎么选?从SPI到DDR的PCB拓扑实战指南 前阵子评审一块新板子的原理图同事问了一个特别基础但每次都容易争起来的问题这路时钟信号走菊花链还是星形走线当时会议室里两位工程师给出了完全相反的结论谁也说服不了谁。这种事在硬件圈太常见了因为“菊花链”和“星形走线”这两个词本身不是同一维度的概念放在一起比容易越聊越乱。做了这么多年嵌入式硬件我越来越觉得要想把这块板子的拓扑定对不能只看“哪个好”得先看清你手里的信号是干什么的、速率多高、扇出多少个节点、后端协议允不允许这么连。这篇文章我把菊花链和星形走线从概念、选型、SPI场景下的实际接线与代码到PCB布线的实操经验和常见坑一次性讲透希望能帮正在为拓扑结构头疼的工程师省点工夫。1. 从一串葡萄说起菊花链和星形到底是怎么连的1.1 菊花链手拉手往末端传菊花链Daisy Chain这个名字形象点说就是“一串葡萄”或者“手拉手排队”。信号从链路头进入第一个设备处理完以后由第一个设备再传给第二个设备第二个传给第三个一路串下去直到最后一个节点收尾。数据或者信号在整条链路上是顺序流动的不是同时到达每个节点的。在芯片互联上最典型的例子就是SPI接口的片间级联。主控的MOSI接到第一颗芯片的数据输入第一颗芯片的数据输出接到第二颗芯片的数据输入第二颗再往第三颗接最后一颗的输出再接回主控的MISO。整个链上所有芯片共享同一个时钟SCLK共享同一个片选CS。在PCB走线里菊花链又是另一种表现形态。它指的不是数据在芯片内部的逻辑串联而是PCB上一条走线物理上“途经”多个器件引脚信号经过每个器件继续往末端走。典型例子是DDR内存颗粒的地址线和控制线走Fly-by拓扑走线从控制器出发先经过第一颗DDR颗粒的引脚再走到第二颗再到第三颗、第四颗最后在末端端接电阻处终止。1.2 星形走线一个中心四周开花星形走线就更好理解了中心节点向多个目的地分别拉出一条独立的走线像剥开的橘子中间一瓣一瓣围着圆心长或者像一个太阳向四周发光。每个分支相对独立信号从源端出发以后分别沿着自己的路径到达各自的负载。工程上经常说的“星形”其实大多数时候是T型分支走线。源端先拉出一段主干然后在某个位置分叉分成几路分别走向不同的终端。真正的“纯星形”是从源端直接分出N条线每条等长到目标这在PCB上比较少见因为源端引脚很难直接拉出多根线。但不管是纯星形还是T型分支核心特征都是一样的每个目的节点有一条相对独立的“专属通道”。在低频和协议简单的场景里星形走线特别常见。比如一颗I2C总线上挂多个传感器PCB上通常就是分叉接到各个器件又比如FPC排线里一根电源线分出几个分支给不同的负载都属于星形走线的范畴。1.3 两个概念什么时候会同时出现在一块板子上很多人刚接触这两个词的时候会觉得这是二选一的关系这块板子用了菊花链就不能用星形。实际上不是这样一块复杂的数字电路板里两种拓扑完全可以同时出现而且各有各的适用位置。最经典的是DDR3/DDR4内存电路。地址线、控制线、时钟线走菊花链Fly-by用一整条链把4颗或者8颗内存颗粒串起来而数据线DQ、DQS则严格走点对点或者星形等长线控制器分别连接每一颗颗粒的数据引脚彼此独立。同一个芯片不同的引脚不同的信号类型采用完全不同的拓扑策略这就是实战中最真实的状态。所以理解这两个概念不是去背“谁好谁坏”而是要搞清楚它们各自的形态特征、适用场景和限制条件。下面几章我就从选型逻辑一路讲到代码和PCB实操。2. 选型不是拍脑袋信号、速率、故障隔离决定拓扑2.1 信号完整性视角菊花链的连续性与星形的短桩冲突先看信号完整性。这是选型最核心的约束也是绝大多数工程师产生分歧的地方。菊花链走线在物理上是一条连续的、没有长分支的线路。信号从源端出发经过一个个中间节点最终到达末端。这条路径的特点是阻抗连续性比较好没有明显的“长桩线”Stub悬挂在走线上。每个中间器件引脚本身会带来一定的寄生电容让走线在这个位置产生一个局部阻抗下降但只要节点密度不是特别高、器件转换速率不是特别快影响是有限的。信号跑起来以后主要的反射集中在末端所以设计菊花链时通常会在末端加一个终端电阻让反射能量被吸收掉保证波形干净。星形走线恰恰相反。源端到每个负载都有独立路径从分支点看每条分支的远端都是开路状态。这意味着每一条分支都是一根“桩”。分支越长桩越长信号在分支末端反射回来的能量就越大会在源端的波形上叠加出明显的振铃、过冲和台阶。频率越高这个问题越严重。早年做一款双网口交换机交换芯片PHY芯片的MDI差分对之间做隔离变压器连接网络变压器次级到RJ45座之间的走线我为了做成“两边等距的星形”一条直路被拆成了两条大圈绕行。结果整板测试时长距离链路误码率明显偏高。后来改成从变压器引线走一段短线后直接进RJ45剩下的空间全给地平面误码现象就消失了。所以信号完整性的初判逻辑可以这么说高速、连续、一对多扇出信号优先考虑菊花链低速、扇出少、对反射不敏感的信号星形走线的灵活性和等长能力反而更有优势。2.2 扇出、布线资源与可维护性的取舍除了信号完整性这种“物理层面”的限制工程上还有一个重要维度布线的可实施性和后期可维护性。菊花链在PCB上的一大好处是省走线资源。一条线串完所有节点中间不需要反复拉回源端也不需要在分支点反复打换层过孔。尤其在DDR这种地址线有等长要求的场景走菊花链可以很自然地让走线沿着颗粒排布方向延伸末端汇聚在终止电阻附近等长计算也好做。但菊花链有明显短板链路中任何一个中间节点出问题整个链路就断了。如果是SPI协议层级的菊花链最前面的设备出问题后面所有设备全部失联如果是PCB物理上的菊花链走线断开后面的器件全都拿不到信号。这在调试和量产售后阶段非常难受。工业设备里如果板卡要面对现场复杂环境故障隔离能力是很重要的考虑因素这时候星形走线的优势就体现出来了每个分支互相独立一个分支上的器件坏了不影响其他分支正常工作。星形走线的问题则在于布线资源消耗大。N个负载就得拉N条独立的线每一条都要从源端或者分叉点独立走出占用的过孔数、走线面积都成倍增加。等长要求高的时候分支线还往往要绕来绕去在紧凑的板卡上很容易绕到地都劈不开。我个人的经验法则负载数量超过4个、信号速率高于50MHz的时候优先考虑菊花链因为它花了最少的资源解决了大部分问题负载数量少、速率又不高的I2C、低速GPIO、电源分配这类信号星形走线反而更稳妥调试的时候拔一颗器件不影响整条总线这种“省心”在日常维护里价值很大。2.3 协议决定的拓扑地图SPI、I2C、DDR总线的典型打法拓扑选型不只是电气工程师说了算还得看通信协议本来是怎么定义的。协议支持什么形态板上才能用对应的拓扑这是个硬约束。SPI是典型的灵活选手。标准SPI是一主多从、每个从设备独立CS的连接方式这在物理走线上通常表现为星形主控的SCK/MOSI/MISO拉出去分支分别接到各个从设备CS也是独立一根线各接各的。但SPI还支持菊花链模式前提是从设备硬件上支持SDI/SDO级联。级联以后主控只需要一根CS所有设备的时钟和数据在链上像流水线一样“流过”这在多个ADC同步采集、LED驱动芯片级联这类场景里非常实用。I2C协议本身是总线式设计所有设备挂在同一条SDA和SCL上地址用来区分设备。这种天然总线形态决定了物理走线上基本都是星形/T型分支不会有人把I2C设备接成“A设备SDA输出到B设备SDA输入”这种链式结构因为协议根本不允许这么玩。DDR总线则是最讲究的。命令/地址/控制总线是一对多扇出用的是菊花链Fly-by拓扑终端电阻放在链末端数据线是多对多控制器对多颗内存颗粒各连各的实际走线严格要求点对点和等长星形分支的短线也有严格限制。为什么数据线不能串成菊花链因为每一颗内存颗粒的DQ都是双向的控制器写数据时要给所有颗粒同时发读数据时要接收所有颗粒的返回双向信号在菊花链上的时序和反射问题会变成一场灾难谁做谁难受。协议决定拓扑形态这基本上是所有通信系统的默认规则。所以在拍板走线方式之前先把芯片手册里关于接口连接的说明翻清楚比任何仿真都管用。3. SPI菊花链从接线到代码一次真正跑通的完整链路3.1 引脚级连接把SDO当级联口把CS当成总开关这一节重点说SPI菊花链因为这个方向是热词里出现的重点也是实际项目里最容易被问“怎么接”“怎么写代码”的部分。先看硬件连接。以一个主控、三片支持菊花链的从设备为例主控的SCK接到所有从设备的SCK。主控的MOSI主出从入接到第一片从设备的SDI数据输入。第一片从设备的SDO数据输出接到第二片从设备的SDI。第二片的SDO接到第三片的SDI。第三片的SDO接回主控的MISO主入从出。主控的CS接到所有从设备的CS片选。这个接法里CS是所有从设备共用的“总开关”。CS处于高电平时所有从设备不工作CS拉低以后整条链进入工作状态每个SCLK脉冲会把主控发出的数据沿着链“推进一步”同时把每个从设备要上报的数据往链尾方向推一步。SCLK跑完需要的脉冲数以后CS拉高整条链路完成一次读写。需要特别注意的是并不是所有SPI从设备都支持这种级联方式。很多普通芯片的SDO只是片选有效时把本片寄存器里的数据移出来而不是把输入数据逐级传下去。数据到底能不能从SDO往下一个芯片继续传要看芯片手册里有没有“Daisy-Chain Mode”或者“SDO daisy chain”这样的描述。3.2 时序原理SCLK转几次数据才算真正到位理解了物理连接再去看时序就简单了。SPI菊花链的本质是“将所有从设备的移位寄存器串成一个长移位寄存器”。每一片从设备的内部通常有一个数据移位寄存器SCLK上升沿/下降沿到来时芯片会把自己移位寄存器里的数据锁存一位同时把输入引脚上的数据移进来。假设每片从设备需要16个SCLK才能完成一次数据交互三片级联时整条链就需要3×1648个SCLK。这48个SCLK必须在CS拉低期间全部打完。CS拉高之后每片从设备会把锁存在自己内部寄存器里的数据并行输出到对应的IO口或者DAC输出等负载上去。数据顺序上要格外小心。主控第一个字节发送出去以后先进入第一片从设备但这个数据最终会随着SCLK的继续推送“流”到链的更深处。也就是说主控发出的第1个字节最终会到达链尾的芯片主控发出的最后一个字节反而停留在离它最近的第一片芯片里。如果配置字需要按照“第一片芯片的配置、第二片芯片的配置、第三片芯片的配置”这样从左到右对齐发送顺序往往是反过来的。具体以芯片手册为准每个系列的说明方式还有差异但绝大多数手册都会画一张“数据顺序图”照着那张图填数据就没错。3.3 代码实现多字节发送、配置字排序与锁存时序代码层面SPI菊花链用MCU的硬件SPI外设发送是最简单的本质上就是一次多字节的同步收发。以STM32的HAL库为例思路是这样的#define CHAIN_DEVICE_COUNT 3 // 级联设备数量 #define BITS_PER_DEVICE 16 // 每片设备的数据位数 uint8_t tx_buf[CHAIN_DEVICE_COUNT * BITS_PER_DEVICE / 8]; uint8_t rx_buf[CHAIN_DEVICE_COUNT * BITS_PER_DEVICE / 8]; // 构造配置字注意数据排列顺序与芯片手册保持一致 // 这里假设手册要求tx_buf[]中先填链尾设备的配置再填中间的最后填链首的 for (int i 0; i CHAIN_DEVICE_COUNT; i) { uint16_t cfg device_config[i]; tx_buf[i * 2] (uint8_t)(cfg 8); // 高位在前 tx_buf[i * 2 1] (uint8_t)(cfg 0xFF); // 低位在后 } // CS 拉低开始传输 HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET); HAL_SPI_TransmitReceive(hspi1, tx_buf, rx_buf, sizeof(tx_buf), HAL_MAX_DELAY); // CS 拉高锁存 HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);这段代码有几个细节容易踩坑第一个坑是SCK空闲电平和采样沿。有些SPI从设备要求CPOL0、CPHA1有些要求CPOL1、CPHA0。如果配置不对读回来的数据会整体错位一位或者全错。我习惯在初始化的地方先打印一下读回的原始值确认每一位的对应关系再继续往下开发。第二个坑是CS用硬件NSS还是软件GPIO。在菊花链模式下我一般用普通GPIO做CS因为这样能在CS拉低到第一个SCLK之间插入可调延时对某些要求CS建立时间的芯片特别管用。硬件NSS虽然省事但是在多字节连续传输的过程中可能出现CS中间跳变的不可控情况尤其在SPI外设配置不太干净的时候。第三个坑是RCLK锁存信号。不是所有设备都在CS拉高时锁存数据。比如级联的74HC595移位寄存器真正的输出锁存是靠RCLK上升沿触发的。如果用SPI主控驱动多片74HC595流程应该是这样// 先清零锁存引脚 HAL_GPIO_WritePin(RCLK_GPIO_Port, RCLK_Pin, GPIO_PIN_RESET); // 通过 SPI 发送 N 帧数据 HAL_SPI_Transmit(hspi1, send_buf, frame_count, HAL_MAX_DELAY); // 全部移位完成后再拉高锁存引脚并行输出 HAL_GPIO_WritePin(RCLK_GPIO_Port, RCLK_Pin, GPIO_PIN_SET);74HC595这类芯片级联时主控只需把要显示的数据按顺序拼好一次性发出去数据会自动从第一片流向后面的芯片最后RCLK一个上升沿所有芯片的输出引脚同时更新。这类应用里CSOE甚至可以常接地拉低只要控制RCLK的时机就行。3.4 Linux设备树与驱动侧的注意点如果用的是SoC跑Linux比如全志、瑞芯微、NXP i.MX这类平台SPI菊花链的设备树写法和普通单设备略有区别但也不复杂。因为整条菊花链从主控角度看只有一根CS线所以设备树里往往只注册一个SPI设备节点代表整条链。芯片的“级联长度”属性一般通过自定义device tree属性传给驱动。拿一款支持菊花链的ADC为例设备树大致长这样spi0 { status okay; pinctrl-names default; pinctrl-0 spi0_pins; adc_chain: adc-chain0 { compatible vendor,daisy-chain-adc; reg 0; spi-max-frequency 1000000; #address-cells 1; #size-cells 0; daisy-chain-size 4; /* 自定义属性表示链上有4片ADC */ }; };驱动侧需要注意普通SPI驱动读取数据的长度由传输长度决定而菊花链驱动需要把长度设置成“链上设备数 × 单设备位数”。很多人在这一步踩坑读回来的数据只有第一片设备的后面三片全是0就是因为传输长度只设置了一个设备的宽度SCLK脉冲数不够数据根本没推完。另外SPI速度不要一味往高了调。菊花链的SCLK是同时到达所有设备的但每个设备内部的移位寄存器传播有一定延时数据从链首传到链尾需要时间。SPI速率太高时链尾设备可能还没收到完整数据CS就已经拉高了。具体能跑多快芯片手册上通常会有“Daisy Chain Frequency”相关的说明或者建议值。如果没有我习惯先按1MHz跑通再用逻辑分析仪看波形慢慢往上提。4. PCB走线的实操细节哪些坑我替你踩过了4.1 DDR总线上的Fly-by地址线走菊花链数据线走星形如果有机会看一份成熟的DDR3/DDR4 Layout Guide你会发现里面写的拓扑规则高度一致地址、命令、控制、时钟走Fly-by菊花链数据线和数据选通线走点对点等长。芯片原厂比如Intel、Synopsys为什么会这么规定原因前面提到过地址线是单向的、一对多扇出所有颗粒同时采样同一组地址信号用菊花链连接可以让所有颗粒看到信号的时间差尽量小同时避免大片的分支桩线造成信号反射。末端放一个终结电阻VTT端接吸收反射链上每个颗粒的引脚到走线的连接线都非常短寄生参数相对可控。数据线不一样。DQ、DQS是双向的控制器的IO要往颗粒写数据颗粒也要往控制器读数据。如果像地址线那样串联读数据时数据需要一路传回时序复杂度和信号完整性问题会成倍增加。所以数据线必须点对点物理上与每颗颗粒单独相连然后通过等长设计保证所有数据线从控制器到颗粒的传播延时一致。这里说的“点对点”在物理上往往看起来像星形——控制器引脚出发分别连接到多颗颗粒的数据引脚。实际走线经验地址线走菊花链时从控制器出来以后尽量先经过离它最近的颗粒再往远端走别先绕远再回来不然链的路径会互相交叉。菊花链上的颗粒引脚出线尽量垂直主干线引脚到主干的长度越短越好。很多DDR Layout规则会要求这个长度小于某个阈值比如150mil以内。末端端接电阻放在最后一颗颗粒之后电阻位置不能离最后一个颗粒太远否则起不到端接效果。4.2 星形分支长度不匹配时序裕量去哪了星形走线最容易被忽略的问题是分支长度不匹配。想象一下一个时钟源通过T型分支送给两颗芯片一路走了5mm就到另一路绕了20mm才到。信号在T型节点处的“第一次经过”是同时的但是分支末端的反射回来时间不一样。高频下第一路的反射已经回到源端叠加了第二路还在半路上波形就会变得特别“脏”个别情况下直接导致采样错误。等长处理是星形布线里必不可少的一步。设计时最好在原理图阶段就把所有要求等长的网络标出来写进Layout guide。以我常用的做法为例源端到分支点的主干尽量短分支出去以后各路的长度差控制在时钟上升沿对应的传播距离的1/10以内。怎么估算FR4板材中信号传播速度大约是每纳秒150mm左右如果一个时钟信号上升沿是1ns那么1ns内信号在板子上跑约150mm长度差最好控制在15mm以内。这只是粗略的工程估算高速场景还得靠仿真但作为初筛规则非常实用。星形分支的另一个实操细节是串阻的位置。很多工程师喜欢在源端串一颗22Ω或者33Ω的电阻来抑制反射但电阻的位置很重要。串阻应该放在源端和T型分支点之间也就是在主干的起点处而不是放在某个分支的末端。放在主干起点电阻能对整棵树的反射全部起到阻尼作用只放在某个分支上其他分支的反射照样反弹回源端等于没处理干净。4.3 常见问题排查速查表下面把这个领域最常见的几类问题和排查方向整理成表方便实际遇到时快速定位。问题现象可能原因排查方向SPI菊花链读回的数据全部为0传输长度不够SCLK脉冲数少于链设备数×每设备位数核对驱动中的传输长度设置链路上某一片设备始终收不到数据中间某一级的SDO没有正确使能或硬件焊接问题检查SDO到下一级SDI的连接、芯片模式寄存器配置波形出现明显振铃、过冲分支桩线过长分支间长度差过大源端缺少匹配电阻重新规划走线分支加源端串阻缩短Stub高速下数据偶发错误降速后正常SCKL速率超过链路传播能力或信号质量裕量不足降低SPI速率加长CS建立时间检查走线阻抗I2C总线一挂多时总线时钟纹波大总线分支过多分支长度不统一上拉电阻选值不当统一各分支长度调整上拉电阻必要时平面铺地隔离这张表里的问题我基本都在实际项目里遇到过尤其是“链上某一片设备收不到数据”这一条排查过程往往非常折腾。后来养成了习惯新板子调试SPI菊花链先把链上所有设备的SDO输出依次写一个固定字节再读回来判断每一级是否通如果发现某一级不对直接拿示波器量那一级的SDI和SDO波形对比主控发出的数据时序一量基本就能定位是硬件还是配置问题。还有一个小经验是切换板级器件的时候不要把原来的GPIO初始化顺序改动。某些SPI从设备在CS高电平时SDO是高阻态如果链上好几片都是高阻整条MISO线上会出现浮空电平干扰。GPIO顺序不对可能导致初始化时某一片提前进入了非预期状态让链路的初始相位错乱。5. 写在后面的话个人经验收尾聊了这么多最后还是回到那个最常见的质疑菊花链和星形走线到底哪个更好我的回答一直是不要给拓扑定性要看你手里的信号是什么性格。串联的一串设备省线、省IO、天然适合高速连续传输但牺牲了故障隔离各拉各线、分支独立的星形走线灵活、易排查、对低速率友好但牺牲了布线资源和高速性能。真正的高手不是背出答案而是画完拓扑图以后能说出为什么要这么走知道万一出问题该在哪个节点量波形。我自己的习惯是在项目原理图评审阶段就画一张“信号拓扑草稿图”把所有需要重点关注的信号全列上去标清楚速率、方向、扇出数量、末端匹配方式。50MHz以上的并行单向信号默认考虑菊花链低速总线和多电源分配默认星形遇到有争议的再翻手册加仿真验证。这张图花不了半小时但省下的调试时间往往是论天算的。如果你正在做的板子也遇到“有人说走菊花链、有人说走星形”的局面不妨先把两边的主张对应的物理原理理一遍再拿一颗示波器探头验证一下哪个节点波形最差。实践出真知这一步做完以后再遇到类似的芯片和接法心里基本就有底了。
返回列表