[Magic Circuits]-中高速模拟信号采集系统

中高速模拟信号采集系统

米娜桑好久不见!
废话就不多说啦。来点正经的技术文~

这次来试试做一个中高速精密模拟信号采集系统,是一套模拟向数字转换的完整信号链~

资料汇总

电路性能参数

  • 使用ADS8860完成16-bit 1Msps(1M sample per second)的模拟信号采集
  • 输入信号为跨在0V上的(无直流偏置的正负信号),幅值为16V(Vpp=32V)的模拟信号
  • 模拟信号频率范围: DC~100KHz
  • 通过数字串行接口(SPI)将采集到的数据传回MCU
  • 整个模拟电路系统的供电为3.3V单电源

ADC前端设计

参考《新概念模拟电路》-Section-125:单电源标准运放ADC驱动电路

gN81AO.png

参考电路性能设计需求:

  • 采用3.3V为运放和ADC供电(运放为轨到轨运放)
  • 16bit采样精度,采样率1Msps,VRef=2.5V(REF03G)
  • 采集输入信号跨在0V上,幅度为16V(Vpp = 32V),频率范围 DC~100KHz

那么ADC的单端输入最大范围是0-2.5V,考虑裕量,输入安全范围为0V-2V。

确定ADC驱动电路参数要求如下:

  • 电路输出静默电压 Uoz = 1V
  • 增益 G = 2/32 = 1/16 = 0.0625
  • Vdd = 3.3V

分析过程就简略了~如果需要了解的话请自行翻书哦

R_2 = {{G*V_{dd}} \over {U_{oz}}} * R_1  
R_5 = {{G*V_{dd}} \over {V_{dd} - G * V_{dd} - U_{oz}}} * R_1  
R_4 = R1 || R2 || R5

设R1 = 100k,根据上述参数代入公式计算R2,R4,R5

抗混叠滤波器设计

什么&为什么?

当输入被测信号频率为Fi,按照奈奎斯特采样定律,要想采集完整的信号,采样率Fs必须大于2倍被测信号频率Fi。当采样率小于2Fi时,一定会出现混叠现象,即采集的波形中出现很低的混叠频率。下图演示了混叠频率出现的原因——

gN8MB6.png

输入信号为黑色的高频信号,当Fs小于2Fi时,我们获得的采样点形成了红色的波形,其频率不是信号频率,而是混叠频率,很低。混叠现象欺骗了我们的双眼,因此我们不希望出现这种现象。一旦采样数据中出现混叠频率,即使后期增加软件滤波,也是难以滤除的。

唯一的方法就是让大于Fs/2的频率的信号不要出现在ADC的输入端,或者这种频率分量的信号在ADC输入端只有很小的幅度。因此增加一个抗混叠滤波器是非常有必要的。

最简单、最常见的方法就是在ADC输入端前增加一级截止频率Fh的无源低通滤波电路,以实现抗混叠滤波。

抗混叠滤波器的截止频率选择有如下要求:

f_{signal} << f_H << {{f_s} \over {2}}

比如信号频率100KHz,采样频率1MHz,那么fH就在100KHz和500KHz之间取值。但是不能太过于靠近这2个极限值,太过接近100k,会损伤有用信号。太过接近500k,滤波效果会打折扣。

杨老师的比喻是:

这样看起来,fH像个夹板丈夫,左边是媳妇,右边是母亲......

所以还是需要斟酌一下.jpg

设计

ADS8860最高采样率1MHz,输入信号频率不超过100KHz,根据前面的公式可得:

1kHz < f_H < {f_s \over 2} = 500kHz

在没有其他已知条件下,建议将Fh选为两者的乘法平均数:

f_H = {1 \over 2*pi*R_{ISO}*C_L} = {\sqrt{100k*500k}} = 223.607kHz

R_{ISO}*C_L = 0.7118us

同时兼顾采样误差对电阻的要求,查询 ADS8860的Datasheet

gN8J9H.png

可知转换时间最少为500ns,也就是

T_{SAM} = 0.5us 

再看ADS8860内部等效采样电路

gN8Y3d.png

而ADS8860内部采样电容约为4pF,考虑到最为苛刻的要求:

R_s*(4pF+C_L) <= {T_{SAM} \over {0.69314*(16+1)}} = 0.042433us

设CL = 100pF,解得:

R_s <= 408Ω

即前级驱动电路的输出电阻加内部开关电阻不得超过408欧姆。OPA2189的开环输出电阻在f=100kHz时约为200Ω(见下图)。所以可以选择电阻为100欧姆。

gN8tgA.png

至此,抗混叠滤波器设计完毕。

仿真一下

使用LTSpice对ADC驱动电路进行仿真,选择了一个能够单电源供电且轨到轨输出的运算放大器作为OPA2189的替代:

gNYbvj.png

仿真结果表明,在输入信号频率为100kHz,幅度为32V时,输出能够满足设计要求。

gNY78g.png

