14-基于SPI的DAC芯片驱动
一、DAC
1.1 DAC简介
Digital-to-Analog Converter,数字模拟转换器。是指将离散的数字信号转换为连续变量的模拟信号的器件,这些模拟信号通常以电流、电压或电荷的形式输出。常见的数字模拟转换器通常用来将一定比例电压值的数字信号转换为模拟信号。
1.2 DAC常见指标参数
分辨率:指最小输出电压(对应的输入数字量只有最低有效位为“1”)与最大输出电压(对应的输入数字量所有有效位全为“1”)之比。比如N位DAC,其分辨率为1/(2^N-1)。
输出电压范围:DAC作为数字转模拟的器件,其能够进行转换的数字信号的范围总是有限的。不同型号的DAC,输出电压相差很大,对于电压输出型,最大输出电压一般为5~10V,也有高压输出型的,为24~30V。对于电流输出型DAC,输出电流一般为20mA左右,高者有的能达到3A,这类DAC由于本身输出电流,最终需要外部电阻和运放电路,才能实现电压输出。
假如一个DAC为8位,最大输出电压为5V
输入数字量:255 电压:5V
输入数字量:128 电压:2.5V
输入数字量:64 电压:1.25V
理想情况下:模拟量与数字量之间的关系

转换速率:DAC的转换速率由建立时间决定。从输入由全0突变为全1时开始,到输出电压稳定FSR±LSB 范围(或FSR+x%FSR指明范围)内为止,这段时间称为建立时间,它是DAC的最大响应时间,所以该值用来衡量转换速度的快慢。


Buffer缓存器;Latch锁存器;通过buffer 与 Latch同步更新双通道电压,确保纳秒级精度同步

REF为参考电压值,TVL5618的参考电压值为2.048V

二、DAC时序分析

16位数据:高四位配置问题(速率、通道控制),12位数据位
tsu(cs-ck):信号从~CS被拉低到第一个SCLK下降沿所需要保持的时间间隔
tsu(D):数据应当在SCLK下降沿之前多长时间内稳定


1V模拟量对应的数字量为1000→0011_1110_1000;
2V模拟量对应的数字量为2000→0111_1101_0000;

