Loading...

文章背景图

以GD32F307ZGT6为例的TPC112S1驱动

2026-07-15
5
-
- 分钟

TPC112S1是一款数模转换芯片,详情参见官方数据手册

驱动示例:

typedef enum
{
    TPC112S1_NORMAL = 0U, // 常规模式
    TPC112S1_PD_1K_TO_GND = 1U, // 1k下拉
    TPC112S1_PD_100K_TO_GND = 2U, // 100k下拉
    TPC112S1_PD_HIGH_Z = 3U, // 高阻态
} tpc112s1_mode_t;

#define TPC_DIN_PORT        GPIOB
#define TPC_DIN_PIN         GPIO_PIN_9     // ADC_DIN

#define TPC_CLK_PORT        GPIOB
#define TPC_CLK_PIN         GPIO_PIN_8     // ADC_CLK

#define TPC_SYNC_PORT       GPIOE
#define TPC_SYNC_PIN        GPIO_PIN_6     // ADC_SYNC

#define TPC112S1_MAX_CODE   4095U

static void tpc_bus_delay(void)
{
    for (volatile uint32_t i = 0; i < 1000; i++)
    {
        __NOP();
    }
}

__attribute__((__always_inline__)) static void tpc_din_write(uint8_t level)
{
    if (level)
    {
        gpio_bit_set(TPC_DIN_PORT, TPC_DIN_PIN);
    }
    else
    {
        gpio_bit_reset(TPC_DIN_PORT, TPC_DIN_PIN);
    }
}

__attribute__((__always_inline__)) static void tpc_clk_write(uint8_t level)
{
    if (level)
    {
        gpio_bit_set(TPC_CLK_PORT, TPC_CLK_PIN);
    }
    else
    {
        gpio_bit_reset(TPC_CLK_PORT, TPC_CLK_PIN);
    }
}

__attribute__((__always_inline__)) static void tpc_sync_write(uint8_t level)
{
    if (level)
    {
        gpio_bit_set(TPC_SYNC_PORT, TPC_SYNC_PIN);
    }
    else
    {
        gpio_bit_reset(TPC_SYNC_PORT, TPC_SYNC_PIN);
    }
}

static void tpc112s1_write_word(uint16_t word)
{
    uint16_t mask;

    // TPC112S1 在 SCLK 下降沿采样 DIN。这里让 SCLK 空闲为高,先放数据,再拉低 SCLK 产生采样边沿
    tpc_sync_write(0U);
    tpc_bus_delay();

    for (mask = 0x8000U; mask != 0U; mask >>= 1U)
    {
        tpc_din_write((word & mask) != 0U);
        tpc_bus_delay();

        tpc_clk_write(0U);
        tpc_bus_delay();

        tpc_clk_write(1U);
        tpc_bus_delay();
    }

    tpc_sync_write(1U);
    tpc_bus_delay();
}

static void tpc112s1_write_code(uint16_t code)
{
    uint16_t word;

    if (code > TPC112S1_MAX_CODE)
    {
        code = TPC112S1_MAX_CODE;
    }

    word = code & 0x0FFFU;
    tpc112s1_write_word(word);
}

void tpc112s1_set_voltage_mv(uint32_t vout_mv, uint32_t vref_mv)
{
    uint16_t code;

    if (vref_mv == 0U)
    {
        return;
    }

    if (vout_mv >= vref_mv)
    {
        code = TPC112S1_MAX_CODE;
    }
    else
    {
        code = (uint16_t)(((uint64_t)vout_mv * 4096U + vref_mv / 2U) / vref_mv);
        if (code > TPC112S1_MAX_CODE)
        {
            code = TPC112S1_MAX_CODE;
        }
    }

    tpc112s1_write_code(code);
}

void tpc112s1_mode_ctrl(tpc112s1_mode_t mode)
{
    uint16_t word;

    if (mode > TPC112S1_PD_HIGH_Z)
    {
        mode = TPC112S1_PD_HIGH_Z;
    }

    word = ((uint16_t)mode << 12);
    tpc112s1_write_word(word);
}

void tpc112s1_init(void)
{
    static uint8_t once_flag = 0;
    
    if (once_flag)
    {
        return;
    }
    
    rcu_periph_clock_enable(RCU_GPIOB);
    rcu_periph_clock_enable(RCU_GPIOE);

    // PB8/PB9 前面是 MOS 管电平转换,用开漏由外部 10K 上拉
    gpio_bit_set(GPIOB, TPC_CLK_PIN | TPC_DIN_PIN);
    gpio_init(GPIOB, GPIO_MODE_OUT_OD, GPIO_OSPEED_50MHZ, TPC_CLK_PIN | TPC_DIN_PIN);

    // SYNC 空闲为高
    gpio_bit_set(GPIOE, TPC_SYNC_PIN);
    gpio_init(GPIOE, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, TPC_SYNC_PIN);

    tpc_clk_write(1U);
    tpc_din_write(1U);
    tpc_sync_write(1U);

    tpc_bus_delay();

    // 上电默认输出 0V
    tpc112s1_write_code(0U);
    
    once_flag = 1;
}

使用示例:

tpc112s1_init();
// 假定 VREF 脚的参考电压为 5V
// 输出 3.3V
tpc112s1_set_voltage_mv(3300U, 5000U);
// 切换模式,输出 1k 下拉
tpc112s1_mode_ctrl(TPC112S1_PD_1K_TO_GND);
// 发送正常 DAC 编码值自动切回 TPC112S1_NORMAL 模式
tpc112s1_set_voltage_mv(3300U, 5000U);

原创

以GD32F307ZGT6为例的TPC112S1驱动

本文链接: 以GD32F307ZGT6为例的TPC112S1驱动

本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

评论交流

文章目录