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)
beginif(!rst_n)out <= 16'd0; // 复位else if(datacs & RDdata) begincase(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: ;endcaseend
end// SPI通信
always @(posedge CLK_16_7M or negedge rst_n)
beginif(!rst_n) begincnt <= 1'b0;CS <= 1'b0;RST <= 1'b0;order <= 3'd0;endelse beginRST <= 1'b1;if(cnt < 7'd50)beginCS <= 1'b1;cnt <= cnt + 1'b1;endelse if(cnt >= 7'd50 && cnt <= 7'd82)beginCS <= 0;cnt <= cnt + 1'b1;endif(cnt > 7'd82) // 准备结束, 开始转换beginif(order==3'd0)beginch_sel <= 16'hC400; //写控制字,指示下个通道选中通道1order <= 3'd1;rddat7 <= rddat; //读数据,此数据来自通道7end //本次设置的控制字,下个周期才会生效(采样),再下个周期才能读到数据if(order==3'd1)beginch_sel <= 16'hC800; //写控制字,指示下个通道选中通道2order <= 3'd2;rddat0 <= rddat; //读数据,此数据来自通道0 下同理endif(order==3'd2)beginch_sel <= 16'hCC00;order <= 3'd3;rddat1 <= rddat;endelse if(order==3'd3)begin ch_sel <= 16'hD000;order <= 3'd4;rddat2 <= rddat;endelse if(order==3'd4)begin ch_sel <= 16'hD400;order <= 3'd5;rddat3 <= rddat;endelse if(order==3'd5)begin ch_sel <= 16'hD800;order <= 3'd6;rddat4 <= rddat;endelse if(order==3'd6)begin ch_sel <= 16'hDC00;order <= 3'd7;rddat5 <= rddat;endelse if(order==3'd7)beginch_sel <= 16'hC000; //写控制字,指示下个通道选中通道0order <= 3'd0;rddat6 <= rddat;endCS <= 1'b1; // 一次转换结束, 拉高CS, 准备下一次配置与转换cnt <= 7'd40;endend
endalways @(posedge CLK_16_7M or negedge rst_n)
beginif(!rst_n)beginSDI <= 0;endelse begincase (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];endcaseend
endalways @(negedge CLK_16_7M or negedge rst_n)
beginif(!rst_n)beginrddat <= 0;endelse if(order >= 3'd0) begincase(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;endcaseend
endendmodule