☰
FPGA通过SPI配置ADC的完整指南:从时序到Verilog实现
2026/10/15 8:14:15 网站建设 项目流程

简介:FPGA通过SPI配置ADC系列文章整理成一份Word文档,面向数字IC/FPGA工程师及嵌入式学习者,解决SPI接口配置ADC时时序不清、模式混淆的常见问题。文档从SPI总线基本原理讲起,对比4线与3线模式,并以TI ADS52J90为例逐步拆解读写时序、寄存器地址/数据格式以及tSCLK、tSEN_SU等关键参数,由浅入深,适合入门到进阶。资源压缩包共1个文件,类型为docx,大小787KB。已有1870人学习下载。内容涵盖SPI概念、4线/3线配置、ADC写操作和读操作时序分析等,还对TI与ADI的不同命名做了对照,强调实际操作中的时序裕量设置,可直接作为FPGA开发中ADC配置模块的设计参考。

1. FPGA给ADC上电后不出数据:SPI配置才是真正的开机动作

某采集卡项目里,FPGA连着一颗16位ADC,上电后数据总线一直是低,时钟给了、电源纹波正常、参考电压也没问题,换了三版代码依然全零。最后把SPI总线抓进逻辑分析仪,才发现寄存器写入根本没有完成。类似的问题我见过不止一次:硬件连线查到头发现全是对的,真正坏事的反而是那条看起来不起眼的配置链路。ADC的通道开关、增益、参考电压、采样率和内部滤波器,几乎全都收在寄存器里,FPGA要做的第一件事不是收数据,而是先把这些寄存器配置到位。这篇笔记按 FPGA 通过 SPI 配置 ADC 这条主线,把协议时序、寄存器映射、Verilog 控制器实现、上电排错和可复用设计一次讲透,新手能照着落地,熟手能直接拿去查坑。

2. 为什么用SPI配ADC:时序参数、引脚分工和选型前必确认的四件事

2.1 配置通道和数据通道分开是关键判断

ADC 的引脚看起来多,实际上按职能分只有四类:模拟输入、电源与参考、数据输出、配置控制。数据输出负责把转换结果送出去,通常是并行总线、双沿 DDR 或者高速串行差分对;配置控制则负责设置 ADC 的工作状态,最常见的就是一根 SPI 接口。

这两条通道在带宽上的差异非常明显。数据通道要求高吞吐,所以走并行或者高速串行;配置通道只在上电初始化、切换量程、切换通道的时候用一下,数据量小,对速率不敏感。所以 ADC 厂商普遍选择 SPI 来做配置口,因为它引脚少,一颗 ADC 只需要 SCLK、CS、SDI/SDO 三四根线,还能通过菊花链把多颗 ADC 串在同一条总线上,PC 上也不占 GPIO。

这里要特别提醒:不要把"配置通过 SPI"理解成"数据也从 SPI 出"。有些 ADC 是三线制,数据输出和配置共用同一个串行口,工作时序复杂得多;大多数据采集场景用的是独立配置口,数据口和配置口各走各的。设计之前先翻开数据手册确认这两件事:配置口是标准 SPI 还是自定义三线,数据口和配置口是否复用管脚。复用意味着你写完配置之后还要把引脚方向切回数据模式,这一条踩坑的概率极高,后面章节会专门展开。

2.2 CPOL/CPHA:先定时钟极性再写代码

SPI 有四种工作模式,区别在于时钟空闲电平(CPOL)和数据采样沿(CPHA)。ADC 的数据手册一般会给出时序图,但很多开发者习惯性套用"模式 0",结果配置写不进去,还以为是状态机写错了。实际上判断模式并不复杂,看时序图只看两个点:SCLK 空闲的时候是高还是低;数据在 SCLK 的哪个沿发生变化。

举个例子。CPOL=0 时 SCLK 空闲为低,CPOL=1 时 SCLK 空闲为高。CPHA=0 表示数据在第一个沿被采样,CPHA=1 表示数据在第二个沿被采样。四选一的组合就是标准 SPI 的 mode 0 到 mode 3。对于 FPGA 主控来说,这四种模式都做得了,只要把发送端和接收端的采样沿选对,没有哪个模式"天生更好"。

