目录
一、AD7606数据手册
1.ADC采样原理
2.AD7606使用手册
二、实例
1.状态转移图
2.Verilog代码
3.仿真结果
总结
一、AD7606数据手册
1.ADC采样原理
在实际的工程中,经前端传感器出来的信号基本都是模拟信号,而后端mcu主控芯片是基于数字信号进行处理的,因此需要用到ADC进行模数转换。ADC包括三个基本功能:抽样、量化和编码。抽样过程是将模拟信号在时间上离散化,使之成为抽样信号;量化是将抽样信号的幅度离散化使之成为数字信号;而编码则是将数字信号转换成数字系统所能接受的形式。如何实现这三个功能就决定了ADC的形式和性能。同时,ADC的分辨率(即采样精度)越高,需要的转换时间就越长,转换速度就越低,故ADC的分辨率和转换速率两者总是相互制约的。
对于一个16位的ADC来说,如果输入的模拟信号幅值在0到3.3V,那么采样后输出的数字信号对应的应该在0到65535,采样精度是1/65536。因此,我们发现,采样位数越高的AD,其采样精度越高,信噪比越大,其越接近原始信号。
采样率即是两个采样点之间的间隔时间,两个采样点之间的间隔时间越短,其采样率越高。根据奈奎斯特采样定律,信号的采样率应该大于其最大频率的2倍。而实际应用中,通常选择信号最大频率的几十倍的采样率,为了更加准确有效的恢复出原始信号。
2.AD7606使用手册
AD7606是16位,8通道同步采集模数数据采集系统。各器件均内置模拟输入钳位保护、二阶抗混叠滤波器、跟踪保持放大器、16位电荷再分配逐次逼近型模数转换器、灵活的数字滤波器、2.5V基准电压源、基准电压缓冲以及高速串行和并行接口。
AD7606采用5V单电源供电,可以处理正负10V和正负5V真双极性输入信号,同时所有通道均能以高达200kSPS的吞吐速率采样。输入钳位保护电路可以耐受最高达正负16.5V的电压。无论以何种采样频率工作, AD7606的模拟输入阻抗均为1MΩ。它采用单电源工作方式,具有片内滤波和高输入阻抗,因此无需驱动运算放大器和外部双极性电源。AD7606抗混叠滤波器的3dB截止频率22kHz;当采样率为200kSPS时,它具有40dB抗混叠抑制特性。灵活的数字滤波器采用引脚驱动,可以改善信噪比(SNR),并降低3dB带宽。
下面给出AD7606引脚配置和功能描述,下图是AD7606的引脚图:
下图给出AD7606的引脚功能描述:
其中,AD7606可以选择三种工作模式,通过配置引脚PAR/SER/BYTE SEL和DB15,如下图所示:
上述三种工作模式都需要首先给AD7606一个转换信号,如果是各通道同步采样,则需要同时给出CONVST_A和CONVST_B信号,然后等待BUSY信号,如果选择等待AD转换后读取,则需要等待BUSY信号拉低后再进行数据读取;如果选择在AD转换期间读取,则不需要等待BUSY信号拉低。下面给出两种不同时刻读取数据的时序图:
在读取数据时,需要首先给AD7606一个读取数据的使能信号CS,接着给出读取数据的时钟信号RD/SCLK,然后AD7606给出相应的数据。
如果工作在并行接口模式,在CS信号拉低后,RD给出8个时钟,分别读取8个通道采集到的数据DATA[15:0],在读取通道1时FRSTDATA信号拉高,时序图如下所示:
如果工作在串行接口模式,在CS信号拉低后,SCLK给出16*4=64个时钟,分别读取DOUTA输出的采集到的通道1~4上的数据和DOUTB上输出的采集到的通道5~8上的数据,在读取通道1时,FRSTDATA信号拉高时序图如下所示:
如果工作在并行字节接口模式,在CS信号拉低后,RD给出2*8=16个时钟,两个时钟为一组,分别读取某一通道采集到的数据的高八位和低八位,数据从DATA[7:0]输出,时序图如下所示:
下表给出上述三种模式对应的时序规格:
二、实例
要求:通过AD7606同步采集八个通道的数据,FPGA按照串行读取的操作,分别读取各通道采集到的数据。
1.状态转移图
共定义九个状态进行转换,通过输入caiji_flag标志信号开始每次的数据采集,当数据采集结束后,输出caiji_over结束信号。
2.Verilog代码
module ad7606_1(
input clk,
input res,
input dout_a, //ad7606通道a输入串行读取数据
input dout_b, //ad7606通道b输入串行读取数据
input ad_busy, //ad7606输入busy信号
input caiji_flag, //外界输入开始数据采集的标志
output reg ad_cs, //读ad7606的使能信号
output reg ad_rd, //读ad7606的时钟信号
output reg ad_convstab //ad7606开始转换信号,低电平有效
);
parameter IDLE = 9'b0_0000_0001;
parameter AD_CONV = 9'b0_0000_0010;
parameter WAIT_1 = 9'b0_0000_0100;
parameter WAIT_BUSY = 9'b0_0000_1000;
parameter READ_CH15 = 9'b0_0001_0000;
parameter READ_CH26 = 9'b0_0010_0000;
parameter READ_CH37 = 9'b0_0100_0000;
parameter READ_CH48 = 9'b0_1000_0000;
parameter READ_STOP = 9'b1_0000_0000;
parameter CONV_TIME = 5; //AD_CONV状态持续时间等价转换信号低电平持续时间
parameter WAIT_TIME = 5; //WAIT_1状态持续时间
parameter FIV_CLK = 4;
parameter CNT_CLK = 16; //每个通道一次发送的时钟个数
reg [8:0]stata;
reg [5:0]cnt ; //在数据读取状态表示分频系数
reg [4:0]cnt_bite;
reg [15:0]databuffa; //a通道串并转换后存储
reg [15:0]databuffb; //b通道串并转换后存储
//存储八个通道采集到的数据
reg [15:0] data_ch1;
reg [15:0] data_ch2;
reg [15:0] data_ch3;
reg [15:0] data_ch4;
reg [15:0] data_ch5;
reg [15:0] data_ch6;
reg [15:0] data_ch7;
reg [15:0] data_ch8;
reg [2 :0] over;
wire caiji_over;
always@(posedge clk or negedge res)
if(!res)
cnt <= 'd0;
else if(stata == AD_CONV)
if(cnt == CONV_TIME)
cnt <= 'd0;
else
cnt <= cnt + 1;
else if(stata == WAIT_1)
if(cnt == WAIT_TIME)
cnt <= 'd0;
else
cnt <= cnt + 1;
else if(stata == WAIT_BUSY) //为了在下一个状态,cnt从6开始计数,为了让CS和RD信号前后有延时
if(ad_busy == 1'b0)
cnt <= 'd6;
else
cnt <= cnt;
else if(stata == READ_CH15 || stata == READ_CH26 || stata == READ_CH37 || stata == READ_CH48)
if(cnt == (2*FIV_CLK-1))
cnt <= 'd0;
else
cnt <= cnt + 1;
always@(posedge clk or negedge res)
if(!res)
cnt_bite <= 'd0;
else if(stata == READ_CH15 )
if(cnt_bite == (CNT_CLK) && cnt == (2*FIV_CLK-1))
cnt_bite <= 'd0;
else if(cnt == (2*FIV_CLK-1))
cnt_bite <= cnt_bite + 1;
else
cnt_bite <= cnt_bite;
else if( stata == READ_CH26 || stata == READ_CH37 || stata == READ_CH48)
if(cnt_bite == (CNT_CLK -1) && cnt == (2*FIV_CLK-1))
cnt_bite <= 'd0;
else if(cnt == (2*FIV_CLK-1))
cnt_bite <= cnt_bite + 1;
else
cnt_bite <= cnt_bite;
else
cnt_bite <= 'd0;
always@(posedge clk or negedge res)
if(!res)
stata <= 4'd0;
else begin
case(stata)
IDLE : if(caiji_flag == 1'b1)
stata <= AD_CONV;
else
stata <= IDLE;
AD_CONV : if(cnt == CONV_TIME)
stata <= WAIT_1;
else
stata <= AD_CONV;
WAIT_1 : if(cnt == WAIT_1)
stata <= WAIT_BUSY;
else
stata <= WAIT_1;
WAIT_BUSY : if(ad_busy == 1'b0)
stata <= READ_CH15;
else
stata <= WAIT_BUSY;
READ_CH15 : if(cnt_bite == (CNT_CLK ) && cnt == (2*FIV_CLK-1))
stata <= READ_CH26;
else
stata <= READ_CH15;
READ_CH26 : if(cnt_bite == (CNT_CLK -1) && cnt == (2*FIV_CLK-1))
stata <= READ_CH37;
else
stata <= READ_CH26;
READ_CH37 : if(cnt_bite == (CNT_CLK -1) && cnt == (2*FIV_CLK-1))
stata <= READ_CH48;
else
stata <= READ_CH37;
READ_CH48 : if(cnt_bite == (CNT_CLK -1) && cnt == (2*FIV_CLK-1))
stata <= READ_STOP;
else
stata <= READ_CH48;
READ_STOP : stata <= IDLE;
default:stata <= IDLE;
endcase
end
//输出信号
always@(posedge clk or negedge res)
if(!res)
ad_convstab <= 1'b1;
else if(stata == AD_CONV)
ad_convstab <= 1'b0;
else
ad_convstab <= 1'b1;
always@(posedge clk or negedge res)
if(!res)
ad_cs <= 1'b1;
else if(stata == WAIT_BUSY && ad_busy == 1'b0)
ad_cs <= 1'b0;
else if(stata == READ_STOP)
ad_cs <= 1'b1;
else
ad_cs <= ad_cs;
always@(posedge clk or negedge res)
if(!res)
ad_rd <= 1'b1;
else if(stata == READ_CH15 || stata == READ_CH26 || stata == READ_CH37 || stata == READ_CH48)
if(cnt == (FIV_CLK-1))
ad_rd <= 1'b0;
else if(cnt == 2*FIV_CLK-1)
ad_rd <= 1'b1;
else
ad_rd <= ad_rd;
else
ad_rd <= 1'b1;
//处理输入的串行数据
always@(posedge clk or negedge res)
if(!res)begin
databuffa <= 16'd0;
databuffb <= 16'd0;
end
else if(stata == READ_CH15 || stata == READ_CH26 || stata == READ_CH37 || stata == READ_CH48)begin
if(cnt == FIV_CLK && ad_rd == 1'b0)begin
databuffa <= {databuffa[14:0],dout_a};
databuffb <= {databuffb[14:0],dout_b};
end
else begin
databuffa <= databuffa;
databuffb <= databuffb;
end
end
else begin
databuffa <= 16'd0;
databuffb <= 16'd0;
end
//将采集到的数据存储到data_ch1-data_ch8中
always@(posedge clk or negedge res)
if(!res)begin
data_ch1 <= 16'd0;
data_ch2 <= 16'd0;
data_ch3 <= 16'd0;
data_ch4 <= 16'd0;
data_ch5 <= 16'd0;
data_ch6 <= 16'd0;
data_ch7 <= 16'd0;
data_ch8 <= 16'd0;
end
else if(stata == READ_CH15 && cnt_bite == (CNT_CLK) && cnt == (2*FIV_CLK-1))begin
data_ch1 <= databuffa;
data_ch5 <= databuffb;
end
else if(stata == READ_CH26 && cnt_bite == (CNT_CLK -1) && cnt == (2*FIV_CLK-1))begin
data_ch2 <= databuffa;
data_ch6 <= databuffb;
end
else if(stata == READ_CH37 && cnt_bite == (CNT_CLK -1) && cnt == (2*FIV_CLK-1))begin
data_ch3 <= databuffa;
data_ch7 <= databuffb;
end
else if(stata == READ_CH48 && cnt_bite == (CNT_CLK -1) && cnt == (2*FIV_CLK-1))begin
data_ch4 <= databuffa;
data_ch8 <= databuffb;
end
else begin
data_ch1 <= data_ch1 ;
data_ch2 <= data_ch2 ;
data_ch3 <= data_ch3 ;
data_ch4 <= data_ch4 ;
data_ch5 <= data_ch5 ;
data_ch6 <= data_ch6 ;
data_ch7 <= data_ch7 ;
data_ch8 <= data_ch8 ;
end
//八个通道采集结束后,对over信号打拍处理,输出over_flag
assign caiji_over = over[2];
always@(posedge clk or negedge res)
if(!res)
over <= 3'd0;
else if(stata == READ_STOP)begin
over[0] <= 1'b1;
over[1] <= over[0];
over[2] <= over[1];
end
else begin
over[0] <= 1'b0;
over[1] <= over[0];
over[2] <= over[1];
end
endmodule
下面给出tb测试文件:
`timescale 1ns/1ns
module tb1();
reg clk;
reg res;
reg data_b;
reg data_a;
reg busy;
reg caiji_flag;
wire ad_cs;
wire ad_rd;
wire ad_convstab;
reg ad_convstab_buffer;
wire convstab_flag;
reg [9:0]cnt;
initial begin
clk <= 1'b0;
res <= 1'b0;
busy <= 1'b0;
data_a <= 1'b0;
data_b <= 1'b0;
caiji_flag <= 1'b0;
#100 res <= 1'b1;
end
always #10 clk <= ~clk;
//检测ad_convstb的下降沿
always@(posedge clk)
ad_convstab_buffer <= ad_convstab;
assign convstab_flag = (~ad_convstab)&ad_convstab_buffer;
always@(posedge clk or negedge res)
if(!res)
cnt <= 0;
else if(convstab_flag)
cnt <= cnt + 1;
else if(cnt == 7)
cnt <= cnt;
else
cnt <= cnt + 1;
always@(posedge clk)begin
if(cnt >5 && cnt <8)begin
caiji_flag <= 1'b1;
busy <= 1'b0;
end
else if(cnt == 8)begin
caiji_flag <= 1'b0;
busy <= 1'b0;
end
else if(cnt>8 && cnt<20)begin
busy <= 1'b1;
caiji_flag <= 1'b0;
end
else if(cnt == 20)begin
busy <= 1'b0;
caiji_flag <= 1'b0;
end
else
busy <= busy;
end
always@(posedge ad_rd or posedge ad_cs)
if(ad_cs)begin
data_a <= 1'b0;
data_b <= 1'b0;
end
else begin
data_a <= {$random}%2;
data_b <= {$random}%2;
end
ad7606_1 u_ad7606_1(
. clk (clk) ,
. res (res) ,
. dout_a (data_a) , //ad7606 数据
. dout_b (data_b) ,
. ad_busy (busy) , //ad7606 busy
. caiji_flag (caiji_flag) ,
. ad_cs (ad_cs) , //ad7606 AD 片选
. ad_rd (ad_rd) , //ad7606 AD 串行读数据时钟
. ad_convstab (ad_convstab) //ad7606 AD convert start
);
endmodule
3.仿真结果
仿真结果如下图所示:图1给出了前五个状态的时序图,图2给出了后四个状态(数据采集)的时序图,图3给出了整体的时序仿真图。
图1
图2
图3
总结
总体而言,该芯片是一款性能不错的AD芯片,操作时序图相对比较简单,基本能够满足一般系统的性能要求。当然如果系统对数据采集的要求过高,即要求高信噪比,那么在AD选型的过程中可以考虑18位的AD(AD7690、CBM79AD60)或者是24位AD(AD1258)芯片;这里给大家推荐一下AD7690,18位的AD芯片,单通道数据采集,差分输入,串行读取AD数据,其操作时序十分简单,封装为MSOP-10,占用PCB空间较小。文章来源:https://uudwc.com/A/ABNpg
初次创作,难免文章中存在错误,希望读者能够及时纠正并给予私信,望大家共同进步!文章来源地址https://uudwc.com/A/ABNpg