ADC(tlv5618)驱动设计

1、TLV5618 DAC 芯片输出电压计算原理

该电阻网络型 DAC 的输出 电压范围应该为0V~VREF ,对应到 AC620 板上的电路,即 0V~2.048V 。另外在每个 DAC通道的电阻网络电压输出后级,连接了一个 2 倍增益的轨对轨放大器。将电阻网络 DAC 单元的输出电压放大为 2 倍后输出到管脚。所以, TLV5618 芯片的实际输出电压范围为0V~2*VREF,对应到 AC620 板上的电路,即 0V~4.096V 。当芯片上电时, DAC 的值全部被复位到 0。每个 DAC 通道的输出可由下列公式计算得出:
REF 是基准电压,本电路中为 2.048V CODE 是数字电压输入值,范围 0 2^ 12 - 1;输出电压对应着0~2*REF,即0~4.096V

2、TLV5618 DAC 接口时序

(1)SCLK下降沿时,读取数据,数据保持稳定,DIN应在SCLK上升沿时变化。

(2) 当片选(CS̅)信号为低电平时,输入数据信号线(DIN)上的值在每个SCLK信号的下降沿被移入芯片内部的寄存器。 16 位的数据按照高位在前,低位在后的顺序依次移入。

3、TLV5618 16 位DIN数据格式

如下图(前4位是控制位,后12位是数据位)

其中,SPD 为速度控制位,PWR 为电源控制位。 

R1 R0 所有可能的组合以及代表的含义如下所示。如果其中一个寄存器或者缓冲区
被选择,那么 12 位数据将决定新的 DAC 输出电压值。

4、TLV5618驱动模块示意图

5、代码设计

