TLC5615模块之FPGA驱动
1、芯片介绍
TLC5615 为美国德州仪器公司 1999 年推出的产品,是具有串行接口的数模转换器,其输出为电压型,最大输出电压是基准电压值的两倍。带有上电复位功能,即把 DAC 寄存器复位至全零。性能比早期电流型输出的 DAC 要好。只需要通过 3 根串行总线就可以完成 10 位数据的串行输入, 易于和工业标准的微处理器或微控制器(单片机) 接口, 适用于电池供电的测试仪表、移动电话,也适用于数字失调与增益调整以及工业控制场合。
DIN: 串行数据输入端;
TLC5615引脚图
TLC5615引脚图
SCLK: 串行时钟输入端;
/CS: 芯片选用通端,低电平有效;
DOUT: 用于级联时的串行数据输出端;
AGND: 模拟地;
REFIN:基准电压输入端, 2V~ (VDD - 2);
OUT: DAC 模拟电压输出端;
VDD: 正电源端,4.5~5.5V ,通常取 5V。
TLC5615 工作时序如上图所示。 可以看出,只有当片选 CS 为低电平时, 串行输入数据才能被移入16位移位寄存器。当 CS 为低电平时,在每一个 SCLK 时钟的上升沿将 DIN 的一位数据移入 16 位移寄存器。注意, 二进制最高有效位被导前移入。接着,CS 的上升沿将 16 位移位寄存器的 10 位有效数据锁存于 10 位 DAC 寄存器, 供 DAC 电路进行转换; 当片选 CS 为高电平时,串行输入数据不能被移入 16 位移位寄存器。注意, CS 的上升和下降都必须发生在 SCL K 为低电平期间。
2、时钟确定
根据下面时序图和芯片资料算出最大串行时钟速率近似为14M,因为核心板时钟为50M,故采用sclk串行时钟为12.5M,即采用四分频方式。
但是在芯片手册中说:为了使时钟馈通最小。CS在高电平时,sclk应该保持低电平。因此为了方便时钟的控制,不采用PLL生成的方式。采用线性序列机的方法生成可控的sclk。
3、注意
因为DAC的寄存器为12位,但是数据位只有10位,因此要将数据位低位添加两个0,或者左移两位。
4、代码
module TLC5615_CTRL(
input sys_clk,
input rst,
input conv_en, //DA转换使能信号
input [11:0] conv_data, //DA转换输入数据
output reg cs,
output reg conv_end, //DA转换完成信号
output reg tlc5615_clk,
output reg tlc5615_data
);
reg [6:0] cnt;
//计数器
always @(posedge sys_clk or negedge rst)
if(!rst)
cnt <= 7'd0;
else if(conv_en == 1 | (cnt != 7'd0)) begin
if(cnt == 7'd64)
cnt <= 7'd0;
else
cnt <= cnt + 7'd1;
end
else
cnt <= 7'd0;
always @(posedge sys_clk or negedge rst)
if(!rst) begin
conv_end <= 1'b0;
tlc5615_clk <= 1'b0;
tlc5615_data <= 1'b0;
cs <= 1'b1;
end
else begin
case(cnt)
0:
begin
conv_end <= 1'b0;
tlc5615_clk <= 1'b0;
tlc5615_data <= 1'b0;
cs <= 1'b1;
end
1:
begin
tlc5615_data <= conv_data[11];
cs <= 1'b0;
end
2: tlc5615_clk <= 1'b1;
4: tlc5615_clk <= 1'b0;
5: tlc5615_data <= conv_data[10];
6: tlc5615_clk <= 1'b1;
8: tlc5615_clk <= 1'b0;
9: tlc5615_data <= conv_data[9];
10:tlc5615_clk <= 1'b1;
12:tlc5615_clk <= 1'b0;
13:tlc5615_data <= conv_data[8];
14:tlc5615_clk <= 1'b1;
16:tlc5615_clk <= 1'b0;
17:tlc5615_data <= conv_data[7];
18:tlc5615_clk <= 1'b1;
20:tlc5615_clk <= 1'b0;
21:tlc5615_data <= conv_data[6];
22:tlc5615_clk <= 1'b1;
24:tlc5615_clk <= 1'b0;
25:tlc5615_data <= conv_data[5];
26:tlc5615_clk <= 1'b1;
28:tlc5615_clk <= 1'b0;
29:tlc5615_data <= conv_data[4];
30:tlc5615_clk <= 1'b1;
32:tlc5615_clk <= 1'b0;
33:tlc5615_data <= conv_data[3];
34:tlc5615_clk <= 1'b1;
36:tlc5615_clk <= 1'b0;
37:tlc5615_data <= conv_data[2];
38:tlc5615_clk <= 1'b1;
40:tlc5615_clk <= 1'b0;
41:tlc5615_data <= conv_data[1];
42:tlc5615_clk <= 1'b1;
44:tlc5615_clk <= 1'b0;
45:tlc5615_data <= conv_data[0];
46:tlc5615_clk <= 1'b1;
64:
begin
tlc5615_clk <= 1'b0;
cs <= 1'b1;
conv_end <= 1'b1;
end
endcase
end
endmodule 代码片
5、测试模块
`timescale 1ns/1ns
module TLC5615_CTRL_tb;
reg sys_clk;
reg rst;
reg conv_en;
reg [11:0] conv_data;
wire cs;
wire conv_end;
wire tlc5615_clk;
wire tlc5615_data;
TLC5615_CTRL TLC5615_CTRL(
.sys_clk(sys_clk),
.rst(rst),
.conv_en(conv_en),
.conv_data(conv_data),
.cs(cs),
.conv_end(conv_end),
.tlc5615_clk(tlc5615_clk),
.tlc5615_data(tlc5615_data)
);
initial sys_clk =1;
always #10 sys_clk = ~sys_clk;
initial begin
rst = 1'b0;
conv_en = 1'b0;
conv_data = 0;
#201;
rst = 1'b1;
#100;
conv_data = { 10'h2aa,2'b00};
conv_en = 1'b1;
#100;
conv_en = 1'b0;
@(posedge conv_end);
#400;
conv_data = { 10'h3e8,2'b00};
conv_en = 1'b1;
@(posedge conv_end);
#400;
$stop;
end
endmodule
6、仿真图
7、验证
将程序下载至开发板后,将对应的引脚连接至TLC5615模块上,利用万用表测出电压值与实际相符合。
PS:
V为转换后的电压值,Vref为参考电压,data为转换为十进制的值。