1. 前言

TPC219x 是一款具有 16、14 和 12 位分辨率的高精度 DAC,所有引脚均兼容。

该器件包括一个 2.5V 内部基准,可用于降低系统复杂性。

可以选择多个增益选项,以提供不同的满量程输出电压,1.25V、2.5V 和 5V。

该器件在单个模拟电源下工作,并具有单独的 VIO 电源用于数字通信。通信通过串行接口进行,并且可以在宽范围 VIO 电源电压下工作。

集成了一个上电复位电路,以将 DAC 输出保持在零电平或中间电平。

介绍源自3peak官网介绍;使用的TPC2190是一款16位DAC输出芯片;

2. SPI及引脚配置

截取 bit23 的位中心,可以看到在bit23的位中心,CS片选引脚为电平;SCLK时钟线正处在下降沿,并且是在第一个沿,再细细观察一下,可以看到时钟线空闲时为高电平,由此可以得出配置的SPI的时钟极性和相位;至于数据传输脚的FSDO,是该芯片的一个使数据提前半个时钟周期开始读取的标志,可以用或者不用,需要去配置芯片的寄存器;
在这里插入图片描述

数据位数配置则要查看它的数据帧结构;在开启CRC时读和写的数据长度都是1帧数据4字节,在关闭CRC时,数据帧结构则是1帧数据3个字节;

那么,在开启CRC的情况下,可以将SPI数据长度配置为16位,关闭CRC时配为8位,当然,全凭个人喜好即可;
在这里插入图片描述

接下来就能得到如下配置,AT32的配置工具做了个示意图,比较了一下和TPC219x的数据传输时序是一致的;
在这里插入图片描述

void gpio_and_spi1_config()
{
	gpio_init_type gpio_init_struct;
	spi_init_type spi_init_struct;   

	/* enable gpioa periph clock */
  	crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE); 
    /* enable spi1 periph clock */
  	crm_periph_clock_enable(CRM_SPI1_PERIPH_CLOCK, TRUE);

	gpio_default_para_init(&gpio_init_struct);  
	
	gpio_bits_reset(GPIOA, GPIO_PINS_4);
  	gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
  	gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
	gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
	gpio_init_struct.gpio_pins = GPIO_PINS_4;
	gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
	gpio_init(GPIOA, &gpio_init_struct);
	  
	gpio_default_para_init(&gpio_init_struct);
	spi_default_para_init(&spi_init_struct);
	
	gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE5, GPIO_MUX_0);
 
	/* configure the SCK pin */
	gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
	gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
	gpio_init_struct.gpio_mode = GPIO_MOD_MUX;
	gpio_init_struct.gpio_pins = GPIO_PINS_5;
	gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
	gpio_init(GPIOA, &gpio_init_struct);

	 /* configure the MISO pin */
	 gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE6, GPIO_MUX_0);
	 gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
	 gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
	 gpio_init_struct.gpio_mode = GPIO_MODE_MUX; 
	 gpio_init_struct.gpio_pins = GPIO_PINS_6;
	 gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
	 gpio_init(GPIOA, &gpio_init_struct);
	
	
	 /* configure the MOSI pin */
	 gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE7, GPIO_MUX_0);
	 gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
	 gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
	 gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
	 gpio_init_struct.gpio_pins = GPIO_PINS_7;
	 gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
	 gpio_init(GPIOA, &gpio_init_struct);
	
	 /* configure param */
	 spi_init_struct.transmission_mode = SPI_TRANSMIT_FULL_DUPLEX;
	 spi_init_struct.master_slave_mode = SPI_MODE_MASTER;
	 spi_init_struct.frame_bit_num = SPI_FRAME_8BIT;
	 spi_init_struct.first_bit_transmission = SPI_FIRST_BIT_MSB;
	 spi_init_struct.mclk_freq_division = SPI_MCLK_DIV_8;
	 spi_init_struct.clock_polarity = SPI_CLOCK_POLARITY_HIGH;
	 spi_init_struct.clock_phase = SPI_CLOCK_PHASE_1EDGE;
	 spi_init_struct.cs_mode_selection = SPI_CS_SOFTWARE_MODE;
	 spi_init(SPI1, &spi_init_struct);
	
	 spi_enable(SPI1, TRUE);
}

