AD7606是16位,8/6/4通道同步采样模数转换芯片,各器件内置模拟输入钳位保护,二阶抗混叠滤波器,跟踪保持放大器,16位电荷再分配逐次逼近式模数转换器。
其中:
CONVST:启动转换信号
busy:转换完成信号
cs:片选信号
reset:复位信号
读取AD数据时序如下:
AD采样流程如下:
1、拉低CONVST信号启动转换
2、读取busy信号,当busy信号为低时,说明转换完成,可以读取采样数据,然后触发中断去读取数据
3、读取数据时,先使能CS信号,然后变换RD信号读取数据(注意:每读取一个通道的数据,RD使能到禁止使能一次,AD7606CS保持使能,不能喝RD同步变化,这点在有的AD上面有所不同如MAX125,本人在更换AD芯片时没有注意这点时序变化,导致查了两天时间)
4、8个通道数据读取完成后禁止使能CS,等待下次读取。
当AD独享数据总线时刻采用RD和CS并联的结构,如下图:
其时序如下图所示:
多句嘴,这个时序如果用FPGA实现的话,效率会很高,更能满足采样率要求高的设计。
verilog HDL设计实现如下所示:
//*******************************************************//
// 采样模块模块 6片7606AD //
//*******************************************************//
module AD7606_6(
input rst_n,/*系统复位*/
input clk_50m,/*时钟*/
input [31:0]sampleCnt,/*采样时钟计数*/
input [7:0]inS_data,/*AD数据总线*/
input [5:0]buzy,/*AD忙信号*/
output reg rst,/*AD复位总信号*/
output reg convst,/*AD数据装换总信号*/
output reg [5:0]cs_n,/*AD片选信号*/
output reg rd_n,/*AD读信号*/
output reg IsDataReady, /*一点数据完成读取*/
output reg [7:0]DataOut/*AD数据*/
);
parameter [13:0] AD_RESET_P = 14'b00_0000_0000_0000;
parameter [13:0] AD_RESET_N = 14'b00_0000_0000_0001;
parameter [13:0] AD_START_SP = 14'b00_0000_0000_0010;
parameter [13:0] AD_CONVST_P = 14'b00_0000_0000_0100;
parameter [13:0] AD_BUSY_P = 14'b00_0000_0000_1000;
parameter [13:0] AD_BUSY_N = 14'b00_0000_0001_0000;
parameter [13:0] AD_CS_N = 14'b00_0000_0010_0000;
parameter [13:0] AD_RD_N = 14'b00_0000_1000_0000;
parameter [13:0] AD_GET_DATA = 14'b00_0001_0000_0000;
parameter [13:0] AD_RD_P = 14'b00_0100_0000_0000;
parameter [13:0] AD_RD_P1 = 14'b00_1000_0000_0000;
parameter [13:0] AD_CS_P = 14'b01_0000_0000_0000;
parameter [13:0] AD_CS_P1 = 14'b10_0000_0000_0000;
//当前ad采样序号
reg[3:0] ad_index;//当前AD序号
reg[4:0] ad_data_index;//当前AD数据序号
//
parameter AD_NUM = 6; //
reg clk_ad;
reg ad_start_sp_neg_tri;
reg[31:0] clk_ad_cnt;
always @(posedge clk_50m or negedge rst_n)
begin
if(!rst_n)begin
clk_ad <= 1'b0;
clk_ad_cnt <= 32'd0;
end
else if(clk_ad_cnt>=sampleCnt)begin//
clk_ad <= ~clk_ad;
clk_ad_cnt <= 32'd0;
end
else begin
clk_ad_cnt <= clk_ad_cnt +1'b1;
end
end
/*AD采样状态转换*/
reg[13:0] current_state;//当前状态
reg ad_count_ena;//计数器使能
reg[23:0] ad_count;//计数器
//
/*AD采样状态转换*/
always @(posedge clk_50m or negedge rst_n)
begin
if(!rst_n)begin
current_state <= AD_RESET_P;
ad_count_ena <= 1'b0;
ad_count <= 24'd0;
rst <= 1'b0;
convst <= 1'b0;
rd_n <= 1'b1;
cs_n <= {AD_NUM{1'b1}};
IsDataReady <= 1'b0;
end
else if(ad_count_ena) begin
if(ad_count<=24'd1)
ad_count_ena <= 1'b0;
else
ad_count <= ad_count-1'b1;
end
else begin
case(current_state)
AD_RESET_P:begin
current_state <= AD_RESET_N;
ad_count_ena <= 1'b1;
ad_count <= 24'd3;
rst <= 1'b1;
convst <= 1'b0;
rd_n <= 1'b1;
cs_n <= {AD_NUM{1'b1}};
end
AD_RESET_N:begin
current_state <= AD_START_SP;
ad_count_ena <= 1'b1;
ad_count <= 24'd2;
rst <= 1'b0;
convst <= 1'b0;
rd_n <= 1'b1;
cs_n <= {AD_NUM{1'b1}};
end
AD_START_SP:begin
if(ad_start_sp_neg_tri!=clk_ad)begin
current_state <= AD_CONVST_P;
ad_count_ena <= 1'b1;
ad_count <= 24'd3;//等待buzy信号
ad_start_sp_neg_tri<=clk_ad;
convst <= 1'b1;//AD转换开始
rd_n <= 1'b1;
cs_n <= {AD_NUM{1'b1}};
end
else begin
current_state <= AD_START_SP;//等待。。。
ad_count_ena <= 1'b0;
ad_count <= 24'd0;
convst <= 1'b0;
rd_n <= 1'b1;
cs_n <= {AD_NUM{1'b1}};
end
end
AD_CONVST_P:begin
if(buzy == {AD_NUM{1'd1}})begin
current_state <= AD_BUSY_P;
ad_count_ena <= 1'b1;
ad_count <= 24'd230;
end
else begin
current_state <= AD_RESET_P;
ad_count_ena <= 1'b1;
ad_count <= 24'd6;
rst <= 1'b1;
end
rd_n <= 1'b1;
cs_n <= {AD_NUM{1'b1}};
end
AD_BUSY_P:begin
if(buzy == {AD_NUM{1'd0}})begin
current_state <= AD_BUSY_N;
ad_count_ena <= 1'b1;
ad_count <= 24'd1;
ad_index <=4'd0;//AD序号清零
end
else begin
current_state <= AD_BUSY_P;
ad_count_ena <= 1'b1;
ad_count <= 24'd6;
end
end
AD_BUSY_N:begin
current_state <= AD_CS_N;
ad_count_ena <= 1'b0;
ad_count <= 24'd0;
end
AD_CS_N:begin
current_state <= AD_RD_N;
ad_count_ena <= 1'b1;
ad_count <= 24'd2;
ad_data_index <=5'd0;
cs_n <= {AD_NUM{1'b1}} & (~({6'b000001}<<ad_index));
end
AD_RD_N:begin
current_state <= AD_GET_DATA;
ad_count_ena <= 1'b1;
ad_count <= 24'd2;
rd_n <= 1'b0;//AD读使能
end
AD_GET_DATA:begin
current_state <= AD_RD_P;
ad_count_ena <= 1'b0;
ad_count <= 24'd0;
DataOut <= inS_data;//取AD数据
IsDataReady <= 1'b1;
end
AD_RD_P:begin
current_state <= AD_RD_P1;
ad_count_ena <= 1'b1;
ad_count <= 24'd2;
IsDataReady <= 1'b0;
ad_data_index <= ad_data_index +1'b1;
rd_n <= 1'b1;//AD读禁能
end
AD_RD_P1:begin
if(ad_data_index==5'd16)begin
current_state <= AD_CS_P;
ad_count_ena <= 1'b1;
ad_count <= 24'd1;
end
else begin
current_state <= AD_RD_N;
ad_count_ena <= 1'b0;
ad_count <= 24'd0;
end
end
AD_CS_P:begin
current_state <= AD_CS_P1;
ad_count_ena <= 1'b1;
ad_count <= 24'd2;
ad_index <= ad_index +1'b1;
cs_n <= {AD_NUM{1'b1}};//片选结束
end
AD_CS_P1:begin
if(ad_index==AD_NUM)begin
current_state <= AD_START_SP;
convst <= 1'b0;//AD转换停止
end
else begin
current_state <= AD_CS_N;
end
end
endcase
end
end
endmodule