D223 ADC数据处理流水线:从原始采样值到工程单位的完整转换链
2026/8/14 14:41:26 网站建设 项目流程

一颗ADC芯片输出的只是数字编码,如何把它变成用户看得懂的电压值?本文从代码层面完整解析D223的ADC数据处理流水线:原始值→滑动平均→量程转换→校准插值→工程单位。


一、数据处理流水线总览

D223的ADC数据从硬件到用户显示,经过以下完整流水线[word_4][note_63]:

AD7606原始16位数据 │ ├── 256点滑动平均滤波 │ ├── 16位均值 → getAdcFilter16[] │ └── 24位累加和 → getAdcFilter24[] │ ├── 量程转换(±5V / ±10V) │ ├── 16位 → mV │ ├── 24位 → μV │ └── 电流模式 → μA │ ├── 两点线性插值校准 │ └── 消除系统误差 │ ├── 校正系数与零点偏移 │ └── 微调 │ └── 传感器单位转换 └── V, mV, A, mA, ℃, N, kg, Pa ...

二、Step 1:256点滑动平均滤波

2.1 数据结构

D223的ADC数据缓冲区[word_4]:

u16 getAdc_Buf256[8][256];// 8通道×256点滑动窗口u16 getAdcFilter16[8];// 16位滤波值u32 getAdcFilter24[8];// 24位精度提升值u16 getAdc_Buf200[8][200];// 波形显示缓存u16 getAdc_Buf1000[8][1000];// 连续数据读取缓存

2.2 滑动平均算法

每收到一次新的ADC采样,数据进入滑动窗口,计算256点累加和[word_4]:

voidmodbus_getDeviceDatas(void){for(u8 i=0;i<8;i++){// Step1: 256点滑动平均u32 sumTotal=0;for(u16 j=0;j<256;j++)sumTotal+=_uadc.getAdc_Buf256[i][j];_uadc.getAdcFilter16[i]=sumTotal/256;// 16位均值_uadc.getAdcFilter24[i]=sumTotal;// 24位累加和(不除!)}}

2.3 为什么不除以256就能得到24位?

这是整个流水线中最精妙的设计[word_4]:

  • AD7606是16位ADC,单次采样值范围:0~65535(2^16)
  • 256个采样值累加:最大 65535 × 256 = 16,776,960 ≈ 2^24
  • 累加结果不除以256,直接保留24位精度

效果

  • 16位均值:sumTotal / 256,范围0~65535,精度±1 LSB
  • 24位累加:sumTotal,范围0~16,776,960,精度提升到±1/256 LSB
  • 有效位数(ENOB)提升约4位(log2(256) = 8,实际约4位有效提升)
  • 信噪比提升约24dB

关键:24位精度不是ADC硬件直接给出的,而是通过256次过采样累加获得的。代价是采样率降低256倍——以时间换精度[word_4]。

2.4 滤波效果

256点滑动平均等效于一个低通FIR滤波器:

  • 截止频率约为采样率/512
  • 对白噪声的抑制:20×log10(√256) = 24dB
  • 对50Hz工频干扰也有一定抑制效果

三、Step 2:量程转换

3.1 ±10V量程转换

AD7606在±10V量程下的数据编码[word_4]:

ADC原始值对应电压
0x0000 (0)-10V
0x8000 (32768)0V
0xFFFF (65535)+10V

16位转换公式[word_4]:

// ±10V量程int16 adc16=(int16)_uadc.getAdcFilter16[i]-32768;// 去偏置_modbus._inputReg.adc_mV_Data16[i]=adc16/3.2768;// → mV// 3.2768 = 32768 / 10000(满量程10V = 10000mV)

24位转换公式[word_4]:

// ±10V量程int32 adc24=(int32)_uadc.getAdcFilter24[i]-8388608;// 去偏置_modbus._inputReg.adc_uV_Data24[i]=adc24/0.8388608/10;// → μV// 8388608 = 2^23(24位中位值)// 0.8388608 = 8388608 / 10000000

3.2 ±5V量程转换

±5V量程下,系数相应调整[word_4]:

// ±5V量程// 16位: 系数 = 6.5536 = 32768 / 5000// 24位: 系数 = 1.6777216 = 8388608 / 5000000

3.3 上位机端的转换

C#上位机中的24位ADC数据转换[word_3]:

// Setting.csif(_prxData.adcRange==1)// ±5V量程value=(SWAPS32(adcValue)-8388608)/83886.08/10;else// ±10V量程value=(SWAPS32(adcValue)-8388608)/167772.16/10;// 8388608 = 2^23, 24位ADC中位值

3.4 Modbus寄存器编码

D223/G511的Modbus寄存器中,24位ADC原始值用两个16位寄存器表示[word_17]:

量程0x0000000x008000000x00FFFFFF
±5V-5V0V+5V
±10V-10V0V+10V

3.5 电流信号转换

当信号类型为电流时,通过240Ω取样电阻将电流转换为电压[word_4]:

// 电流模式(4-20mA环路,240Ω取样电阻)_modbus._inputReg.adc_uA_Data16[i]=adc16/3.2768/240*1000;// → μA

转换链:ADC数字值 → mV电压 → ÷240Ω × 1000 → μA电流[word_4]。


四、Step 3:两点线性插值校准

4.1 校准公式

两点线性插值是D223校准的核心算法[word_4][word_3]:

doublecalc_adcCalibData(doubledata,doubled1,doublea1,doubled2,doublea2){return(((data-d1)*(a2-a1))/(d2-d1))+a1;}

参数说明[word_4]:

  • data:当前ADC原始数字量
  • d1, a1:校准点A的数字量和模拟量
  • d2, a2:校准点B的数字量和模拟量

4.2 校准执行流程

固件中的校准执行[word_4]:

doublegetCalibAdcDatas(u8 widthByte,u8 ch,s32 data){doubleadcFloat=0;if(校准点A使能&&校准点B使能){// 使用用户标定的两点进行线性插值adcFloat=calc_adcCalibData(data,_framDatas._adcCalibDatasPointA[ch].calibDigital,_framDatas._adcCalibDatasPointA[ch].calibAnalog,_framDatas._adcCalibDatasPointB[ch].calibDigital,_framDatas._adcCalibDatasPointB[ch].calibAnalog);adcFloat*=0.00001;// 缩放到实际工程单位}else{// 使用默认理想转换曲线(无校准)if(±10V量程)adcFloat=data*10.0/8388608.0-10.0;// 24位elseadcFloat=data*5.0/8388608.0-5.0;// 24位}returnadcFloat;}

4.3 校准参数存储

每通道独立存储两组校准数据[word_7]:

// C#上位机中的校准参数结构publicstaticInt32[]calib_adcCalib_digitalA=new Int32[8];// A点数字量publicstaticInt32[]calib_adcCalib_analogA=new Int32[8];// A点模拟量(×100000)publicstaticbyte[]calib_adcCalib_enableA=new byte[8];// A点使能publicstaticInt32[]calib_adcCalib_digitalB=new Int32[8];// B点数字量publicstaticInt32[]calib_adcCalib_analogB=new Int32[8];// B点模拟量publicstaticbyte[]calib_adcCalib_enableB=new byte[8];// B点使能publicstaticInt32[]correctFactor=new Int32[8];// 校正系数(×100000)publicstaticInt32[]calibZero=new Int32[8];// 零点偏移(×100000)

模拟量乘以100000存储为整数,避免浮点运算精度损失[word_7]。

4.4 校正系数与零点偏移

在两点校准之后,还叠加校正系数和零点偏移[word_4]:

adcFloat=adcFloat*(correctFactor*0.00001)+(calibZero*0.00001);
  • correctFactor:乘法校正系数,默认100000(即1.0)
  • calibZero:加法零点偏移,默认0

五、Step 4:传感器单位转换

5.1 支持的传感器单位

D223支持以下传感器单位[word_3][word_6]:

类别单位
电压V, mV
电流A, mA
温度℃, m℃, ℉
力/重量N, kg, g
转速G, K, mK
压力MPa, kPa, hPa, Pa

共17种预置单位[word_3]。

注意:D223支持最大256个自定义单位,可以任意修改[note_259]。这意味着用户可以根据实际传感器定义任意工程单位。

5.2 上位机单位选择

C#上位机中,每个通道可以独立选择传感器单位[word_6]:

publicstaticbyte[]sensorUnit=newbyte[8];// 每通道单位索引publicstaticstring[]sensorUnitList={"V","mV","A","mA","℃","m℃","N","kg","g","G","K","mK","MPa","kPa","hPa","Pa","℉"};

六、完整转换示例

示例:±10V量程下测量1V电压

假设AD7606输出16位原始值 = 39322(对应约1V)[word_5]:

Step1: 256点滑动平均 假设256次采样的累加和 = 39322 × 256 = 10,066,432 getAdcFilter16 = 10,066,432 / 256 = 39322 (16位均值) getAdcFilter24 = 10,066,432 (24位累加和) Step2: 量程转换(±10V) 16位mV值 = (39322 - 32768) / 3.2768 = 6554 / 3.2768 = 2000 mV = 2V 24位μV值 = (10066432 - 8388608) / 0.8388608 / 10 = 1677824 / 8.388608 = 200000 μV = 0.2V 注意:这里的示例假设了理想线性,实际值取决于信号和噪声 Step3: 两点校准(假设已标定) 校准点A: d1=32768, a1=0V(0V输入时的ADC值) 校准点B: d2=65535, a2=10V(10V输入时的ADC值) 校准值 = (39322 - 32768) × (10 - 0) / (65535 - 32768) + 0 = 2.003V Step4: 单位转换 传感器选择"V" → 显示 2.003 V 传感器选择"mV" → 显示 2003 mV

七、精度层次总结

D223的ADC数据处理实现了多层精度保障[word_4][note_244]:

层次方法精度
AD7606硬件16位SAR ADC±0.5 LSB INL/DNL
256点过采样软件滑动平均24位等效精度
量程转换数学运算无损(浮点计算)
两点校准线性插值消除系统误差
校正系数乘法+加法微调微米级微调
硬件精度未标定±0.05%
标定后精度两点标定0.01% FSR

八、与其他型号的数据处理对比

特性DABL7606DABL-G511DABM-D223
过采样方式256点滑动平均256点滑动平均256点滑动平均
精度模式16位/24位16位/24位16位/24位
校准方式两点线性插值两点线性插值两点线性插值
参数存储FRAMFRAMFRAM
自定义单位17种预置17种预置256种自定义
数据流SPI1 DMA直读SPI1 DMA直读QSPI四线DMA

三款产品的数据处理算法基本一致,核心差异在于数据传输通道——D223通过QSPI四线DMA读取FPGA FIFO,带宽远高于SPI1直读[note_63]。


九、总结

D223的ADC数据处理流水线是一个从硬件到软件、从原始值到工程值的完整转换链:

AD7606 16位原始值 ↓ 256点滑动平均(+8位精度) 24位累加值 ↓ 量程转换(±5V/±10V → mV/μV) 工程电压值 ↓ 两点线性插值(消除系统误差) 校准电压值 ↓ 校正系数 + 零点偏移(微调) 最终电压值 ↓ 传感器单位转换(V/mV/℃/Pa...) 用户显示值

每一步都有明确的数学公式和代码实现,整个流水线透明可控,便于用户理解和定制。


下篇预告:《D223上位机C#开发实战:从帧解析到波形显示的完整实现》

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

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

立即咨询