放大看一下,顶部和底部存在少量非线性失真,具体效果如何待我实际测试的时候再康康。
总之,输入幅度范围是满足了设计要求且十分安全的。

gNYTPS.png

电路图与BOM

最后,用开源人喜闻乐见的KiCad设计了schematic。

gN8NjI.png

并且阻容取值如下:

元件 计算值 实际取值
R1 100kΩ 100kΩ
R2 20.625kΩ 20kΩ+620Ω
R4 6.2kΩ 6.2kΩ
R5 9850Ω 10kΩ
Riso 100Ω 100Ω
CL 100pF 100pF

IC清单

本次实验使用的器件如下:

Model Quantity Description Usage 厂牌
ADS8860 1 16-bit 1MHz采样率 高精度单端ADC 用途?当然是作主ADC呀 Texas Instruments
OPA2189 1 极低偏置 高精度运算放大器,同时具有高GBW 一个单元作为基准电压BUFFER,一个单元用作ADC驱动电路 Texas Instruments
REF03G 1 2.5V 精密基准电压源 用作ADC的基准电压 Analog Devices
TLV70033 1 3.3V LDO 整个模拟电路系统的电源 Texas Instruments

PCB Layout

同样的,用KiCad进行PCB Layout,最后交由某5块钱PCB代工厂(懂得都懂)进行加工。

gN884e.png
gN83ND.jpg
gN8QHK.jpg

测试——

测试单片机平台 STM32F303CCT6
代码我之前写过一份最简单的3-wire模式操作,放在文章开头的资料链接里了~

啊,板子还没到,暂时先鸽着.jpg

到了到了,但是基准电压IC-REF03G我还没买(好贵的说),于是先用LDO的3.3V输出当reference用用~

正面

gc7EPf.jpg

反面

gc7Fat.jpg

连上杜邦线的样子:

gc7VG8.jpg

ADC驱动电路测试

使用的测试仪器有:

  • 500MHz带宽,4Gsa采样率示波器
  • 200MHz信号源

首先,用信号源产生一个 16Vpp,无直流偏置(±8V),频率100kHz的正弦信号 ,输入模拟前端,在ADC输入侧,即模拟前端输出的测试点,用示波器测试如下:

**100kHz正弦信号**

gc5Acd.jpg

gc5uAf.jpg

依据我们ADC驱动电路的设计传输函数:

y = G * x + b  
 G = 0.0625, b = 1 
 y为输出,x为输入

计算得出的结果符合实际测试结果~ 真不戳

再来测试一些别的信号:

**1kHz,±8V正弦信号**

gc5mHP.jpg

**10Hz,±8V正弦信号**

gc5ZnI.jpg

**100kHz,±8V三角波信号**

gc5eBt.jpg

**100kHz,±1V三角波信号**

gc5EjA.jpg

**100kHz,奇怪的信号增加了~**

gc5k1H.jpg

单片机收集数据

我用了STM32F303CCT6来控制ADS8860采集信号并接受其发送的转换数据,配置ADS8860工作模式为

**3-wire CS mode without BUSY Indicator**

我使用TIM6定时产生的事件来控制ADS8860的采样率,在定时器中断中完成采样和数据传输。

最核心的代码是这一小段,非常简单。


uint16_t ads8860_readADCRawValue(void)
{
    uint8_t data[2];

    //  Set CONVST to high to start a conversion
    GPIOB -> BSRR = ADS8860_CVST_Pin;

    //  At least 700ns delay
    for(uint16_t i = 0; i < 42; i++)
        __nop();

    GPIOB -> BRR = ADS8860_CVST_Pin;

    HAL_SPI_Receive(&ADS8860_SPI_Port, data, 2, 0xFF);

    //  Return converted data
    return ((data[0] << 8) | data[1]);
}

定时器回调函数

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef * htim)
{
    if (htim -> Instance == TIM6)
    {
        if(adc_conv_flag == 1)
        {
            if (adc_printf_flag == 1)
            {
                adc_conv_flag = 0;
                adc_printf_flag = 0;
            }
            else 
                __nop();
        }

        else 
        {
            adcRawData[adc_counter] = ads8860_readADCRawValue();
            adc_counter++;

            if (adc_counter == ADC_SAMPLE_SIZE)
            {
                adc_counter = 0;
                adc_conv_flag = 1;
            }
        }
    }
}

驱动代码和其他资料一起打包放在开头的github仓库里了~

采集一个1kHz 峰峰值16V,无直流偏置的正弦信号,并将波形数据通过串口打印到上位机绘图,得到如下结果:

gcbk38.png

真不戳。

在调试的时候遇到了一些问题,比如采样率和定时器计算值不符,后来发现可能是F3的主频太低,spi速率不太够...

现在测试出来最高采样率差不多只能跑到20kHz (啊喂,这也差太多了吧!) 如果以后有条件我会尝试使用更高速的单片机进行测试的~

这期就是这样,感谢你耐心地看完~

发表回复