LVDS(Low-Voltage Differential Signaling)低电压差分信号,是一种低功耗、低误码率、低串扰和低辐射的差分信号技术。
KSPS(Kilo Samples per Second),采样千次每秒,是转化速率的单位。
逐次逼近型ADC由比较器包括n位逐次比较型AD转换器,它由控制逻辑电路、时序产生器、移位寄存器、DA转换器及电压比较器组成。
举例如下:电路为8位AD转换器,输入模拟量vA=6.84v,DA转换器基准电压VREF=10v。当启动脉冲低电平到来后转换开始,在第一个CP作用下,数据寄存器将D7~D0=10000000送入D/A转换器,其输出电压v0=5V,vA与v0比较,vA>v0存1;第二个CP到来时,寄存器输出D7~D0=11000000,v0为7.5V,vA再与7.5V比较,因vA<7.5V,所以D6存0;输入第三个CP时,D7~D0=10100000,v0=6.25V;vA再与v0比较,……如此重复比较下去,经8个时钟周期,转换结束。由图中v0的波形可见,在逐次比较过程中,与输出数字量对应的模拟电压v0逐渐逼近vA值,最后得到A/D转换器转换结果D7~D0为10101111。该数字量所对应的模拟电压为6.8359375V,与实际输入的模拟电压6.84V 的相对误差仅为 0.06%
本实验是打算采用AD7928这个数据采集设备,这是一个12位高速、低功耗、8通道逐次逼近型ADC。采用单电源工作,电源电压为2.7v~5.25v,最高吞吐速率可以达到1Msps。内置有低噪声、款带宽采样保持放大器,可以处理8Mhz以上的输入频率。
通过配置控制寄存器,器件的模拟输入范围可以在0v到REFin或0v到2REFin间选择,可采用标准二进制或者二进制补码输出编码。AD7928具有八个通道序列器的单端模拟输入,可以通过预先编程选择通道转换顺序。
时序规格
通过阅读手册第20页,发现有三种方式可以解决上述的问题。
(1)、设置SEQ=0,SHADOW=1,这种方式然后再对SHADOW寄存器进行配置。
(2)、设置SEQ=1,SHADOW=1.也可以实现通道循环,且不需要对对SHADOW寄存器进行配置。但是这个配置必须是从通道0到指定通道依次递增,然后再从0开始。但是WRITE必须是低电平。如果是高电平,那就必须再将SEQ设为1,SHADOW设为0。
(3)、因为上一次转换输出的时候会把下一次转换的通道的地址给出,从而设计可以让8个通道循环起来,这个方法设计出来只要按照时序要求,就基本不会出现错误
目前存在的问题是,这只是8通道的AD采集,但是实验需要用到32个通道,怎么去用这一个AD采集模块去完成4次8通道AD采集???
同时使用8个通道只需要对控制寄存器的参数进行输入配置,即可让8个通道循环使用。
我想想该怎么加控制?
把这个AD7928的通道选择为四个,这四个通道进行循环。每个通道传输来自一个八选一模块的输出,然后八路数据在这个通道里面依次传输。
这个代码是单纯的启动AD7928八个通道连续循环采集数据。
module ad7928_ctrl32(input clk,input rst_n,//spiinput adc_dout,output reg adc_cs,output reg adc_sclk,output reg adc_din,//othersoutput reg dout_vld, //每个转换结束输出一个标志位output [2:0] adc_sel, //控制8选1output reg [18:0] dout,output reg ad_change_flag //每组(即32个PD)结束之后输出一个标志位);parameter WRITE = 1'b1;parameter PM = 2'b11;parameter SEQ =1'b0;parameter SHADOW = 1'b0;parameter RANGE = 1'b0;parameter CODING = 1'b1;//先设计一个时钟频率为1Mhz的,那么周期就是1000nsreg [5:0] cnt0;wire add_cnt0 = 1'b1;wire end_cnt0 = add_cnt0 && cnt0==6'd49;always @ (posedge clk or negedge rst_n) beginif(!rst_n) begincnt0 <= 6'd0;endelse if(add_cnt0) beginif(end_cnt0) begincnt0 <= 6'd0;endelse begincnt0 <= cnt0 + 1'b1;endendend//每次采集16位数据,并且cs的上升沿与下降沿之间最少50nsreg [4:0] cnt1;wire add_cnt1 = end_cnt0;wire end_cnt1 = add_cnt1 && cnt1==5'd17;always @ (posedge clk or negedge rst_n) beginif(!rst_n) begincnt1 <= 5'b0;endelse if(add_cnt1) beginif(end_cnt1) begincnt1 <= 5'b0;endelse begincnt1 <= cnt1 + 1'b1;endendend//切换四个通道reg [2:0] cnt2;wire add_cnt2 = end_cnt1;wire end_cnt2 = add_cnt2 && cnt2 == 3'd3;always @ (posedge clk or negedge rst_n) beginif(!rst_n) begincnt2 <= 3'b0;endelse if(add_cnt2) beginif(end_cnt2) begincnt2 <= 3'b0;endelse begincnt2 <= cnt2 + 1'b1;endendend//切换那4个8选1通道reg [2:0] cnt3;wire add_cnt3 = end_cnt2;wire end_cnt3 = add_cnt3 && cnt3 == 3'd7;always @ (posedge clk or negedge rst_n) beginif(!rst_n) begincnt3 <= 3'b0;endelse if(add_cnt3) beginif(end_cnt3) begincnt3 <= 3'b0;endelse begincnt3 <= cnt3 + 1'b1;endendend//产生adc_csalways @ (posedge clk or negedge rst_n) beginif(!rst_n) beginadc_cs <= 1'b1;endelse if(add_cnt0 && cnt0==6'd24 && cnt1==5'd0) beginadc_cs <= 1'b0;endelse if(add_cnt0 && cnt0==6'd24 && cnt1==5'd17) beginadc_cs <= 1'b1;endend//产生adc_sclkalways @ (posedge clk or negedge rst_n) beginif(!rst_n) beginadc_sclk <= 1'b1;endelse if(add_cnt0 && cnt0==6'd24 && cnt1>=5'd1 && cnt1<5'd17) beginadc_sclk <= 1'b0;endelse if(end_cnt0) beginadc_sclk <= 1'b1;endend//给ADC7928输入控制寄存器wire [15:0] data;assign data = {WRITE,SEQ,1'b0,cnt2,PM,SHADOW,1'b0,RANGE,CODING,4'b0};always @ (posedge clk or negedge rst_n) beginif(!rst_n) beginadc_din <= 0;endelse if(end_cnt0 && cnt1<16) beginadc_din <= data[15-cnt1];endend//输出ADC7928的16位数据reg [15:0] tmp_dout;always @ (posedge clk or negedge rst_n) beginif(!rst_n) begintmp_dout <= 16'd0;endelse if(add_cnt0 && cnt0==6'd24 && cnt1>=1 && cnt1 <17) begintmp_dout[16-cnt1] <= adc_dout;endendalways @ (posedge clk or negedge rst_n) beginif(!rst_n) begindout <= 19'd0;endelse if(cnt1==5'd16)begindout <= {cnt3,tmp_dout};endendalways @ (posedge clk or negedge rst_n) beginif(!rst_n) beginad_change_flag <= 1'b0;endelse if(cnt1==5'd16 && end_cnt3) beginad_change_flag <= 1'b1;endelse beginad_change_flag <= 1'b0;endendalways @ (posedge clk or negedge rst_n) beginif(!rst_n) begindout_vld <= 1'b0;endelse if(add_cnt0 && cnt0==6'd25 && cnt1==5'd16)begindout_vld <= 1'b1;endelse if(add_cnt0 && cnt0==6'd24 && cnt1==5'd16) begindout_vld <= 1'b0;endendassign adc_sel = cnt3;endmodule
这个代码仿真过了,没错,具体还得下板子
后面有机会再试试其他方法,设计这个循环通道的代码
联系客服