我一般会这样做:打开数据手册的 SPI 时序图,先找 CS 拉低后 SCLK 的第一个跳变,再看数据线 SDI 上第一位有效数据是在跳变之前还是之后稳定。数据在跳变之前稳定,说明从机在当前沿采样,主控也要在当前沿发送数据;数据在跳变之后才切换,说明主控应该在前一个沿发送、在当前沿采样。把这组关系写进 RTL 的注释里,比背四种模式的表格更不容易错。

模式CPOLCPHA典型特征常见使用场景
mode 000空闲低,第一个沿采样大多数单通道ADC配置口
mode 101空闲低,第二个沿采样部分射频收发器配置口
mode 210空闲高,第一个沿采样SPI Flash等常用外设
mode 311空闲高,第二个沿采样DSP外设、部分ADC

2.3 寄存器是黑匣子:读回位才是调试入口

ADC 的配置寄存器在 FPGA 看来就是个黑匣子,你往里写数,它内部产生什么效果,外部看不到。看不到就没法在板上直接判断"配置到底生效没有",所以数据手册里"读回"功能几乎是所有可调试性的来源。

大多数 ADC 的寄存器分三类:只读的状态寄存器、可读写的配置寄存器、写触发型寄存器。配置寄存器支持读回,意味着你可以用同一根 SPI 总线把刚才写的值读出来比对,这是排障最重要的手段。如果一块 ADC 的数据手册里没有明确写"寄存器支持回读",务必在选型阶段就标记出来,后续调试成本会差一个量级。

另外要注意寄存器位段的定义。同样是"增益配置"这个位,有些芯片是 0 表示 1 倍、1 表示 2 倍,有些恰好反过来;有些芯片寄存器位宽是 8 位,有些是 16 位;有些地址从 0x00 开始,有些故意留了保留位。这些细节写代码之前必须逐位核对,宁可慢一点,也不要拿着猜测值去写,否则配置流程跑起来之后排查范围会大大扩大。

2.4 选型前要确认的四件事

如果你还在选 ADC,而不是已经拿到芯片,我建议在原理图定稿前确认四件事,全部确认完再开始写配置控制器。

第一,配置帧格式。确认地址位宽、数据位宽、是否带读/写标志位。有的 ADC 用 8 位地址加 8 位数据,有的用 16 位地址加 16 位数据,还有的用指令头区分读写。这个直接决定 SPI 帧的 bit 数。第二,最高 SCLK 频率。配置口虽然是低速口,但不同 ADC 上限差异很大,从几 MHz 到几十 MHz 都有,FPGA 侧分频参数要按它来定。第三,是否支持回读和菊花链。回读是调试命脉,菊花链决定了多片 ADC 能不能共享一条总线。第四,复位与忙信号。有些 ADC 必须由 FPGA 控制硬件复位脚的释放时序,有些只靠 SPI 写软复位;有些 ADC 配置期间要求数据输出保持高阻,这些引脚要提前留出来。

这四件事确认完,SPI 控制器的位宽、时钟频率、状态机流程才能定下来。顺序反了的话,经常会出现原理图已经投版,发现配置管脚不够用、或者 FPGA 普通 IO 驱动能力不足,后期只能飞线,非常被动。

3. 写一个SPI配置控制器:可综合的Verilog状态机与最小实现

3.1 整体结构:指令下发、移位器和片选时序

SPI 配置控制器本质上是一个串行发送接收机。FPGA 主控按位把地址和数据的二进制值送到 SDI 上,同时从 SDO 上采回数据。整体结构我一般分成三层:上层是配置调度逻辑,负责把一条条寄存器配置项按顺序下发;中间是 SPI 主控状态机,负责产生 CS 和 SCLK 时序、控制移位过程;下层是时钟分频和引脚三态控制。

上层配置调度在中小型项目里可以用一个状态机顺序执行,也可以用类 CPU 的方式管理一个配置数组。配置数组的好处是换芯片或改配置时只改内容,不用改时序逻辑,后面第 4 章会给出具体组织方式。这一章的 SPI 主控状态机部分,是整条链路最核心、也是复用价值最高的代码。

状态机我习惯用五个状态:IDLE 空闲等待指令、LOAD 装载发送数据并拉低 CS、SHIFT 按位移位发送并接收、DONE 拉高 CS 结束一帧、WAIT 帧间隔等待。WAIT 状态很多人会省掉,但不少 ADC 明确要求相邻两次 CS 有效之间要有最小间隔,没有这个状态,连续配置时很容易触发芯片的时序违例。

3.2 核心代码:读写状态机

