当前位置:   article > 正文

35_ZYNQ7020开发板串行序列机SPI协议接口ADC128S022_zynq7020 spi

zynq7020 spi

模数转换器即A/D转换器,或简称ADC,通常是指将模拟信号转变为数字信号的电子元件。
经过与标准量比较处理后的模拟量转换成以二进制数值表示的离散信号的转换器。
ADC128S022
我们使用的模数转换器为8通道及12位的分辨率。
模拟电源VA输入范围为2.7V-5.25V,数字电源VD输入范围为2.7V~VA。
通信接口支持:SPI、QSPI、以及通用的DSP接口。
转换速率:50kps-200kps
在这里插入图片描述
本款ADC为12位的分辨率,因此1bit代表电压值即为VA/4096
当模拟电压低于VA/8192,输出数据即为
0000_0000_0000b。
当模拟电压高于VA-1.5*VA/4096,输出数据为
1111_1111_1111b。
一、ADC128S022型ADC芯片引脚功能
在这里插入图片描述
二、原理图
在这里插入图片描述
ADC部门电路图如图所示,这里外接了一个抗混叠低通滤波器,作用是为了避免输入信号的高频成分在ADC的基带中引起混叠。数字电源与模拟电源电压均为3.3V,且数字电源与模拟电源之间串联磁珠用于抑制电磁干扰。

微控制器与ADC1288S022接口使用标准的SPI接口,因此直接连接到微控制器的片选SPI。对于SPI时序搭建控制电路,以实现对ADC128S022的控制。
在这里插入图片描述
三、ADC128的控制时序、SPI时序
在这里插入图片描述
ADC采集的一个串行帧开始CS下降沿,结束于CS的上升沿。一帧包含16个上升沿SCLK。
ADC的数据输出引脚DOUT当CS为高时代表空闲状态,为低时为传输状态。
相当于CS可以当输出使能。
一帧采集中,头三个SCLK的循环,ADC处于采样模式(track)。在接下来的13个循环为保持模式(hold),转换完成并且完成数据输出。
下降沿1~4为前导零,5-16为输出转换结果。
ADC DIN控制寄存器
在这里插入图片描述
ADD[2:0]
在这里插入图片描述
四、ADC128接口时序设计
技术手册:芯片工作频率SCLK:0.8-3.2Mhz。
定义工作频率:1.92Mhz,设置两倍于SCLK的采样时钟SCLK2X进行计数。
其中CS_N为芯片状态标志信号,SCLK为芯片时钟输入脚,DIN为芯片春航数据输入,DOUT为芯片串行数据输出。
在这里插入图片描述
在这里插入图片描述
线性系列机大大简化了设计思想。
线性序列机的设计思想使用计数器不断计数。
五、线性序列机ADC驱动设计
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
代码:
adc128s022.v

