ADS8688 为 16 位采样芯片,最大采样范围 − 10.24 V ∼ + 10.24 V -10.24V\sim+10.24V −10.24V∼+10.24V ,最大采样率 500 k S P S 500 kSPS 500kSPS,8 采样通道,每个通道都可支持双极性 ± 10.24 V \pm 10.24V ±10.24V、 ± 5.12 V \pm 5.12V ±5.12V、 ± 2.56 V \pm 2.56V ±2.56V,单极性 0 ∼ 10.24 V 0\sim 10.24V 0∼10.24V、 0 ∼ 5.12 V 0\sim 5.12V 0∼5.12V。
FPGA驱动代码如下
// 16位采样芯片 ADS8688 的FPGA驱动
// author : 今朝无言
// date : 2022.03.02
// 说明 : 本模块采用循环模式依次采样8个通道
module ads8688(
input rst_n, // FPGA 复位信号(下降沿动作)
input CLK_50M, // 50 MHz时钟输入
output reg RST = 1, // ADS8688 复位信号
output reg SDI, // ADS8688 串行数字输入
output reg CS, // ADS8688 片选信号(低电平有效)
output SCLK, // ADS8688 串行时钟
input SDO, // ADS8688 串行数字输出
input datacs, // 模块数据使能信号
input RDdata // 读使能信号
input [3:0] dataAddr, // 数据通道,0~7
output reg [15:0] out // 采样数据
);
reg [6:0] cnt;
reg [2:0] order = 0; // 状态标志
reg [15:0] ch_sel; // 配置寄存器,用于选择采样通道、设置采样电压范围等
reg [15:0] rddat;
reg [15:0] rddat0, rddat1, rddat2, rddat3, rddat4, rddat5, rddat6, rddat7;
wire CLK_16_7M;
assign SCLK = ~CS & CLK_16_7M;
// 时钟分频模块
clkdiv clk_inst
(
.clk (CLK_50M),
.div (16'd3),
.clkout (CLK_16_7M)
);
// 数据读取
always @(posedge CLK_50M or negedge rst_n)
begin
if(!rst_n)
out <= 16'd0; // 复位
else if(datacs & RDdata) begin
case(dataAddr)
4'd0: out <= rddat0;
4'd1: out <= rddat1;
4'd2: out <= rddat2;
4'd3: out <= rddat3;
4'd4: out <= rddat4;
4'd5: out <= rddat5;
4'd6: out <= rddat6;
4'd7: out <= rddat7;
default: ;
endcase
end
end
// SPI通信
always @(posedge CLK_16_7M or negedge rst_n)
begin
if(!rst_n) begin
cnt <= 1'b0;
CS <= 1'b0;
RST <= 1'b0;
order <= 3'd0;
end
else begin
RST <= 1'b1;
if(cnt < 7'd50)
begin
CS <= 1'b1;
cnt <= cnt + 1'b1;
end
else if(cnt >= 7'd50 && cnt <= 7'd82)
begin
CS <= 0;
cnt <= cnt + 1'b1;
end
if(cnt > 7'd82) // 准备结束, 开始转换
begin
if(order==3'd0)
begin
ch_sel <= 16'hC400; //写控制字,指示下个通道选中通道1
order <= 3'd1;
rddat7 <= rddat; //读数据,此数据来自通道7
end //本次设置的控制字,下个周期才会生效(采样),再下个周期才能读到数据
if(order==3'd1)
begin
ch_sel <= 16'hC800; //写控制字,指示下个通道选中通道2
order <= 3'd2;
rddat0 <= rddat; //读数据,此数据来自通道0 下同理
end
if(order==3'd2)
begin
ch_sel <= 16'hCC00;
order <= 3'd3;
rddat1 <= rddat;
end
else if(order==3'd3)
begin
ch_sel <= 16'hD000;
order <= 3'd4;
rddat2 <= rddat;
end
else if(order==3'd4)
begin
ch_sel <= 16'hD400;
order <= 3'd5;
rddat3 <= rddat;
end
else if(order==3'd5)
begin
ch_sel <= 16'hD800;
order <= 3'd6;
rddat4 <= rddat;
end
else if(order==3'd6)
begin
ch_sel <= 16'hDC00;
order <= 3'd7;
rddat5 <= rddat;
end
else if(order==3'd7)
begin
ch_sel <= 16'hC000; //写控制字,指示下个通道选中通道0
order <= 3'd0;
rddat6 <= rddat;
end
CS <= 1'b1; // 一次转换结束, 拉高CS, 准备下一次配置与转换
cnt <= 7'd40;
end
end
end
always @(posedge CLK_16_7M or negedge rst_n)
begin
if(!rst_n)
begin
SDI <= 0;
end
else begin
case (cnt)
7'd50: SDI <= ch_sel[15]; // 配置寄存器以选择转换通道、采样电压范围
7'd51: SDI <= ch_sel[14];
7'd52: SDI <= ch_sel[13];
7'd53: SDI <= ch_sel[12];
7'd54: SDI <= ch_sel[11];
7'd55: SDI <= ch_sel[10];
7'd56: SDI <= ch_sel[9];
7'd57: SDI <= ch_sel[8];
7'd58: SDI <= ch_sel[7];
7'd59: SDI <= ch_sel[6];
7'd60: SDI <= ch_sel[5];
7'd61: SDI <= ch_sel[4];
7'd62: SDI <= ch_sel[3];
7'd63: SDI <= ch_sel[2];
7'd64: SDI <= ch_sel[1];
7'd65: SDI <= ch_sel[0];
endcase
end
end
always @(negedge CLK_16_7M or negedge rst_n)
begin
if(!rst_n)
begin
rddat <= 0;
end
else if(order >= 3'd0) begin
case(cnt)
7'd67: rddat[15] = SDO; // 读取采样值
7'd68: rddat[14] = SDO;
7'd69: rddat[13] = SDO;
7'd70: rddat[12] = SDO;
7'd71: rddat[11] = SDO;
7'd72: rddat[10] = SDO;
7'd73: rddat[9] = SDO;
7'd74: rddat[8] = SDO;
7'd75: rddat[7] = SDO;
7'd76: rddat[6] = SDO;
7'd77: rddat[5] = SDO;
7'd78: rddat[4] = SDO;
7'd79: rddat[3] = SDO;
7'd80: rddat[2] = SDO;
7'd81: rddat[1] = SDO;
7'd82: rddat[0] = SDO;
endcase
end
end
endmodule