This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

ADS8691: 无法写入范围选择寄存器,按照默认寄存器可以正常输出

Part Number: ADS8691

您好,我在使用ADS8691作为adc采样芯片,然后在写入范围选择寄存器的时候出现了问题,我尝试写入全一输出的寄存器来测试是否通信成功最终还是只能输出默认的寄存器的转换结果,以下 是我的代码使用verilog编写 fpga输入的外部时钟频率是200mhz,我在代码里采用了八分频。

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 11:34:08 09/19/2022
// Design Name:
// Module Name: ads8691
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module ads8691(
input clk_200,
input rst_n,
input sdo,
input rvs,
(*KEEP="TRUE"*)output reg sclk,
output reg sdi,
output reg rst,
output reg conv_cs,
output [18:0] conv_result
);

reg sclk_en;

reg[3:0]sclk_cnt;
reg [3:0]idle_cnt;//稍微延迟一下下 不延迟也没关系
reg [3:0]reset_cnt;//稍微延迟一下下 不延迟也没关系

reg [4:0]rd_cnt;
reg [4:0]rd_cnt_1;

(*KEEP="TRUE"*)reg [17:0]rd_data;
wire [31:0]temp;

(*KEEP="TRUE"*)reg [5:0]wr_cnt;
reg [5:0]wr_cnt_1;
(*KEEP="TRUE"*)parameter [31:0]wr_data=32'b10100000000000000000100000101011; // diyiban 11010100000101000000000000001011
// 11001000010010000000000000000000 全1 11010100000100000000000000000101 10100000000000000000100000101011 nop 00000000_000000000_00000000_00000000 
reg [7:0]conv_cnt;
reg [7:0]rd_cnt1;

reg rvs_a;
reg rvs_b;
wire rvs_neg;
wire rvs_pos;
(*KEEP="TRUE"*)reg [5:0]adc_state;
parameter idle=6'b000001;
parameter reset=6'b000010;
//parameter acq=6'b000100;
parameter rd=6'b001000;
parameter wr=6'b010000;
parameter conv=6'b100000;





always@(posedge clk_200 or negedge rst_n)begin
if(!rst_n)begin
rvs_a<=1'd0;
rvs_b<=1'd0;
end
else begin
rvs_a<=rvs;
rvs_b<=rvs_a;
end
end
assign rvs_pos=(~rvs_b)&rvs_a;
assign rvs_neg=(~rvs_a)&rvs_b;

