一、74HC4051简介

1. 74HC4051原理

         当同时需要输出或者采集8个低频的电压但是又为了要减少DAC/ADC的数量,可以使用多路复用器74HC4051。

        74HC4051是一款8通道模拟多路复用器/解复用器,其核心功能是通过数字控制信号选择某一通道导通,与38译码器不同的是,74HC4051是模拟信号的导通,可以理解为导线的直接相连。导通是双向的。既可以在8路电压中选择一路输出,也可以将一路公共电压映射到8路输出的任意一路。

        74HC4051的模拟开关本质是物理通道切换。当切换通道时,前一路的物理连接会被断开,芯片本身不会存储或维持之前通道的电压值。但是每个通道后端可以并联一个电容(时间常数τ=RC)以及一个运放,用于暂时的电压保持,因此74HC4051也需要不断地切换轮巡所有通道。避免电容放点时间过长,丧失电压保持的功能。

 2. 74HC4051引脚定义

    3. 74HC4051真值表

    Input

    Channel ON

    E_N

    C

    B

    A

    0

    0

    0

    0

    X0 to Z

    0

    0

    0

    1

    X1 to Z

    0

    0

    1

    0

    X2 to Z

    0

    0

    1

    1

    X3 to Z

    0

    1

    0

    0

    X4 to Z

    0

    1

    0

    1

    X5 to Z

    0

    1

    1

    0

    X6 to Z

    0

    1

    1

    1

    X7 to Z

    1

    X

    X

    X

    switches off

    二、DACx0501

    1. DACx0501简介

            DACx0501是德州仪器(TI)推出的高精度、低功耗数模转换器(DAC)系列,包含16位的DAC80501、14位的DAC70501和12位的DAC60501三款型号。该系列专为工业、测试测量和通信等场景设计,具有以下核心特性:

            1. ​高精度与稳定性

            ​分辨率与线性度:提供12-16位分辨率,最大积分非线性(INL)和微分非线性(DNL)均低于1LSB,确保输出信号的精确性。

            ​内部基准电压:集成2.5V精密基准源,温度漂移低至5ppm/°C,支持1.25V、2.5V或5V的满量程输出电压范围,并可通过外部基准扩展灵活性。

            2. ​低功耗设计

            工作电流仅1mA(5.5V供电时),在掉电模式下电流可降至15µA(典型值),适合电池供电或低功耗场景。

            宽电源电压范围(2.7V至5.5V),兼容多种供电环境。

             3. ​灵活的接口与配置

    ​        数字接口:通过SPI2C引脚可切换为SPI或I²C模式。SPI模式下支持高达50MHz的时钟速率,I²C模式兼容标准(100kbps)、快速(400kbps)和快速+(1.0Mbps)速率。本文仅介绍其SPI模式。

            ​上电复位功能:输出默认为零电平或中间电平,需写入有效代码后才会更新,防止系统启动时的不确定性

    2.  DACx0501配置

            1.spi模式的数据帧格式

    Bit24~21

    Bit20~17

    Bit16~1

    0

    4bit地址

    8bit数据

            2. 发送时序

            3.寄存器 

    名称

    地址

    功能描述

    关键字段/位定义

    ​NOOP

    0x0

    无操作寄存器,用于维持当前状态或填充通信帧。

    命令位0000,无数据操作。

    ​DEVID

    0x1

    设备识别寄存器,读取芯片型号和版本信息。

    RESOLUTION位标识DAC分辨率,RSTSEL保留位需置0。

    ​SYNC

    0x2

    同步控制寄存器,管理多DAC同步更新。

    DAC_SYNC位控制同步模式,SYNC_EN使能硬件同步引脚。

    ​CONFIG

    0x3

    核心配置寄存器,控制参考电压、缓冲器和功耗模式。

    REF_PWDWN(参考电压使能)、BUF_GAIN(输出缓冲增益)、DAC_PWD(DAC关断)。

    ​GAIN

    0x4

    增益校准寄存器,设置输出范围(如0-VREF或0-2VREF)。

    BUF_GAIN位选择增益倍数(bit8置位:1/2,1x或bit0置位:2x),RESERVED位需置0。

    ​TRIGGER

    0x5

    触发控制寄存器,配置DAC更新触发方式。

    LDAC位选择立即更新或同步触发,SOFT_RESET位触发软件复位。

    ​STATUS

    0x7

    状态监控寄存器,检测参考电压异常或配置错误。

    REF_ALARM位指示参考电压故障,需通过写1清除标志。

    ​DAC_DATA

    0x8

    DAC数据寄存器,写入待转换的数字值(16~20位,取决于分辨率)。

    数据位直接映射到模拟输出,需按分辨率对齐有效位。

     4.verilog代码

    
    // 顶层模块:DAC多路复用控制器
    module dac_multiplexer (
        input clk,          // 系统时钟(如50MHz)
        input reset_n,      // 异步复位
        // SPI接口
        output spi_sclk,    // SPI时钟
        output reg spi_cs,  // SPI片选(低有效)
        output spi_mosi,    // SPI主输出
        input spi_miso,     // SPI主输入(未使用)
        // 74HC4051控制
        output [2:0] mux_sel,  // 通道选择ABC
        output mux_en_n,       // 使能信号(低有效)
        // 状态指示
        output reg [2:0] state_led // 状态机指示
    );
    
    // ---------- 参数定义 ----------
    parameter NUM_CHANNELS = 8;       // 复用通道数
    parameter CLK_DIV = 16;           // SPI时钟分频系数
    parameter HOLD_TIME = 1000;       // 电压保持时间(时钟周期数)
    
    // ---------- 寄存器定义 ----------
    reg [15:0] dac_data[0:7];         // 8通道DAC数据缓存
    reg [23:0] spi_tx_data;            // SPI待发送数据(4位保留+4位地址+16位数据)
    reg [7:0] spi_counter;            // SPI位计数器
    reg [24:0] hold_counter;          // 电压保持时间计数器
    reg [2:0] current_channel;        // 当前通道编号
    
    // ---------- 状态机定义 ----------
    typedef enum {
        IDLE,
        SPI_START,
        SPI_TX,
        CHANNEL_HOLD,
        CHANNEL_SWITCH
    } state_t;
    reg [2:0] state;
    
    // ---------- SPI时钟生成 ----------
    reg [7:0] clk_div_counter;
    reg spi_clk;
    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            clk_div_counter <= 0;
            spi_clk <= 0;
        end else begin
            if (clk_div_counter >= CLK_DIV/2 - 1) begin
                clk_div_counter <= 0;
                spi_clk <= ~spi_clk;
            end else begin
                clk_div_counter <= clk_div_counter + 1;
            end
        end
    end
    assign spi_sclk = (state == SPI_TX) ? spi_clk : 1'b0;
    
    // ---------- 主状态机控制 ----------
    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            state <= IDLE;
            spi_cs <= 1'b1;
            current_channel <= 3'b0;
            hold_counter <= 0;
        end else begin
            case (state)
                IDLE: begin
                    state_led <= 3'b001;
                    if (current_channel < NUM_CHANNELS-1)
                        current_channel <= current_channel + 1;
                    else
                        current_channel <= 0;
                    state <= SPI_START;
                end
                
                SPI_START: begin
                    state_led <= 3'b010;
                    spi_cs <= 1'b0;
                    spi_counter <= 23; // 24位数据长度
                    spi_tx_data <= {4'd0,4'h8, dac_data[current_channel]}; // DAC_DATA寄存器地址0x8
                    state <= SPI_TX;
                end
                
                SPI_TX: begin
                    state_led <= 3'b011;
                    if (spi_clk && spi_counter > 0) begin
                        spi_counter <= spi_counter - 1;
                        spi_tx_data <= spi_tx_data << 1;
                    end
                    if (spi_counter == 0) begin
                        spi_cs <= 1'b1;
                        state <= CHANNEL_HOLD;
                    end
                end
                
                CHANNEL_HOLD: begin
                    state_led <= 3'b100;
                    if (hold_counter < HOLD_TIME)
                        hold_counter <= hold_counter + 1;
                    else begin
                        hold_counter <= 0;
                        state <= CHANNEL_SWITCH;
                    end
                end
                
                CHANNEL_SWITCH: begin
                    state_led <= 3'b101;
                    mux_sel <= current_channel;
                    state <= IDLE;
                end
            endcase
        end
    end
    
    // ---------- 74HC4051控制 ----------
    assign mux_en_n = (state == CHANNEL_SWITCH) ? 1'b0 : 1'b1;
    
    // ---------- SPI数据输出 ----------
    assign spi_mosi = spi_tx_data[23];
    
    // ---------- 初始化数据加载(示例) ----------
    initial begin
        // 初始化DAC数据缓存(可根据实际应用修改)
        dac_data[0] = 16'h8000;  // 通道0中间电平
        dac_data[1] = 16'h4000;  // 通道1 25%电平
        dac_data[2] = 16'hC000;  // 通道2 75%电平
        // ... 其他通道初始化
    end
    
    endmodule

    Logo

    智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

    更多推荐