FPGA 使用线性序列机设计SPI接口的TLV5618型DAC芯片驱动逻辑

DAC: Digital-to-Analog Converter,数字模拟转换器。是指将离散的数字信号转换为连续变量的模拟信号的器件,这些模拟信号通常以电流、电压或电荷的形式输出。常见的数字模拟转换器通常用来将一定比例电压值的数字信号转换为模拟信号。

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

code = U* 2*8/5(理想情况下 实际情况下会有差异)

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

TLV5618型DAC芯片

查看TLV5618型DAC芯片手册电路以及时序。

先把传进来的数据Data B 存放到Buffer 然后等数据Data A 来时 ,数据Data A传到Latch A

Buffer中的Data B传到Latch B, 然后再经过数模转换和2倍放大器, 这样就实现了通道A,通道B的电压同时输出

其中REF电压需要查看实际芯片电路图(2.048V)

即 输出电压

化简就是

在芯片手册中查看芯片工作时序图

让通道A和B同时输出,要求通道A输出1V电压,通道B输出2V电压。假设DAC设置为快速模式,从DIN中输入的指令应该是什么?

时序分析


模块框图

线性序列机(1,最小时间的定时单元     2,序列计数器      3,驱动部分)

编写逻辑代码

module TLV5618_Driver(
    Clk,
    Reset_n,
    
    DAC_Data,
    Set_Go,
    
    DAC_CS_N,
    DAC_SCLK,
    DAC_DIN,
    
    Set_Done
    );
    //
    input Clk;
    input Reset_n;
    input [15:0]DAC_Data;
    input Set_Go;
    output reg DAC_CS_N;
    output reg DAC_SCLK;
    output reg DAC_DIN;
    output reg Set_Done;
    
    parameter CLOCK_FREQ = 50_000_000;
    parameter SCLK_FREQ = 12_500_000;
    parameter MCNT_DIV_CNT = CLOCK_FREQ /(SCLK_FREQ * 2) - 1;
    
    reg [7:0]DIV_CNT;
    reg [5:0]LSM_CNT;
    reg [15:0]r_DAC_Data;
    
    always@(posedge Clk)
    if(Set_Go)
       r_DAC_Data <=  DAC_Data;
    else 
        r_DAC_Data <= r_DAC_Data;
    
    reg Set_En;  //转换使能
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        Set_En <= 1'b0;
    else if(Set_Go)
        Set_En <= 1'b1;
    else if((LSM_CNT == 6'd33)&&(DIV_CNT == MCNT_DIV_CNT))
        Set_En <= 1'b0;
    else
        Set_En <= Set_En;
    
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        DIV_CNT <= 1'd0;
    else if(Set_En) begin
        if(DIV_CNT == MCNT_DIV_CNT)
            DIV_CNT <= 1'd0;
        else
            DIV_CNT <= DIV_CNT + 1'd1;
    end
    else
        DIV_CNT <= 1'd0;
        
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)   
        LSM_CNT <= 6'd0;
    else if(DIV_CNT == MCNT_DIV_CNT)begin
        if(LSM_CNT == 6'd33)
            LSM_CNT <= 6'b0;
        else
            LSM_CNT <= LSM_CNT + 1'b1;
    end
    else
        LSM_CNT <= LSM_CNT;

    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n) begin
        DAC_CS_N <= 1'd1;
        DAC_SCLK <= 1'd1;
        DAC_DIN <= 1'd1;
    end
    else if(DIV_CNT == MCNT_DIV_CNT) begin
        case(LSM_CNT)
            0 : begin DAC_SCLK <= 1'd1; DAC_CS_N <= 1'd0; DAC_DIN <= r_DAC_Data[15]; end 
            1 : begin DAC_SCLK <= 1'd0; end
            2 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[14]; end
            3 : begin DAC_SCLK <= 1'd0; end
            4 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[13]; end
            5 : begin DAC_SCLK <= 1'd0; end
            6 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[12]; end
            7 : begin DAC_SCLK <= 1'd0; end
            8 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[11]; end
            9 : begin DAC_SCLK <= 1'd0; end
            10 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[10]; end
            11 : begin DAC_SCLK <= 1'd0; end
            12 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[9]; end
            13 : begin DAC_SCLK <= 1'd0; end
            14 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[8]; end
            15 : begin DAC_SCLK <= 1'd0; end
            16 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[7]; end
            17 : begin DAC_SCLK <= 1'd0;end
            18 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[6]; end
            19 : begin DAC_SCLK <= 1'd0; end
            20 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[5]; end
            21 : begin DAC_SCLK <= 1'd0; end
            22 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[4]; end
            23 : begin DAC_SCLK <= 1'd0; end
            24 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[3]; end
            25 : begin DAC_SCLK <= 1'd0; end
            26 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[2]; end
            27 : begin DAC_SCLK <= 1'd0; end
            28 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[1]; end
            29 : begin DAC_SCLK <= 1'd0; end
            30 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[0]; end
            31 : begin DAC_SCLK <= 1'd0; end
            32 : begin DAC_SCLK <= 1'd1; end
            33 : begin DAC_CS_N <= 1'd1; end    
            default : DAC_CS_N <= 1'd1;    
        endcase
    end
    
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n) 
        Set_Done <= 1'd0;
    else if ((LSM_CNT == 6'd33)&&(DIV_CNT == MCNT_DIV_CNT))
        Set_Done <= 1'd1;
    else
        Set_Done <= 1'd0;
        
endmodule

然后编写testbench测试文件 

代码如下

`timescale 1ns / 1ns
module TLV51618_Driver_tb;
    reg Clk;
    reg Reset_n; 
    reg [15:0]DAC_Data;
    reg Set_Go;   
    wire DAC_CS_N;
    wire DAC_SCLK;
    wire DAC_DIN;
    wire Set_Done;
    
    TLV5618_Driver TLV5618_Driver(
        .Clk(Clk),
        .Reset_n(Reset_n),
        .DAC_Data(DAC_Data),
        .Set_Go(Set_Go),        
        .DAC_CS_N(DAC_CS_N),
        .DAC_SCLK(DAC_SCLK),
        .DAC_DIN(DAC_DIN),        
        .Set_Done(Set_Done)
        );     
    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'hC_AAA;
        Set_Go = 1;
        #20;
        Set_Go = 0;
        #200;
        wait(Set_Done);
        
        #20001;
        
        DAC_Data = 16'h4_555;
        Set_Go = 1;
        #20;
        Set_Go = 0;
        #200;
        wait(Set_Done);
        #20001;

        DAC_Data = 16'h1_555;
        Set_Go = 1;
        #20;
        Set_Go = 0;
        #200;
        wait(Set_Done);
        #20001;

        DAC_Data = 16'hf_555;
        Set_Go = 1;
        #20;
        Set_Go = 0;
        #200;
        wait(Set_Done);
        #20001;
        $stop;
    end
endmodule

仿真波形如下

对比芯片手册提供的时序图,可以看到与芯片手册的时序图一致。

至此,TLV5618型DAC芯片驱动逻辑设计完成。

如若需要板级验证,可加入数码管显示模块,按键消抖模块,LED,以及拨码开关设计需要输出的电压进行简单的板级验证。

  • 14
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TLV5638是一种数字模拟转换器(DAC),而STM32则是一系列由STMicroelectronics开发的32位ARM Cortex-M微控制器。编写一个TLV5638的STM32程序可以实现数字数据转换模拟输出,如将数字信号通过DAC转换为模拟信号。 首先,需要确保将TLV5638正确连接到STM32微控制器。TLV5638具有多个输入引脚,包括数据字节引脚(DIN)、地址引脚(A0)和模拟引脚(VOUT)。根据其规格书或数据手册,将这些引脚连接到STM32的相应引脚。 编写程序前,需要在STM32上初始化GPIO引脚和SPI接口来与TLV5638通信。通过将SPI接口配置为主模式,并设置相关参数,可以实现STM32与TLV5638之间的通信。 在编写主程序时,需要定义相应的变量来存储将要转换的数字数据,并使用SPI接口将这些数据传输到TLV5638。可以使用STM32的SPI发送功能来向TLV5638发送数据命令。 在STM32的主循环中,可以设置一个适当的延时,以等待TLV5638的转换完成。在等待期间,可以执行其他操作,例如读取传感器数据或执行其他任务。 一旦TLV5638完成数字到模拟的转换,可以从TLV5638的模拟输出引脚读取模拟信号。根据需要,可以将模拟信号传递给其他外围设备或执行相应的操作。 总之,编写TLV5638的STM32程序涉及到初始化GPIO引脚和SPI接口,配置参数,传输数字数据到TLV5638,等待转换完成,然后读取模拟输出信号。需要根据具体的应用需求进行适当的程序设计逻辑控制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值