ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

AD7606采样率上不去?SPI与FSMC并行接口实测对比

AD7606采样率上不去?SPI与FSMC并行接口实测对比 做多通道数据采集的人大概率绕不开AD7606这颗芯片8通道同步采样、16位分辨率、支持±5V和±10V双极性输入外加片上滤波和过采样放在工业现场非常能打。但很多人真正上手后会卡在同一个地方——采样率上不去。我见过不少工程师用STM32的SPI去读AD7606忙活半天只能跑六七十kSPS最后怀疑是芯片标称参数有问题。其实问题不在ADC而在接口选型。这篇文章把两种常见姿势放在一起做了一组实测对比一种是最传统的SPI串行读取另一种是把AD7606挂到STM32H7的FSMCH7官方叫法FMC并行总线上。先放结论SCLK25MHz时SPI方案实测约95kSPSFSMC并行方案实测逼近200kSPS恰好翻倍还多。这篇文章不打算只给结论更想把背后的原理、接线、CubeMX配置、代码和踩坑都摊开讲。如果你正在选型、或者手里的AD7606迟迟跑不到理想采样率下面这些内容应该能帮上忙。1. 项目概述为什么AD7606值得把接口方案抠到极致1.1 这颗ADC的定位与典型应用场景AD7606是ADI推出的一款8通道同步采样ADC内置16位逐次逼近型转换核每个通道都有独立的采样保持器因此8个通道可以真正做到同一时刻采样而不是像通道轮询那样存在相位差。这对于电力系统的三相电压电流分析、电机驱动器的相电流采集、振动监测、声学阵列等场景非常关键。另一个让它受欢迎的地方是前端模拟电路非常省心。芯片内部集成了输入缓冲放大器、一阶抗混叠滤波器、双极性电源基准等单5V供电就能处理±10V的工业信号不需要额外配运放和负电源。开发板级别的模块也很多几十块钱就能买到现成板子焊上排针就能用。但回到真实项目里很多人只用到了它一半的性能。200kSPS的最大吞吐率写在手册上实际系统却常常因为读取接口太慢只能工作在80~100kSPS甚至更低。这里的关键在于AD7606的ADC转换核心很快慢的是我们往外倒数据的方式。1.2 采样率瓶颈到底卡在哪里先搞清楚AD7606的工作节奏。一次完整的采样周期可以拆成两段转换阶段CONVST引脚收到上升沿后内部ADC启动转换BUSY引脚拉高。转换完成后BUSY拉低8个通道的结果被锁存到输出寄存器。这个阶段典型耗时约4us。读取阶段CPU需要把8个通道的结果从芯片搬进内存。如果使用并行接口每读一个16位结果只需几十纳秒如果使用SPI串行接口则至少需要128个SCLK时钟16位×8通道而且所有数据都从一根线串行移出。注意一个关键约束读取阶段必须在下一轮转换开始前完成否则旧数据会被新结果覆盖。手册给出的最大吞吐率200kSPS换算下来采样周期是5us。扣除4us转换时间留给读取的时间只有约1us。SPI方案在1us内要倒完128个bit需要SCLK不低于128MHz这在AD7606上根本不现实。而FSMC并行方案读取8个16位数据只需要约300ns完全落在窗口以内。所以瓶颈从来不是ADC的转换速度而是数据回传通道的带宽。2. 两种驱动方案的设计思路与原理2.1 方案ASPI串行读取最常用但也最受限SPI方案之所以普及是因为几乎所有MCU都带SPI外设引脚少、接线简单。AD7606进入串行模式后将SER/PAR引脚拉高数据就从DOUTA引脚串行移出连接SCLK和MISO即可CS由普通GPIO控制。很多人默认SPI传输不会影响采样率但在AD7606这种8通道同步采样场景里SPI的串行本质成了硬伤。一次采样周期要移出128个bit假设SCLK为25MHz仅传输时间就是128 / 25MHz 5.12us再加上4us转换时间理论周期9.12us约合109kSPS。如果SCLK只有10MHz传输时间变成12.8us理论采样率直接跌到59kSPS。何况实际代码里还有中断进出、DMA配置、轮询等待的开销实测值会比理论值更低。当然SPI方案也不是没有优点。它的接线只有四五根驱动代码简单排查问题方便而且采样率要是只需要80kSPS以下SPI完全能胜任。2.2 方案BFSMCFMC并行映射把数据读取变成内存读FSMC全称是Flexible Static Memory Controller在STM32H7上官方叫FMC但大部分工程师仍习惯叫FSMC。它本身是给NOR Flash、SRAM、PSRAM这类并行存储器设计的控制器核心能力是把外部设备映射到MCU的寻址空间里CPU往某个地址读写FSMC硬件会自动产生对应的片选、读、写时序信号。AD7606的并行接口刚好可以伪装成一块16位宽的SRAMD0~D15接数据总线CS接片选RD接读使能BUSY接普通GPIO。这样一来CPU读取AD7606某个通道的数据实际上就是执行一条对映射地址的16位读指令。FSMC硬件会在一个总线周期内自动完成地址建立、片选拉低、读脉冲、数据锁存、总线释放不需要软件模拟任何时序。数据读取速度的提升是代差级别的。假设FMC外设时钟为200MHzSTM32H7典型配置每个总线周期约5ns配置得当的情况下一次16位读访问约30~50ns8通道统统拿完也不过300ns左右。相比SPI的微秒级传输时间这部分开销几乎可以忽略。正因如此AD7606在FSMC方案里可以跑到标称的200kSPS上限。2.3 两种方案的对比逻辑用一张表快速总结两种方案在AD7606场景下的差异对比项SPI串行方案FSMC并行方案数据线数量3~4根SCLK、MISO、CS、BUSY20根左右D0~D15、NOE、NE、BUSY、CONVST等读取8通道耗时128个SCLK约5.12us25MHz约0.3usFMC 200MHz理论最高采样率约109kSPS25MHz SCLK受AD7606限制约200kSPSCPU开销轮询较高DMA可优化等效内存读开销低引脚占用少多驱动代码量简单中需配FMC时序这样看就很清楚了如果你需要高采样率FSMC是必然选择如果引脚紧张且采样率要求不高SPI更现实。3. 硬件连接与CubeMX配置要点3.1 FSMC方案的引脚规划与连接清单下面以STM32H743/H750配合常见AD7606模块为例给出信号级连接。不同封装的具体引脚号请以自己板子的原理图和数据手册为准但信号对应关系是一致的。AD7606信号STM32H7 FMC信号说明DB0~DB15FMC D0~D1516位并行数据总线CSFMC NE1Bank1片选映射区域起始地址0x60000000RDFMC NOE读使能对应AD7606的RD低脉冲BUSY任意GPIO建议带EXTI转换完成信号下降沿表示可读数RESET任意GPIO芯片复位CONVST A/B任意GPIO或PWM启动转换上升沿有效RANGEGPIO或固定电平选择±5V或±10V量程OS0~OS2固定低电平关闭过采样保证最高采样率PAR/SER固定低电平并行模式有个很多人忽略的细节FMC的地址线A0~A2在FSMC方案里其实可以不用接。AD7606没有地址线它是通过RD脉冲来推进内部通道指针的每次RD下降沿自动切换到下一通道。因此连续对映射区域读8次就会依次得到通道1到通道8的数据地址线接不接都不影响通道顺序。3.2 CubeMX中FMC参数设置与计算在CubeMX里配置STM32H7的FMC时有些新手会卡在时序参数上。我的做法是直接把FMC的NOR/SRAM Controller打开选择Bank1的NE1、16位数据宽度、Memory Type选SRAM然后在时序配置里给出一组安全起点AddressSetupTime 1AddressHoldTime 1DataSetupTime 6BusTurnAroundDuration 1这些参数的单位是FMC外设时钟周期。H7主频400MHz时FMC外设时钟一般配置为200MHz一个周期5ns。按DataSetupTime6计算NOE低电平持续时间约30ns满足AD7606手册要求的约20ns最小读脉冲宽度留有余量但不拖沓。8通道读8次总读取时间约 (161) * 5ns * 8 320ns完全落在1us读取窗口之内。调试时建议用示波器抓NOE引脚确认低电平宽度是否符合预期。如果数据读出来偶尔错位或全零优先把DataSetupTime往上加如果对采样周期很敏感再逐步往下压。3.3 SPI方案的CubeMX配置要点SPI方案配置很简单选一个SPI外设主模式时钟极性CPOL0、时钟相位CPHA1对应AD7606手册里的串行时序空闲时SCLK为低数据在SCLK下降沿切换、上升沿稳定采样数据帧宽度16位MSB先行速率按25MHz左右配置。CS用普通GPIO控制BUSY接GPIO或EXTI。需要注意区分SPI16位帧和8通道数据之间没有直接映射关系。每次CS拉低后连续接收8个16位帧这8帧才依次对应通道1到通道8。这跟并行的连续读8次逻辑是类似的只不过SPI是一根线串行吐出来。4. 驱动代码实现FSMC与SPI对比4.1 FSMC方案查询式读取CubeMX配置好FMC之后驱动代码的核心其实非常短。下面是我在实际项目里用的一段简化逻辑#define AD7606_BASE 0x60000000UL volatile uint16_t *ad7606 (volatile uint16_t *)AD7606_BASE; // 启动一次转换CONVST先低后高上升沿触发 void AD7606_StartConv(void) { HAL_GPIO_WritePin(CONVST_GPIO_Port, CONVST_Pin, GPIO_PIN_RESET); delay_ns(100); HAL_GPIO_WritePin(CONVST_GPIO_Port, CONVST_Pin, GPIO_PIN_SET); } // 等待转换完成读取8通道数据 void AD7606_ReadAllChannels(uint16_t *buf) { // BUSY高电平期间表示转换进行中等待低电平 while (HAL_GPIO_ReadPin(BUSY_GPIO_Port, BUSY_Pin) GPIO_PIN_SET) ; // 连续读8次每次触发一次FMC总线读周期 for (int i 0; i 8; i) { buf[i] ad7606[i]; } }两个关键点。第一ad7606[i]虽然地址在递增但AD7606并不关心地址线它只是把每次FMC读产生的RD脉冲当作通道推进信号。第二读取必须放在BUSY拉低之后转换过程中读数据拿到的是无效电平。实测时这段代码在200kSPS触发频率下完全能稳定跑没有丢数据。4.2 FSMC方案进阶利用DMA减轻CPU负担如果不想让CPU在每次转换完成后都去执行8次读操作可以把FMC的内存映射地址直接作为DMA源地址让DMA自动搬8个半字16字节进内存缓冲区。核心操作类似__attribute__((section(.RAM_D1))) uint16_t adcBuf[8]; HAL_DMA_Start_IT(hdma_fmc, (uint32_t)AD7606_BASE, (uint32_t)adcBuf, 8);这里的hdma_fmc需要在CubeMX里把DMA请求源连接到FMC。当BUSY下降沿触发外部中断时在中断服务函数里调一次上面的DMA启动即可。完成中断里做数据处理。STM32H7还可以进一步利用DMAMUX的双缓冲特性让DMA在装满一块缓冲区后自动切换另一块配合BUSY中断完成“转换-搬运-处理”流水线。这个配置在H7系列上比较常用具体实现时注意缓冲区必须放在DMA能访问的RAM区域也就是D1域或D2域别放到默认的DTCM里去踩坑。4.3 SPI方案实现HAL库DMASPI方案的代码也不复杂但性能差距在逻辑设计阶段就已经注定了。轮询版本void AD7606_SPI_ReadAllChannel(uint16_t *buf) { // 等待转换完成 while (HAL_GPIO_ReadPin(BUSY_GPIO_Port, BUSY_Pin) GPIO_PIN_SET) ; HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET); // SPI配置为16位帧size8表示连续接收8个半字 HAL_SPI_Receive(hspi1, (uint8_t *)buf, 8, HAL_MAX_DELAY); HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET); }如果编译环境支持也可以把SPI配置为RXONLY模式让SPI在接收时自动产生SCLK时钟不需要额外的Dummy发送效率会稍高一点。SPIDMA版本只是在初始化里把HAL_SPI_Receive_DMA挂上同时处理好CS的拉低和拉高。真正限制采样率的不是DMA有没有用而是128个SCLK本身需要的时间所以就算DMA把CPU释放了物理上的传输时间仍跑不掉。4.4 采样触发方式定时器PWM更精确还有一个值得讲的优化启动转换不要用软件翻转GPIO而是用定时器的PWM输出直接驱动CONVST引脚。比如用定时器输出一个50%占空比的方波频率就是采样率。PWM的上升沿触发AD7606开始转换硬件自动完成不占CPU也不会因为中断延迟导致采样间隔抖动。我用定时器输出200kHz PWMFMC方案在这个频率下表现稳定同样的PWM频率SPI方案因为一帧传输就要5us再加上转换4us已经完全来不及读回来的数据会出现明显的乱码或错位这正好说明为什么SPI无法跑满速。5. 实测对比数据、采样率、CPU占用5.1 测试环境测试现场的条件如下MCUSTM32H750VBT6主频400MHzFMC外设时钟200MHzADC市售AD7606模块RANGE设为±5V信号源函数发生器输出1kHz正弦波同时接到8个通道上位机通过串口将原始码值发送到PC用Python解析并绘制波形触发方式定时器PWM分别配置为100kSPS、200kSPS两种频率为了统计实际采样率我在BUSY引脚上接了一个逻辑分析仪测量两次采样完成之间的时间间隔。5.2 采样率实测结果方案配置理论极限实测平均采样率CPU开销评价SPI轮询SCLK10MHz约59kSPS约52kSPS高CPU大部分时间在等SPISPIDMASCLK25MHz约109kSPS约95kSPS中DMA释放了部分CPUFMC查询式约200kSPS约196kSPS低每次读8个半字仅几十周期FMCDMA约200kSPS约198kSPS极低CPU只响应BUSY中断和DMA完成中断这组数据能说明两件事第一SPI方案在25MHz SCLK下确实只能逼近100kSPS距离200kSPS差一倍第二FSMC方案的实测结果非常接近AD7606的标称上限说明瓶颈已经是芯片本身。5.3 波形还原与数据精度在1kHz正弦波输入下两种方案还原出来的波形肉眼几乎看不出差别。把数据切到20kHz正弦波用SPI方案采集到约95kSPS时波形每个周期只有4~5个采样点看起来就是锯齿状FSMC方案以200kSPS采同样的信号每个周期有10个采样点波形还原度明显更好。数据精度方面我分别用两种方案连续采集1秒统计每通道码值的方差。结果FSMC方案的噪声底略好于SPI方案这主要是读取完成后数据在总线上保持时间更短受干扰概率更小。实际上两者都符合AD7606在16位下的典型表现但FSMC方案在反复连续采集时数据一致性更稳定。5.4 CPU占用对比的直观感受用SPI轮询时CPU几乎被卡死在读取函数里主循环里的其他任务都会受影响。SPIDMA好一些但每5us左右一次的中断频率还是不低。到了FSMC方案200kSPS下每次读取8个16位数据也就是几十个周期的开销CPU占用极低这为后续在同样的MCU上跑控制算法或频谱分析留出了充足余量。6. 常见问题与排查技巧实录6.1 FSMC读回来的数据全是0或0xFFFF这个坑我遇到不止一次原因集中在几个方向芯片处于复位状态或RESET引脚被拉低检查RESET和上电时序。FMC时序过短尤其是DataSetupTime太小导致RD脉冲宽度不满足AD7606最小读写时间。把DataSetupTime往上加实测从6加到8基本就能解决。数据总线接线错误检查D0~D15是否一一对应这里最容易出现跨越排线时的错位。PAR/SER引脚没有正确拉低芯片仍处于串行模式并行总线不输出有效数据。排查建议是先用示波器抓NOE和NE1信号确认FMC确实在访问映射地址时产生了预期的脉冲。6.2 SPI数据错位或通道顺序对不上如果SPI读回来的数据有值但通道顺序错乱或者偶发地某几个通道数据跳变先检查CS拉低后到第一个SCLK上升沿之间是否有足够的建立时间。AD7606在CS有效后需要一点时间把第一个通道的数据放到输出线上如果SPI时钟太快第一个bit会被吃掉。我的做法是CS拉低后加一个短暂延时或者把SPI的时钟极性和相位重新核对一遍。CPOL0、CPHA1是多数模块默认能跑通的组合但如果你的板子和我的不一样以数据手册的时序图为准。6.3 采样率上不去或周期不稳定这个问题的根源往往是触发方式。如果用软件翻转GPIO来启动转换中断响应时间会带来几微秒的抖动采样率高了之后波形会明显变形。解决办法就是用定时器PWM硬件触发CONVST把采样周期稳定性交给硬件保证。另一个容易踩的点是读取阶段必须严格遵守“BUSY下降沿之后、下一次CONVST之前”读完。在SPI方案里如果采样率配置得过高很可能上次数据还没传完下一次转换已经触发读出来的结果自然乱套。SPI方案的安全工作区间建议控制在90kSPS以下。6.4 数据整体偏移或噪声偏大排除接线问题后优先检查模拟输入端的参考地和电源去耦。AD7606虽然集成度很高但AGND和DGND的布局、REF引脚的电容、电源去耦电容离芯片远近都会影响实际噪声。工业现场应用最好在模块输入端加RC滤波特别是长线传输过来的信号。如果只追求极致的16位精度建议给AD7606的供电使用低噪声LDO避免开关电源直接供电造成的纹波耦合。6.5 # FSMC与DMA搬运时的地址陷阱使用FMCDMA时有个容易踩的细节DMA的源地址如果不是连续的会直接影响搬运结果。AD7606这里虽然看起来是连续读同一个映射区域但每次读操作本身会触发芯片内部地址指针自动加一所以DMA按内存地址递增连续读8次恰好对应8个通道这个逻辑是成立的。不过要注意DMA缓冲区必须放在DMA可访问的RAM区域。STM32H7的DMA默认访问不了DTCM直接把数组定义在默认内存段很可能导致DMA传输无响应需要把缓冲区显式放到.RAM_D1段。7. 选型建议与经验总结回到实际项目里SPI和FSMC并不是非得二选一的关系而是取决于系统需求。如果你的系统采样率不超过80kSPS引脚又特别紧张比如还需要同时挂LCD、SD卡、SDRAM等外设SPI方案完全够用开发调试成本也低。如果你要榨干AD7606的性能或者后续有做频谱分析、电力谐波分析这类需要200kSPS满速运行的项目FSMC并行方案是目前最合理的做法。它虽然占用引脚多但换来的是读取速度提升一个数量级、CPU开销大幅下降代码也简洁直观。我个人的建议是新项目如果主控选STM32H7且AD7606是主角直接上FSMC方案。前期接线麻烦一点、CubeMX时序多调几次但后期做功能扩展时省下的CPU资源和时间成本远超当时投入。这次测试也让我有个体会很多所谓的“芯片性能不够”最后查下来其实是接口方案或者时序配置拖了后腿。多花一点时间研究芯片手册里的并行接口时序比在代码层面反复优化SPI轮询逻辑要有效得多。
返回列表