module tlv5618(
	input wire  Clk,
	input wire  Rst_n,
	
	input wire  [15:0] DAC_DATA,   //并行数据输入端
	input wire  Start,             //开始标志
    
	output reg  Set_Done,	       //完成标志
	output reg  DAC_CS_N,          //DAC片选信号
	output reg  DAC_DIN,           //DAC串行数据输出信号
	output reg  DAC_SCLK,          //DAC工作时钟信号
	output wire DAC_State
);
	
	parameter fCLK = 50;
	parameter DIV_PARAM = 2;
		
	reg [15:0]r_DAC_DATA;	       //数据缓存
	reg [3:0]DIV_CNT;              //分频计数器
	reg SCLK2X;                    //2倍SCLK的采样时钟	
	reg [5:0]SCLK_GEN_CNT;         //SCLK生成暨序列机计数器	
	reg en;                        //转换使能信号	
	wire trans_done;               //转换序列完成标志信号
    
	assign DAC_State = DAC_CS_N;
    
    //生成使能信号。当开始标志start有效时使能信号en置1,当转换完成信号有效时使能信号en置0
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		en  <= 1'b0;
	else if(Start)
		en  <= 1'b1;
	else if(trans_done)
		en  <= 1'b0;
	else
		en  <= en;

	//生成2倍SCLK时钟的分频计数器
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		DIV_CNT  <= 4'd0;
	else if(en)begin
		if(DIV_CNT == (DIV_PARAM - 1'b1))
			DIV_CNT  <= 4'd0;
		else 
			DIV_CNT  <= DIV_CNT + 1'b1;
	end else	
		DIV_CNT  <= 4'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;
		
	//生成序列计数器,对SCLK脉冲进行计数(由于SPI有34个状态,故计数0~33)
	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;

    //数据缓存:收到开始发送命令时,寄存DAC_DATA值
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		r_DAC_DATA  <= 16'd0;
	else if(Start)	
		r_DAC_DATA  <= DAC_DATA;
	else
		r_DAC_DATA  <= r_DAC_DATA;
				
	//依次将数据移出到DAC芯片		
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)begin
		DAC_DIN  <= 1'b1;
		DAC_SCLK  <= 1'b0;
		DAC_CS_N <= 1'b1;
	end else if(!Set_Done && SCLK2X) begin
		case(SCLK_GEN_CNT)
			0:
				begin
					DAC_CS_N <= 1'b0;
					DAC_DIN  <= r_DAC_DATA[15];  DAC_SCLK  <= 1'b1;
				end
		
			1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31:
				begin
					DAC_SCLK  <= 1'b0;
				end
			
			2:  begin DAC_DIN  <= r_DAC_DATA[14]; DAC_SCLK  <= 1'b1; end
			4:  begin DAC_DIN  <= r_DAC_DATA[13]; DAC_SCLK  <= 1'b1; end
			6:  begin DAC_DIN  <= r_DAC_DATA[12]; DAC_SCLK  <= 1'b1; end
			8:  begin DAC_DIN  <= r_DAC_DATA[11]; DAC_SCLK  <= 1'b1; end			
			10: begin DAC_DIN  <= r_DAC_DATA[10]; DAC_SCLK  <= 1'b1; end
			12: begin DAC_DIN  <= r_DAC_DATA[9];  DAC_SCLK  <= 1'b1; end
			14: begin DAC_DIN  <= r_DAC_DATA[8];  DAC_SCLK  <= 1'b1; end
			16: begin DAC_DIN  <= r_DAC_DATA[7];  DAC_SCLK  <= 1'b1; end	
			18: begin DAC_DIN  <= r_DAC_DATA[6];  DAC_SCLK  <= 1'b1; end
			20: begin DAC_DIN  <= r_DAC_DATA[5];  DAC_SCLK  <= 1'b1; end				
			22: begin DAC_DIN  <= r_DAC_DATA[4];  DAC_SCLK  <= 1'b1; end
			24: begin DAC_DIN  <= r_DAC_DATA[3];  DAC_SCLK  <= 1'b1; end
			26: begin DAC_DIN  <= r_DAC_DATA[2];  DAC_SCLK  <= 1'b1; end
			28: begin DAC_DIN  <= r_DAC_DATA[1];  DAC_SCLK  <= 1'b1; end			
			30: begin DAC_DIN  <= r_DAC_DATA[0];  DAC_SCLK  <= 1'b1; end
			
			32: DAC_SCLK  <= 1'b1; 
			33: DAC_CS_N  <= 1'b1;
			default:;
		endcase
	end
	
	assign trans_done = (SCLK_GEN_CNT == 33) && SCLK2X;
	
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		Set_Done <= 1'b0;
	else if(trans_done)
		Set_Done <= 1'b1;
	else
		Set_Done <= 1'b0;
	
endmodule
`timescale 1ns/1ns

module tlv5618_tb();

	reg Clk;
	reg Rst_n;
	reg [15:0]DAC_DATA;
	reg Start;
	wire Set_Done;
	
	wire DAC_CS_N;
	wire DAC_DIN;
	wire DAC_SCLK;
	
	tlv5618 tlv5618(
		.Clk(Clk),
		.Rst_n(Rst_n),
		
		.DAC_DATA(DAC_DATA),
		.Start(Start),
		.Set_Done(Set_Done),
		
		.DAC_CS_N(DAC_CS_N),
		.DAC_DIN(DAC_DIN),
		.DAC_SCLK(DAC_SCLK),
		.DAC_State()
	);

	initial Clk = 1;
	always#10 Clk = ~Clk;
	
	initial begin
		Rst_n = 0;
		Start = 0;
		DAC_DATA = 0;
		#201;
		Rst_n = 1;
		#200;
		
		DAC_DATA = 16'hC_AAA;
		Start = 1;
		#20;
		Start = 0;
		#200;
		wait(Set_Done);
		
		#20000;
		
		DAC_DATA = 16'h4_555;
		Start = 1;
		#20;
		Start = 0;
		#200;
		wait(Set_Done);
		
		#20000;	
		
		DAC_DATA = 16'h1_555;
		Start = 1;
		#20;
		Start = 0;
		#200;
		wait(Set_Done);
		#20000;
		DAC_DATA = 16'hf_555;
		Start = 1;
		#20;
		Start = 0;
		#200;
		wait(Set_Done);		
		#20000;		
		$stop;
	end
	
endmodule

 

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
```c #include <reg52.h> #include <intrins.h> #define SDA P1_1 #define SCL P1_0 void delay_us(unsigned int us) { while(us--) { _nop_(); _nop_(); _nop_(); _nop_(); } } void i2c_start() { SDA = 1; SCL = 1; delay_us(5); SDA = 0; delay_us(5); SCL = 0; } void i2c_stop() { SDA = 0; SCL = 1; delay_us(5); SDA = 1; delay_us(5); } void i2c_send_byte(unsigned char dat) { unsigned char i; for(i=0; i<8; i++) { SDA = dat & 0x80; SCL = 1; delay_us(5); SCL = 0; dat <<= 1; } SDA = 1; SCL = 1; delay_us(5); SCL = 0; } unsigned char i2c_read_byte() { unsigned char i, dat = 0; SDA = 1; for(i=0; i<8; i++) { SCL = 1; delay_us(5); dat <<= 1; dat |= SDA; SCL = 0; } return dat; } void i2c_ack() { SDA = 0; SCL = 1; delay_us(5); SCL = 0; SDA = 1; } void i2c_nack() { SDA = 1; SCL = 1; delay_us(5); SCL = 0; } void i2c_write_reg(unsigned char addr, unsigned char reg, unsigned char dat) { i2c_start(); i2c_send_byte(addr); i2c_ack(); i2c_send_byte(reg); i2c_ack(); i2c_send_byte(dat); i2c_ack(); i2c_stop(); } unsigned char i2c_read_reg(unsigned char addr, unsigned char reg) { unsigned char dat; i2c_start(); i2c_send_byte(addr); i2c_ack(); i2c_send_byte(reg); i2c_ack(); i2c_start(); i2c_send_byte(addr | 0x01); i2c_ack(); dat = i2c_read_byte(); i2c_nack(); i2c_stop(); return dat; } ``` 以上是一个简单的I2C驱动程序,可以用于STC单片机上的TLV320ADC3101。在使用时,需要根据具体的硬件连接情况修改SDA和SCL的引脚定义。同时,需要根据TLV320ADC3101的寄存器地址和寄存器值,调用i2c_write_reg和i2c_read_reg函数来进行寄存器的写入和读取。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值