下面这段代码是一个参数化的 SPI 主控,支持写操作和读操作,CPOL/CPHA、分频系数、帧位宽全部通过参数配置。为了便于理解,代码只保留核心逻辑,主要用于配置类 ADC,数据位宽按 32 位举例,实际使用时根据芯片寄存器帧格式修改参数即可。

module spi_adc_ctrl #( parameter CLK_DIV = 32, // sclk = clk / (2 * CLK_DIV) parameter FRAME_BITS = 32, // 完整SPI帧位宽:地址+数据+读写标志 parameter CPOL = 0, // 时钟空闲电平 parameter CPHA = 0 // 采样沿选择 )( input wire clk, input wire rst_n, input wire start, // 启动一次SPI事务 input wire read_req, // 1=读寄存器,0=写寄存器 input wire [FRAME_BITS-1:0] tx_data, // 待发送帧 output reg [FRAME_BITS-1:0] rx_data, // 接收到的帧 output reg busy, // 忙标志 output reg sclk, output reg cs_n, output reg sdi, input wire sdo ); localparam IDLE = 3'd0, LOAD = 3'd1, SHIFT = 3'd2, DONE = 3'd3, WAIT = 3'd4; reg [2:0] state, next_state; reg [7:0] clk_cnt; // 分频计数器 reg [5:0] bit_cnt; // 位计数器,最大支持64位帧 reg [FRAME_BITS-1:0] shift_reg; wire sclk_en = (state == SHIFT); wire sclk_i = CPOL ? ~clk_en_toggle : clk_en_toggle; // 简单的时钟使能生成:在SHIFT状态每隔CLK_DIV产生一个sclk翻转 reg clk_en_toggle; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin clk_cnt <= 8'd0; clk_en_toggle <= 1'b0; end else if (sclk_en) begin if (clk_cnt == CLK_DIV - 1) begin clk_cnt <= 8'd0; clk_en_toggle <= ~clk_en_toggle; end else begin clk_cnt <= clk_cnt + 1; end end else begin clk_cnt <= 8'd0; clk_en_toggle <= 1'b0; end end // 三态与输出控制 assign sclk = sclk_en ? (CPOL ? ~clk_en_toggle : clk_en_toggle) : CPOL; // 状态机主逻辑 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin state <= IDLE; cs_n <= 1'b1; sdi <= 1'b0; bit_cnt <= 6'd0; shift_reg <= {FRAME_BITS{1'b0}}; busy <= 1'b0; end else begin case (state) IDLE: begin cs_n <= 1'b1; busy <= 1'b0; if (start) begin state <= LOAD; busy <= 1'b1; end end LOAD: begin cs_n <= 1'b0; // 拉低片选,启动事务 shift_reg <= tx_data; bit_cnt <= 6'd0; state <= SHIFT; end SHIFT: begin if (clk_en_toggle == 1'b1) begin // 在sclk沿附近移位 if (CPHA == 1'b0) begin sdi <= shift_reg[FRAME_BITS-1]; // 第一个沿发送最高位 shift_reg <= {shift_reg[FRAME_BITS-2:0], sdo}; // 同时采样 end else begin // CPHA=1时数据在第二个沿采样,此处简化处理 sdi <= shift_reg[FRAME_BITS-1]; end if (bit_cnt == FRAME_BITS - 1) begin bit_cnt <= 6'd0; state <= DONE; end else begin bit_cnt <= bit_cnt + 1; end end end DONE: begin cs_n <= 1'b1; // 拉高片选,结束事务 rx_data <= shift_reg; state <= WAIT; end WAIT: begin // 帧间隔,至少等待若干主时钟周期 if (clk_cnt >= 8'd8) begin // 可调整的帧间隔长度 state <= IDLE; end end default: state <= IDLE; endcase end end endmodule

这段代码的逻辑并不复杂,但有几个细节值得说明。LOAD 状态只做一件事:拉低 CS 并装载发送数据,不立即移位,保证从机看到 CS 有效之后有足够时间准备接收。SHIFT 状态在每个 SCLK 翻转沿把最高位移出去,同时把 SDO 采到的数据从低位往高位移进来,这样一帧结束后移位寄存器里自然就是接收到的完整数据。DONE 状态把 CS 拉高,确保一帧完整结束之后才释放总线。

