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);