3. 寄存器介绍

3.1 0x00 NOP寄存器

空指令寄存器基本都是给0x0000地址写入0用于等待一个时钟周期
在这里插入图片描述

3.2 0x01 DeviceID寄存器

这个寄存器仅可读,存储了芯片信息,精度、通道数量、硬件版本;例如读取TPC2190反馈上来的结果是0x0814,逐一对照进去,可以看出是16位的DAC输出芯片,8通道芯片,版本是0版本;
在这里插入图片描述

3.2 0x02 Sync寄存器

高八位为通道的使能位Broadcast,使能后写入值时,会立即更新;

后八位涉及到通道的更新模式选择:同步或异步
在这里插入图片描述

3.3 0x03 config寄存器

这个寄存器涉及到一些特殊功能的设置,错误诊断功能设置、CRC错误开启、FSDO(提前半个时钟周期传输数据)、内部通道断路设置,如果什么都不需要的话直接给配置寄存器写入0x00即可。
在这里插入图片描述

3.4 0x04 gain 寄存器

高7位都是工厂模式,默认给写0就好

往后一位是使能参考电压的增益选择,第二个字节的8位代表每个通道的增益选择

在这里插入图片描述

3.5 0x05 Trigger 寄存器

高11位保留,第十二位是使用同步模式时要配置为1,最后4位写入1010可以使芯片复位至默认状态;
在这里插入图片描述

3.6 0x06 Broadcast 寄存器

这个寄存器用于填入一个16位的数值,实际生效值与芯片的位数有关;在SYNC寄存器中,被设为同步输出的寄存器的值将会被这个寄存器强行刷新
在这里插入图片描述

3.7 0x07 Status 寄存器

供电电压不足时,该寄存器的值为1,否则为0;
在这里插入图片描述

3.8 0x08 - 0x0F DAC 寄存器

这个就是8个通道寄存器,往里面写值就好了‘
在这里插入图片描述

4. 关键函数实现

基本有下面几个函数就够玩了;按照这个配置使用下去,配套的动态电源芯片第三脚为测量mark点,向通道寄存器写入0xFFFF时,芯片输出电压约2.5v,写入0x7FFF时,芯片输出电压约1.25v;

4.1 SpiWriteAndReadBytes函数

uint8_t SpiWriteAndReadByte(uint8_t TxData)
{
    while(RESET == spi_i2s_flag_get(SPI1,SPI_I2S_TDBE_FLAG));
    spi_i2s_data_transmit(SPI1,(uint16_t)TxData);
    while(RESET == spi_i2s_flag_get(SPI1,SPI_I2S_RDBF_FLAG));
    return spi_i2s_data_receive(SPI1);
}

uint8_t *SpiWriteAndReadBytes(uint8_t *pTxData)
{    
	uint8_t *cmd;
    for(int i=0;i<3;i++)
    *cmd++ = SpiWriteAndReadByte(*pTxData++);
    return cmd;
}

4.2 TPC219_Software_Init函数

void TPC219_Software_Init()
{
    uint8_t cmd[3] = {0};

    // 0x02
    SPI_TPC219_CS_ON;    
    cmd[0] = 0x02;
    cmd[1] = 0xFF;
    cmd[2] = 0x00;
    SpiWriteandSendBytes(cmd);

	// 0x03
    cmd[0] = 0x03;
    cmd[1] = 0x00;
    cmd[2] = 0x00;
    SpiWriteandSendBytes(cmd);

    // 0x04
    cmd[0] = 0x04;
    cmd[1] = 0x00;
    cmd[2] = 0xFF;
    SpiWriteandSendBytes(cmd);
    SPI_TPC219_CS_OFF;
}

4.3 TPC219_Software_Init函数

void TPC219_WriteChannel(uint8_t ch,uint16_t value)
{
    uint8_t cmd[3];
    SPI_TPC219_CS_ON;
    cmd[0] = 0x08 + ch;  // WRITE DAC通道0 
    cmd[1] = (uint8_t)((value) >> 8 & 0xFF);
    cmd[2]  = (uint8_t)((value) & 0xFF);;
    SpiWriteandSendBytes(cmd);
    SPI_TPC219_CS_OFF;
}
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