参数方面,CLK_DIV 直接决定 SCLK 频率,计算公式是 sclk = clk / (2 × CLK_DIV)。比如主时钟 100MHz,CLK_DIV 取 32,SCLK 大约是 1.5625MHz,对绝大多数 ADC 配置口都足够。FRAME_BITS 要与芯片帧格式一致,常见 16、24、32。CPOL/CPHA 前面已经说过,按数据手册时序图设置。busy 信号用于上层调度,上层每发一条配置指令前先等 busy 拉低再发下一条,这个握手必须做,否则状态机内部还在忙着,新指令已经把寄存器覆盖了。

3.3 参数怎么定:分频系数和帧间隔的经验值

分频系数不是越大越好,也不是越小越好。SCLK 太高,如果 PCB 走线长、连接器接触不良,上升沿变缓,从机采样到的数据就可能出错;SCLK 太低,配置几百个寄存器时会明显拖慢启动时间。一般配置口建议控制在 1MHz 到 10MHz 之间,初次调板取低一点,比如 1MHz,验证通过后再慢慢提频率。

帧间隔 WAIT 状态是最容易被低估的参数。很多 ADC 的数据手册里有一行小字:CS 高电平最小脉宽、CS 到 SCLK 最小建立时间。这个时间通常在几十纳秒到几百纳秒之间。如果你用主时钟 100MHz,一个周期才 10ns,必须专门等几拍才能满足。上面的代码里 WAIT 状态直接复用 clk_cnt,等待长度取 8 个主时钟周期,实际项目里应该根据芯片手册要求换算成主时钟周期数,宁可多等不要少等。

还有两个引脚级的问题要在写 RTL 之前想清楚。一是 SDI 和 SDO 是否在芯片上是同一个引脚,也就是三线制。如果是,FPGA 侧必须用三态门控制,读的时候把 SDI 置为高阻,写的时候输出数据;这个切换时机一旦错了,读回的数据要么全是高电平,要么把写数据线上的电平采进去。二是 CS 是否支持多片选择,如果同一根 SCLK 上挂着多颗 ADC,每颗的 CS 必须独立,状态机里要扩展出一个片选译码层。

4. 配置项从上电到生效:寄存器位段、写序列和回读校验

4.1 从数据手册抓五类必配位

拿到一颗新的 ADC,最忌讳的是照着示例代码整段移植。不同芯片的寄存器地址定义差异极大,但寄存器内容按功能划分,基本逃不出五类。把这五类配置位在手册里逐个找到,配置表就完成了大半。

配置类别典型位段不配置时的后果备注
全局使能EN、START、POWER_DOWN芯片不转换或一直处于关断写在配置序列最前面
通道控制CH_EN、通道选择、扫描模式只有默认通道出数多通道ADC必须逐通道核对
模拟前端PGA增益、VREF选择、单端/差分满量程判断错误直接决定采集到的电压是否可信
数据格式补码/偏移二进制、位序软件里算出的值符号全反与FPGA解析逻辑必须一致
采样与滤波采样率分频、内部滤波器输出速率不对或噪声偏大某些芯片滤波系数也在寄存器里

全局使能位通常是第一位要写的,因为有些芯片在未使能状态下,后面的寄存器写入会被忽略。通道控制位决定当前有没有数据,多通道芯片尤其要注意扫描顺序和通道使能两个位段是分开的,只配了通道使能但没配扫描顺序,数据可能只在第一个通道上重复输出。模拟前端配置位最影响采集正确性,增益和参考电压一旦配错,后续所有数据都建立在错误的满量程上,而且很难通过看波形发现。数据格式位影响的是二进制解释方式,偏移二进制和二进制补码只差最高位取反,但会让软件里算出来的电压差出半个量程。采样与滤波位一般排在最后,因为它依赖前面几项已经稳定。

4.2 上电顺序:先复位还是先配时钟

ADC 的上电配置顺序,直接抄参考设计不一定对,但有一条通用链路可以套用。这条链路我在多个项目里验证过,覆盖了大多数 SPI 配置型 ADC。

第一步,等待电源稳定。ADC 的数字电源和模拟电源上升时间可能不同步,数据手册一般会给一个最小上电延时,比如 10ms 到 100ms,FPGA 上电后先延时再碰 ADC。第二步,释放硬件复位。如果芯片有 RESET 脚,FPGA 控制它从有效电平释放到无效电平;如果没有,跳过这一步。第三步,通过 SPI 写软复位命令。很多 ADC 提供一个特殊指令头或者一个软复位寄存器,写进去之后芯片内部逻辑回到默认状态。第四步,按寄存器地址从低到高写配置。这期间芯片的数据输出通常还没使能,不用管数据口。第五步,写全局使能位,打开转换。第六步,做一次寄存器读回校验,确认关键配置位已经生效。