三、代码编写
3.1 设计文件
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Create Date: 2025/07/09 12:46:14
// Design Name:
// Module Name: TCL5618_Driver
//////////////////////////////////////////////////////////////////////////////////
module TCL5618_Driver(
clk,
reset_n,
set_go,
set_done,
DAC_DATA,
DAC_SCLK,
DAC_CS_N,
DAC_DIN,
);
input clk;
input reset_n;
input set_go;
input [15:0] DAC_DATA;
output reg set_done;
output reg DAC_CS_N;
output reg DAC_DIN;
output reg DAC_SCLK;
reg [29:0] div_cnt;
reg [5:0] bit_cnt;
reg [15:0] r_data;
reg set_en;
parameter clk_freq = 50_000_000;
parameter SCLK_freq = 12_500_000;
parameter mcnt_div = clk_freq/(SCLK_freq * 2)-1; //最小时间单位为周期的一半
parameter mcnt_bit = 33;
//数据寄存
always @(posedge clk)
if(set_go)
r_data <= DAC_DATA;
else
r_data <= r_data;
always @(posedge clk or negedge reset_n)
if(!reset_n)
set_en <= 1'b0;
else if(set_go)
set_en <= 1'b1;
else if((bit_cnt == mcnt_bit)&&(div_cnt == mcnt_div))
set_en <= 1'b0;
else
set_en <= set_en;
//最小时间单元计数器
always @(posedge clk or negedge reset_n)
if(!reset_n)
div_cnt <= 30'd0;
else if(set_en)begin
if(div_cnt == mcnt_div)
div_cnt <= 30'd0;
else
div_cnt <= div_cnt + 1'b1;
end
else
div_cnt <= 30'd0;
//对最小时间单位进行位计数
always @(posedge clk or negedge reset_n)
if(!reset_n)
bit_cnt <= 6'd0;
else if(div_cnt == mcnt_div) begin
if(bit_cnt == mcnt_bit)
bit_cnt <= 6'd0;
else
bit_cnt <= bit_cnt +1'b1;
end
else
bit_cnt <= bit_cnt;
//驱动信号
always @(posedge clk or negedge reset_n)
if(!reset_n) begin
DAC_CS_N <= 1'b1;
DAC_SCLK <= 1'b0;
DAC_DIN <= 1'b1;
end
else if(div_cnt == mcnt_div) begin
case(bit_cnt)
0:begin DAC_CS_N <= 1'b0;DAC_SCLK <= 1'b1;DAC_DIN <=r_data[15]; end
1:DAC_SCLK <= 1'b0;
2:begin DAC_SCLK <= 1'b1;DAC_DIN <=r_data[14]; end
3:DAC_SCLK <= 1'b0;
4:begin DAC_SCLK <= 1'b1;DAC_DIN <=r_data[13]; end
5:DAC_SCLK <= 1'b0;
6:begin DAC_SCLK <= 1'b1;DAC_DIN <=r_data[12]; end
7:DAC_SCLK <= 1'b0;
8:begin DAC_SCLK <= 1'b1;DAC_DIN <=r_data[11]; end
9:DAC_SCLK <= 1'b0;
10:begin DAC_SCLK <= 1'b1;DAC_DIN <=r_data[10]; end
11:DAC_SCLK <= 1'b0;
12:begin DAC_SCLK <= 1'b1;DAC_DIN <=r_data[9]; end
13:DAC_SCLK <= 1'b0;
14:begin DAC_SCLK <= 1'b1;DAC_DIN <=r_data[8]; end
15:DAC_SCLK <= 1'b0;
16:begin DAC_SCLK <= 1'b1;DAC_DIN <=r_data[7]; end
17:DAC_SCLK <= 1'b0;
18:begin DAC_SCLK <= 1'b1;DAC_DIN <=r_data[6]; end
19:DAC_SCLK <= 1'b0;
20:begin DAC_SCLK <= 1'b1;DAC_DIN <=r_data[5]; end
21:DAC_SCLK <= 1'b0;
22:begin DAC_SCLK <= 1'b1;DAC_DIN <=r_data[4]; end
23:DAC_SCLK <= 1'b0;
24:begin DAC_SCLK <= 1'b1;DAC_DIN <=r_data[3]; end
25:DAC_SCLK <= 1'b0;
26:begin DAC_SCLK <= 1'b1;DAC_DIN <=r_data[2]; end
27:DAC_SCLK <= 1'b0;
28:begin DAC_SCLK <= 1'b1;DAC_DIN <=r_data[1]; end
29:DAC_SCLK <= 1'b0;
30:begin DAC_SCLK <= 1'b1;DAC_DIN <=r_data[0]; end
31:DAC_SCLK <= 1'b0;
32:DAC_SCLK <= 1'b1;
33:DAC_CS_N <= 1'b1;
default:DAC_CS_N <= 1'b1;
endcase
end
//为了避免数据接收的过程中,未完成的结果条件在输出端口上,使用内部存储器存储数据结枿
always @(posedge clk or negedge reset_n)
if(!reset_n)
set_done <= 1'b0;
else if((bit_cnt == mcnt_bit)&&(div_cnt == mcnt_div))
set_done <= 1'b1;
else
set_done <= 1'b0;
endmodule
3.2 激励文件
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Create Date: 2025/07/09 14:14:00
// Design Name:
// Module Name: TCL5618_Driver_tb
//////////////////////////////////////////////////////////////////////////////////
module TCL5618_Driver_tb();
reg clk;
reg reset_n;
reg set_go;
wire set_done;
reg [15:0] DAC_DATA;
wire DAC_DIN;
wire DAC_SCLK;
wire DAC_CS_N;
TCL5618_Driver TCL5618_Driver_inst(
.clk(clk),
.reset_n(reset_n),
.set_go(set_go),
.set_done(set_done),
.DAC_DATA(DAC_DATA),
.DAC_SCLK(DAC_SCLK),
.DAC_CS_N(DAC_CS_N),
.DAC_DIN(DAC_DIN)
);
initial clk =1;
always #10 clk = ~clk;
initial begin
reset_n=0;
set_go=0;
DAC_DATA=0;
#201;
reset_n=1;
#200;
DAC_DATA=16'hCAAA;
set_go=1;
#20;
set_go=0;
#200;
wait(set_done);
#20001;
DAC_DATA=16'h4555;
set_go=1;
#20;
set_go=0;
#200;
wait(set_done);
#20001;
DAC_DATA=16'h1555;
set_go=1;
#20;
set_go=0;
#200;
wait(set_done);
#20001;
DAC_DATA=16'hf555;
set_go=1;
#20;
set_go=0;
#200;
wait(set_done);
#20001;
$stop;
end
endmodule
3.3 仿真图

四、模块调用

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)