always@(posedge clk_200 or negedge rst_n)begin
if(!rst_n)begin
sclk_cnt<=4'd0;
end
else if(sclk_en)begin
if(sclk_cnt==4'd7)
sclk_cnt<=4'd0;
else
sclk_cnt<=sclk_cnt+1'd1;
end
else
sclk_cnt<=4'd0;
end

always@(posedge clk_200 or negedge rst_n)begin
if(!rst_n)begin
sclk<=1'd0;
end
else if(sclk_en)begin
if(sclk_cnt==4'd1)
sclk<=1'd1;
else if(sclk_cnt==4'd5)
sclk<=1'd0;
end
else
sclk<=1'd0;
end

always@(posedge clk_200 or negedge rst_n)begin
if(!rst_n)begin
conv_cnt<=8'd0;
end
else if(adc_state==conv)
conv_cnt<=conv_cnt+1'd1;
else
conv_cnt<=8'd0;
end

always@(posedge clk_200 or negedge rst_n)begin
if(!rst_n)begin
rd_cnt1<=8'd0;
end
else if(adc_state==rd)
rd_cnt1<=rd_cnt1+1'd1;
else
rd_cnt1<=8'd0;
end

always@(posedge clk_200 or negedge rst_n)begin
if(!rst_n)begin
adc_state<=idle;
rst<=1'd1;
idle_cnt<=4'd0;
sclk_en<=1'd0;
conv_cs<=1'd1;
wr_cnt<=6'd31;
rd_cnt<=5'd31;
rd_data<=18'd0;
rd_cnt_1<=5'd17;
wr_cnt_1<=6'd32;
reset_cnt<=4'd0;
end

else begin
case(adc_state)
idle:begin
if(idle_cnt==4'd15)begin
rst<=1'd0;
adc_state<=reset;
idle_cnt<=4'd0;
conv_cs<=1'd1;
end
else begin
idle_cnt<=idle_cnt+1'd1;
end
end

reset:begin
//if (rvs_neg)begin
// sclk_en<=1'd1;
//adc_state<=wr;
//reset_cnt<=4'd0;
//end
if(reset_cnt==4'd1)begin
rst<=1'd1;
// adc_state<=wr;
//
//sclk_en<=1'd1;
//conv_cs<=1'd0;
end
else if(reset_cnt==4'd10)
conv_cs<=1'd1;

else if (reset_cnt==4'd20)begin
sclk_en<=1'd1;
adc_state<=wr;
reset_cnt<=4'd0;
end

reset_cnt<=reset_cnt+1'd1;

end
wr:begin
if(sclk_cnt==4'd0)begin
sdi<=wr_data[wr_cnt];
if(wr_cnt_1>6'd0)begin
wr_cnt<=wr_cnt-1'd1;
wr_cnt_1<=wr_cnt_1-1'd1;
end
//else if(wr_cnt==6'd0)begin
// wr_cnt<=6'd31;


end
else if(sclk_cnt==4'd7&&wr_cnt_1==6'd0)begin
sclk_en<=1'd0;
adc_state<=conv;
wr_cnt<=6'd31;
conv_cs<=1'd1;
sdi<=32'd0;
wr_cnt_1<=6'd32;
end
end



conv:begin
if(rvs_pos)begin//(||conv_cnt==8'd150)
adc_state<=rd;
sclk_en<=1'd1;
conv_cs<=1'd0;
//if(conv_cnt==8'd20)begin
// adc_state<=rd;
// sclk_en<=1'd1;
//end
end
end

rd:begin
if(sclk_cnt==4'd1)begin
if(rd_cnt>5'd13)
begin
//rd_cnt_1<=rd_cnt-4'd15;
rd_data[rd_cnt_1]<=sdo;//sdo
rd_cnt<=rd_cnt-1'd1;
rd_cnt_1<=rd_cnt_1-1'd1;
end
else if(rd_cnt>5'd0)begin

rd_cnt<=rd_cnt-1'd1;
rd_data<=rd_data;
if(rd_cnt_1==5'd0)
rd_data[0]<=sdo;
end
else if(rd_cnt==5'd0)
begin
rd_data<=rd_data;
rd_cnt<=5'd0;
end
end
else if(rd_cnt==5'd0&&rd_cnt1==8'd50)begin//&&conv_cnt==8'd70

rd_cnt<=5'd31;
sclk_en<=1'd0;
adc_state<=conv;
conv_cs<=1'd1;
rd_cnt_1<=5'd17;
//rst<=1'd1;
end
end

endcase
end
end
assign temp=rd_data;
endmodule

我的思路是先写寄存器从高位开始写入命令,然后进入转换最后进行读取操作,然后在读和转换之间来回转换。

图中是conv和写状态来回循环第二行的是sdi 第一行是sdo 第三行是sclk 第四行是rvs sdi是写的10100000000000000000100000101011 从低位到高位,但是高位到低位也都试过了也不行。麻烦看看我的问题。谢谢!

后续我修改了一下程序

 这个是我的一个数据帧的波形,最上面是sdo 第二个是sdi 第三行是sclk 第四行是rvs信号,最后一行是cs,写入的命令为10100000000000000000100000101011为11010100000100000000000000000101的高低位互换,请问寄存器应该如何写入呢,我这样写入没有效果,谢谢!

  • 您好,

    在默认配置下SPI工作在mode 0模式下,即在SCLK的上升沿采样数据,因此在SCLK的上升沿SDI线上数据需保持稳定,请注意这一点。

    通信方式是从高位到低位。

    写的命令有3种,如下截图所示:

    范围选择寄存器RANGE_SEL_REG Register地址是  address = 14h,看您写的命令不对呀