module adc128s022(
			Clk,
			Rst_n,
			
			Channel,
			Data,
			
			En_Conv,
			Conv_Done,
			ADC_State,
			DIV_PARAM,
			
			ADC_SCLK,
			ADC_DOUT,
			ADC_DIN,
			ADC_CS_N
		);

	input Clk;	//输入时钟
	input Rst_n; //复位输入,低电平复位
	input [2:0]Channel;	//ADC转换通道选择
	output reg [11:0]Data;	//ADC转换结果
	input En_Conv;	//使能单次转换,该信号为单周期有效,高脉冲使能一次转换
	output reg Conv_Done;	//转换完成信号,完成转换后产生一个时钟周期的高脉冲
	output ADC_State;	//ADC工作状态,ADC处于转换时为低电平,空闲时为高电平
	input [7:0]DIV_PARAM;	//时钟分频设置,实际SCLK时钟 频率 = fclk / (DIV_PARAM * 2)
	
	output reg ADC_SCLK;	//ADC 串行数据接口时钟信号
	output reg ADC_CS_N;  //ADC 串行数据接口使能信号
	input  ADC_DOUT;		//ADC转换结果,由ADC输给FPGA
	output reg ADC_DIN;	//ADC控制信号输出,由FPGA发送通道控制字给ADC
	
	reg [2:0]r_Channel; //通道选择内部寄存器
	reg [11:0]r_data;	//转换结果读取内部寄存器
	
	reg [7:0]DIV_CNT;//分频计数器
	reg SCLK2X;//2倍SCLK的采样时钟
	
	reg [5:0]SCLK_GEN_CNT;//SCLK生成暨序列机计数器

	
	reg en;//转换使能信号
	
	//在每个使能转换的时候,寄存Channel的值,防止在转换过程中该值发生变化
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		r_Channel <= 3'd0;
	else if(En_Conv)
		r_Channel <= Channel;
	else
		r_Channel <= r_Channel;

	//产生使能转换信号
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		en  <= 1'b0;
	else if(En_Conv)
		en  <= 1'b1;
	else if(Conv_Done)
		en  <= 1'b0;
	else
		en  <= en;
		
	//生成2倍SCLK使能时钟计数器
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		DIV_CNT  <= 8'd0;
	else if(en)begin
		if(DIV_CNT == (DIV_PARAM - 1'b1))
			DIV_CNT  <= 8'd0;
		else 
			DIV_CNT  <= DIV_CNT + 1'b1;
	end else	
		DIV_CNT  <= 8'd0;

	//生成2倍SCLK使能时钟
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		SCLK2X  <= 1'b0;
	else if(en && (DIV_CNT == (DIV_PARAM - 1'b1)))
		SCLK2X  <= 1'b1;
	else
		SCLK2X  <= 1'b0;
		
	//生成序列计数器
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		SCLK_GEN_CNT  <= 6'd0;
	else if(SCLK2X && en)begin
		if(SCLK_GEN_CNT == 6'd33)
			SCLK_GEN_CNT  <= 6'd0;
		else
			SCLK_GEN_CNT  <= SCLK_GEN_CNT + 1'd1;
	end else
		SCLK_GEN_CNT  <= SCLK_GEN_CNT;
	
	//序列机实现ADC串行数据接口的数据发送和接收	
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)begin
		ADC_SCLK <= 1'b1;
		ADC_CS_N <= 1'b1;
		ADC_DIN  <= 1'b1;
	end else if(en) begin
		if(SCLK2X)begin
			case(SCLK_GEN_CNT)
				6'd0:begin ADC_CS_N <= 1'b0; end
				6'd1:begin ADC_SCLK <= 1'b0; ADC_DIN  <= 1'b0; end
				6'd2:begin ADC_SCLK <= 1'b1; end
				6'd3:begin ADC_SCLK <= 1'b0; end
				6'd4:begin ADC_SCLK <= 1'b1; end
				6'd5:begin ADC_SCLK <= 1'b0; ADC_DIN  <= r_Channel[2];end	//addr[2]
				6'd6:begin ADC_SCLK <= 1'b1; end
				6'd7:begin ADC_SCLK <= 1'b0; ADC_DIN  <= r_Channel[1];end	//addr[1]
				6'd8:begin ADC_SCLK <= 1'b1; end
				6'd9:begin ADC_SCLK <= 1'b0; ADC_DIN  <= r_Channel[0];end	//addr[0]

				//每个上升沿,寄存ADC串行数据输出线上的转换结果
				6'd10,6'd12,6'd14,6'd16,6'd18,6'd20,6'd22,6'd24,6'd26,6'd28,6'd30,6'd32:
					begin ADC_SCLK <= 1'b1; r_data <= {r_data[10:0], ADC_DOUT}; end	//循环移位寄存DOUT上的12个数据
				
				6'd11,6'd13,6'd15,6'd17,6'd19,6'd21,6'd23,6'd25,6'd27,6'd29,6'd31:
					begin ADC_SCLK <= 1'b0; end
				
				6'd33:begin ADC_CS_N <= 1'b1; end
				default:begin ADC_CS_N <= 1'b1; end //将转换结果输出
			endcase
		end
		else ;
	end else begin
		ADC_CS_N <= 1'b1;
	end
	
	//转换完成时,将转换结果输出到Data端口,同时产生一个时钟周期的高脉冲信号
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)begin
		Data <= 12'd0; 
		Conv_Done <= 1'b0;
	end else if(en && SCLK2X && (SCLK_GEN_CNT == 6'd33))begin
		Data <= r_data; 
		Conv_Done <= 1'b1;
	end else begin
		Data <= Data; 
		Conv_Done <= 1'b0;
	end
	
	//产生ADC工作状态指示信号
	assign ADC_State = ADC_CS_N;

endmodule

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/346171
推荐阅读
相关标签
  

闽ICP备14008679号