有一个常见争议:先配时钟还是先配复位?我的做法是先复位后配时钟。理由是很多 ADC 的采样时钟来自外部晶振或 FPGA 供给,芯片复位期间时钟即使没停也不会造成错误,但先给时钟后复位的话,复位释放瞬间时钟沿可能正好落在配置帧中间,产生首次采样错位。当然,如果数据手册明确要求时钟先稳定,那就以手册为准。

4.3 配置表组织方式和读回校验

配置表不要散落在状态机里,也不要写成几十个 if 分支,我一般用一个参数数组来组织。这样可以做到改配置不改逻辑,换芯片型号时只改数组内容。下面是一个 SystemVerilog 风格的配置项定义示例,表达思路为主:

typedef struct packed { logic [7:0] addr; // 寄存器地址 logic [15:0] data; // 寄存器数据 logic readback; // 是否在写入后回读校验 } cfg_item_t; localparam int NUM_CFG = 8; const cfg_item_t CFG_TABLE [NUM_CFG] = '{ '{8'h00, 16'h8000, 1'b0}, // 软复位 '{8'h01, 16'h0001, 1'b1}, // 通道0使能,回读 '{8'h02, 16'h0010, 1'b1}, // PGA增益=2,回读 '{8'h03, 16'h0000, 1'b0}, // 数据格式:二进制补码 '{8'h04, 16'h0100, 1'b1}, // 采样率分频,回读 '{8'h05, 16'h0001, 1'b0}, // 内部滤波器使能 '{8'h06, 16'h8000, 1'b0}, // 全局使能,启动转换 '{8'h07, 16'h0000, 1'b1} // 状态寄存器,回读确认工作状态 };

配置调度逻辑只需要逐个取出 CFG_TABLE 里的项,拼成 SPI 帧,下发到第 3 章的控制器,然后等待 busy 释放。回读校验的做法也很直接:对于 readback 为 1 的项,下发读指令,把读回来的值和期望值做比对,不一致时拉高一个 error 标志,同时停止后续配置。这个 error 标志在调试时接到 LED 或逻辑分析仪上,几秒钟就能定位是哪一条配置写失败了。

参数说明方面,addr 宽度和 data 宽度必须与具体的 ADC 帧格式一致,不能照抄这里的 8 位地址和 16 位数据。readback 标志位只标记关键配置,比如增益、通道使能、全局使能,不要每一项都回读,否则配置时间会拉长一倍。期望值比对可以放在 FPGA 内部,也可以把读回值通过串口或 JTAG 送到上位机,我更推荐在 FPGA 内部做自动比对,调试效率比人工对着手册翻快得多。

5. 避坑记录:SPI配置ADC最常见的五个翻车场景

5.1 现象:SDIO 一直是高,读回的数据全部是 0xFF

配置写不进去,回读全是高电平。用逻辑分析仪看,CS 和 SCLK 时序都对,SDIO 在写阶段有数据翻转,但读阶段一直保持高。原因基本是:这颗 ADC 的配置和数据共用同一个引脚,FPGA 在写完指令后没有把 SDIO 从输出切到输入,或者切换时机晚了一拍。解决方法是把三态方向的切换逻辑理清,在 SDI 发送完最后一个数据位之后、SCLK 的最后一个采样沿之前,就要把引脚置为高阻输入;建议把方向控制信号单独引出来,和 SDI/SDO 并列观察。三态切换这种问题在仿真里极易忽略,因为 testbench 里很少建双向引脚模型,上板才露馅。

5.2 现象:寄存器写进去了,读回来的数值位顺序颠倒

写入 0x8001,读回来变成 0x8008 或者 0x0180,检查地址和数据内容都是对的,只是 bit 位置换了。这通常是位序问题。ADC 的 SPI 接口有些芯片默认 MSB first,有些允许配置成 LSB first,如果芯片上有硬件引脚或者寄存器位控制位序,而 FPGA 侧又固化了移位方向,就会出现整帧数据位序错位。解决方法是先确认手册里的时序图是从左到右还是从右到左画,再对照芯片手册里的波形数一遍 bit 顺序。这种错误用逻辑分析仪抓单帧波形就能看出来,数据口上的电平翻转形状和手册对不上,修起来很快。

5.3 现象:仿真全对,上板配置经常失败,复位后第一次必失败

仿真模型总是按理想时序工作,而真实芯片有建立保持时间要求。最常见的是 CS 拉低之后立刻给出 SCLK,没有满足芯片对 CS 建立时间的要求;或者一帧结束后 CS 拉高时间过短,芯片内部状态机还没来得及复位。解决方法是回到状态机里,在 LOAD 状态加入 CS 建立等待,在 DONE 之后加入 CS 高电平等待,按照手册时序参数换算成主时钟周期数。还有一个容易被忽略的点:芯片的 SCLK 空闲电平如果不是默认的 mode 0,仿真模型可能不检查,但真实芯片会拒收。把这些时间参数写进 RTL 注释,会比对着波形一遍遍抓效率高很多。

5.4 现象:断电再上电配置丢失,必须重新初始化

有些 ADC 的寄存器是 SRAM 型存储,掉电即失,只能靠每次上电重新配置。这不算芯片故障,而是设计上就要默认"每次上电都要走一遍完整配置流程"。如果固件里把初始化代码放在一次性的启动分支里,而 FP GA 的配置比特流加载完成后 ADC 已经上电一段时间,就会有一段窗口期数据全零。解决方法是把 SPI 配置初始化放在 FPGA 状态机的稳定触发条件下,并且在上电完成信号有效之后再下发第一条配置命令。另外,如果硬件上有独立复位脚,要确保复位由 FPGA 控制,不能和系统复位直接短接,否则一次复位就把复位脚拉低,ADC 会跳过配置流程进入默认状态。

5.5 现象:SCLK 频率降到很慢才成功,提高频率就出错

这是信号完整性问题,不是时序逻辑问题。配置口虽然速率低,但如果 PCB 上 SCLK 走线过长、过孔多、或者与数据线间距太近,串扰会把信号沿搞坏。SCLK 降到 1MHz 能工作,提到 10MHz 就失败,基本可以判定是 SI 问题。解决方法是先查 PCB:SCLK 和 SDI/SDO 有没有包地,有没有远端串联电阻;然后在 FPGA 侧把 SCLK 的驱动强度调低一档,或者加上下拉;如果还不行,就要在 PCB 改板时把配置总线的走线缩短。这一条属于硬件和逻辑交界的问题,逻辑上怎么查都查不出错,换到示波器上看一眼 SCLK 上升沿就明白了。

6. 进阶:把配置控制器做成参数化IP,顺手加上自动回读

这一章不写大段代码,只讲三个让这套方案真正可复用的习惯。第一个习惯是参数化。第 3 章代码里的 CLK_DIV、FRAME_BITS、CPOL、CPHA 应该全部提升为模块参数,并且把帧间隔也参数化,用 CS_GAP_CYCLES 表示。换一颗 ADC 时只需要在顶层例化处修改参数,不需要改状态机内部逻辑。我见过太多项目里 SPI 控制器写死了 8 位地址和 8 位数据,换芯片时全部重写,血泪教训。

第二个习惯是自动回读校验。第 4 章的配置表里已经带了 readback 标志,进阶做法是把它做成一个通用服务:每次写入配置后,如果该条需要回读,调度器自动插入一条读命令并把结果与期望值比对,比对失败时错误码精确到寄存器地址。把这个服务封装好之后,新板卡贴片回来,上电先跑一遍配置自检,所有回读项全部通过再接数据采集任务,而不是等采集数据不对了再回头查配置。

第三个习惯是调试输出。FPGA 内部的逻辑分析仪 IP 在调试 SPI 时序时几乎必备,抓 CS、SCLK、SDI、SDO 四个信号加一个 error 标志。触发条件设成 error 拉高,抓到的就是配置失败的那个瞬间,比盲目看波形高效得多。如果项目里没有逻辑分析仪 IP,退一步也要把每一条下发和回读的十六进制值通过串口打出来,对照手册人工核对。

我现在的习惯是:拿到一块新的 ADC,先不写任何业务逻辑,只搭一个最小系统,让它能完成上电配置和寄存器回读,全部通过之后再开始设计采集逻辑。这一步看起来慢,实际上省掉的是后面整块调试时间。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询