1. 项目背景与核心价值
ADC128S102这颗八通道12位ADC芯片在工业控制、医疗设备和测试测量领域应用广泛。去年我在设计一款多通道温度监控系统时,发现市面上的ADC模块要么采样率不够,要么通道数不足,最终决定用FPGA直接驱动这颗TI的经典ADC芯片。这种方案最大的优势在于可以完全自定义采样时序,实现精确的多通道轮询采集。
相比常见的MCU驱动方案,FPGA实现具有三个明显优势:首先,FPGA的并行特性可以完美匹配ADC的多通道切换需求;其次,硬件描述语言的时序控制精度远高于软件轮询;最重要的是,FPGA能够实现真正的同步采样——这对需要保持严格相位关系的多通道信号采集至关重要。
2. 硬件设计要点解析
2.1 接口电路设计
ADC128S102采用标准的SPI接口,但有几个特殊设计需要注意。我在第一版电路上踩过坑:芯片的CS引脚(片选信号)要求下降沿后至少等待6ns才能开始时钟,这个参数在数据手册第8页的时序图里特别标注了。我的解决方案是在FPGA代码里插入两个时钟周期的延迟(使用20MHz时钟时正好10ns)。
电源设计也有讲究:模拟电源AVDD和数字电源DVDD虽然标称都是3.3V,但必须使用独立的LDO供电。实测发现共用电源会导致LSB位出现周期性波动,信噪比下降约3dB。推荐使用TPS7A4901给模拟部分供电,它的噪声密度只有4.7μVrms/√Hz。
2.2 PCB布局技巧
- 去耦电容要尽可能靠近芯片引脚:我在AVDD和DVDD引脚旁各放了1个10μF钽电容+1个100nF陶瓷电容的组合
- 模拟输入走线要等长:8个通道的走线长度差异控制在±5mm以内
- 地平面分割策略:采用"模拟地-数字地单点连接"方案,接地点选在ADC下方过孔
- SPI时钟线要做阻抗匹配:在FPGA端串接33Ω电阻消除反射
3. FPGA逻辑设计详解
3.1 状态机设计
核心是一个五状态的状态机,状态转换图如下:
code复制IDLE -> CONFIG -> ACQUIRE -> CONVERT -> READOUT
特别要注意的是CONFIG状态的处理。ADC128S102每次转换前都需要先发送配置字(包含通道选择和控制位),但很多开发者会忽略配置字的CRC校验问题。我在代码里加入了CRC-4校验生成逻辑,这样可以确保配置命令传输的可靠性。
3.2 时序控制关键参数
verilog复制// 重要时序参数(单位:ns)
parameter t_CSS = 6; // CS下降沿到SCLK有效时间
parameter t_SU = 15; // DIN建立时间
parameter t_HD = 5; // DIN保持时间
parameter t_DV = 20; // SCLK下降沿到DOUT有效
实际编写代码时,我采用"时钟周期计数法"来满足这些时序要求。例如处理t_CSS时:
verilog复制always @(posedge clk) begin
if(state == IDLE && start_conv) begin
cs_n <= 1'b0;
delay_cnt <= 2'd1; // 20MHz时钟下2周期=10ns
end
else if(delay_cnt > 0) begin
delay_cnt <= delay_cnt - 1;
end
else begin
sclk_en <= 1'b1; // 延迟结束后启动时钟
end
end
3.3 数据对齐技巧
由于ADC输出是16位数据(包含4位前导0+12位有效数据),需要特别注意数据对齐。我的做法是在READOUT状态时,用移位寄存器捕获数据:
verilog复制always @(negedge sclk) begin
if(state == READOUT) begin
shift_reg <= {shift_reg[14:0], dout};
if(bit_cnt == 15) begin
adc_data[curr_ch] <= shift_reg[11:0]; // 提取有效12位
end
end
end
4. 校准与性能优化
4.1 增益误差校准
即使使用外部基准电压源,各通道间仍可能存在约±1LSB的增益差异。我采用的校准方法是:
- 给所有通道输入相同的精确电压(建议用2.5V基准)
- 记录各通道输出码值
- 计算校准系数:CalCoeff = 理想码值/实测码值
- 在FPGA内实现乘法校正:Data_cal = Data_raw × CalCoeff
4.2 噪声抑制方案
实测发现当所有通道连续工作时,电源噪声会导致有效分辨率降至10.5位。通过以下措施改善:
- 在FPGA代码中加入伪随机间隔采样(间隔时间在±5%范围内抖动)
- 配置ADC内部滤波器为"50Hz抑制"模式
- 对每个通道连续采样8次做滑动平均
这些措施使得在100ksps采样率下,ENOB(有效位数)达到11.7位。
5. 实测问题排查记录
5.1 通道串扰问题
现象:当相邻通道输入信号幅度差异较大时,小信号通道读数被干扰
排查过程:
- 检查PCB发现模拟输入走线间距不足(仅0.2mm)
- 改用交叉走线布局后有所改善
- 最终解决方案:在配置字中启用内部缓冲器(CONFIG[2]=1)
5.2 时钟抖动问题
现象:高精度基准源下仍出现±2LSB波动
解决方法:
- 改用FPGA的专用时钟输出引脚驱动SCLK
- 在时钟线上增加π型滤波器(22Ω+100nF+22Ω)
- 将SPI时钟频率从20MHz降至10MHz
6. 扩展应用方案
基于这个基础设计,还可以实现更多高级功能:
- 自动量程切换:通过监测输入幅度动态调整配置字中的增益位
- 同步触发采集:利用FPGA的全局时钟网络实现多片ADC同步采样
- 数字滤波直通:在FPGA内集成移动平均、FIR等滤波器
我在当前项目中加入了温度补偿功能:通过读取ADC内部温度传感器(通道7),实时校正其他通道的增益误差。具体做法是建立温度-误差查找表,在FPGA内用Block RAM实现。