stm32驱动tm1638_芯片id是什么意思「建议收藏」

stm32驱动tm1638_芯片id是什么意思「建议收藏」一、_12位dac芯片

DAC芯片——TLV5636ID

   TLV5636是一个12位电压输出的DAC芯片,它的内部控制寄存器为16位,其中高4位是控制位,后12位是DAC的数据位。可以通过写入16位数据对芯片进行配置,

一、TLV5636ID介绍。

1.封装图

stm32驱动tm1638_芯片id是什么意思「建议收藏」

 2.各引脚意义

stm32驱动tm1638_芯片id是什么意思「建议收藏」

 (1)DIN:串行数据的输入管脚

(2)SCLK: DAC的时钟输入管脚

(3)CS:DAC芯片的片选信号,低电平有效。

(4)FS:同步信号。

(5)AGND:模拟地

(6)REF:DAC的外部参考电压输入,可通过编程选取内部基准还是外部基准电压。

(7)OUT:DAC芯片输出电压。电压计算为 V = 2 *(data)/(2*exp(12) = 4096)

(8) VDD:电源

3.内部结构电路

stm32驱动tm1638_芯片id是什么意思「建议收藏」

  可以看到芯片的输入为DIN、SCLK、\overline{CS} 、FS四个信号,在其内部有一个12位的数据锁存器,用于存放输入数据,另外2位的控制参考电压锁存器和2位功率和速度控制锁存器,共同构成16位输入数据。

4.TLV5636ID的时序图

stm32驱动tm1638_芯片id是什么意思「建议收藏」

stm32驱动tm1638_芯片id是什么意思「建议收藏」

   从数据手册上看,TLV5636ID的 最小时钟周期时间为50ns,也就是最大的时钟频率为20MHz,在编程的时候应该考虑到这个,一般SPI挂接在APB1或者APB2上,时钟周期拿STM32F103来说是72MHz/36MHz。通过对SPI设置分频系数来满足不超过20MHz的条件。

其中几个重要的时间如下:

a. TwH(FS):FS信号拉高持续时间,最低为半个时钟周期。FS信号非常重要,FS的下降沿告诉DAC芯片开始数据传输。所以在开启使能后必须要使得FS信号线产生一个下降沿信号

b.Tsu(D):数据准备时间。其实相当于数据稳定时间,这个时间最小为1/6个SPI时钟周期。

d.Tsu(H):数据有效时间。这段数据可以经SPI读取最小为1/10个SPI时钟周期。

e.Tsu(c16-cs):D0被采样后的第一个上升沿到CS拉高的最小时间,最小为1/10个SPI时钟周期。

5.串行接口

  TLV5636ID兼容3种接口如下:

stm32驱动tm1638_芯片id是什么意思「建议收藏」

各种接口协议下的连接如上图。

必须注意的是:TLV5636ID的工作必须拉低CS信号,其次要给FS信号一个下降沿,告诉数据传输开始,这样移位寄存器将数据移入(MSB,高位先移动,软件需设置成一样)锁存器中,在16个数据被采集完毕或者FS拉高后,数据将会输出到OUT端。 另外,如果是使用SPI接口时,需要对DAC芯片进行配置,所以写入的第一个数据是配置DAC的工作模式的,如果数据位宽是8位的,那么需要进行两次写操作,这个不必重复进行。配置完后可以进行正常的数据传输。

6.TLV5636ID的数据格式

stm32驱动tm1638_芯片id是什么意思「建议收藏」

stm32驱动tm1638_芯片id是什么意思「建议收藏」

二、软件编程

1.流程

    根据前面的数据手册,为了方便,先用软件模拟SPI进行数据传输,硬件的还没有试。

第一步:初始化TLV5636ID,软件模拟的话就初始化个人选择的4个端口,分别代表DAC的DIN,SCLK,CS和FS信号。我选择的分别是PB15,PB13,PB12,PA6。

第二步:配置 SPI的工作模式,写入数据0xD003(外部输入基准电压),使用内部的基准电压时写入数据0xD002或者0xD000。

第三步:写入需要写入的数据。(数据时一次性的,只为了测试DAC芯片的输出功能是否正常)

2.代码

//tlv5636.h

#ifndef __TLC5636_H__
#define __TLC5636_H__

#include “stm32f10x.h”

/* 定义GPIO端口 */
#define RCC_SCK     RCC_APB2Periph_GPIOB
#define PORT_SCK    GPIOB
#define PIN_SCK        GPIO_Pin_13

#define RCC_DIN     RCC_APB2Periph_GPIOB
#define PORT_DIN    GPIOB
#define PIN_DIN        GPIO_Pin_15

//#define RCC_DOUT     RCC_APB2Periph_GPIOB
//#define PORT_DOUT    GPIOB
//#define PIN_DOUT    GPIO_Pin_14

#define RCC_CS         RCC_APB2Periph_GPIOB
#define PORT_CS        GPIOB
#define PIN_CS        GPIO_Pin_12

#define RCC_FS    RCC_APB2Periph_GPIOA
#define PORT_FS   GPIOA
#define PIN_FS    GPIO_Pin_6

/* 定义口线置0和置1的宏 */
#define CS_0()        GPIO_ResetBits(PORT_CS, PIN_CS)
#define CS_1()        GPIO_SetBits(PORT_CS, PIN_CS)

#define SCK_0()        GPIO_ResetBits(PORT_SCK, PIN_SCK)
#define SCK_1()        GPIO_SetBits(PORT_SCK, PIN_SCK)

#define DI_0()        GPIO_ResetBits(PORT_DIN, PIN_DIN)
#define DI_1()        GPIO_SetBits(PORT_DIN, PIN_DIN)

#define FS_0()        GPIO_ResetBits(PORT_FS, PIN_FS)
#define FS_1()        GPIO_SetBits(PORT_FS, PIN_FS)

void tlc5636_Init(void);
void tlc5636_Send16Bit(uint16_t _data);
void tlc5636_Write2Byte(uint16_t data);
#endif
 

//tlv5636.c

#include “tlc5636.h” 
#include “SysTick.h”
#include “gpioport.h”

/*
*********************************************************************************************************
*    函 数 名: tlc5636_Init
*    功能说明: TLV5636的初始化
*    形    参: 无
*    返 回 值: 无
*********************************************************************************************************
*/ 
void tlc5636_Init(void)
{

    
    GPIO_InitTypeDef GPIO_InitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_SCK | RCC_DIN |RCC_FS| RCC_CS, ENABLE);
    
    /* 配置几个推挽输出IO */
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;        /* 设为输出口 */  
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 

    GPIO_InitStructure.GPIO_Pin = PIN_SCK;
    GPIO_Init(PORT_SCK, &GPIO_InitStructure);//时钟引脚初始化

    GPIO_InitStructure.GPIO_Pin = PIN_DIN;            /*对于主机而言为输入,对于从机而言为输出,因此此处配置成输出*/
    GPIO_Init(PORT_DIN, &GPIO_InitStructure);//MOSI引脚初始化

    GPIO_InitStructure.GPIO_Pin = PIN_CS; 
    GPIO_Init(PORT_CS, &GPIO_InitStructure);//CS端初始化
    
    GPIO_InitStructure.GPIO_Pin = PIN_FS;
    GPIO_Init(PORT_FS, &GPIO_InitStructure);//FS端初始化
    
    SCK_0();    CS_1();        FS_0();//空闲状态时,SCLK置0,CS置1,FS置0

/*
*********************************************************************************************************
*    函 数 名: TLC5636_Send16Bit
*    功能说明: 向TLV5636总线发送16个bit数据。
*    形    参: _data : 数据
*    返 回 值: 无
*********************************************************************************************************
*/ 
void tlc5636_Send16Bit(uint16_t _data)
{

    uint8_t i; 
    
    FS_1();
    delay_us(12);
    FS_0();
    
    
    for(i = 0; i < 16; i++)
    {

        if (_data & 0x8000)
        {

            DI_1();
        }
        else
        {

            DI_0();
        }
        SCK_1();
        _data <<= 1;
        delay_us(10);
    
        SCK_0();    
        delay_us(10);        
    }
}

void tlc5636_Write2Byte(uint16_t _data)
{

    CS_0();
    tlc5636_Send16Bit(_data);
    CS_1();
//    FS_1();//这条不能写,因为FS = 1,意味着数据传输完成,所以DAC芯片的输出测不到电压值。切记
    
}

//main.c

#include “gpioport.h”
#include “system.h”
#include “SysTick.h”
#include “tlc5636.h” 

int main(void)
{

    
    RCC_HSE_Config(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);
    SysTick_Init(72);
    LED1_Init();
    
  tlc5636_Init();
    tlc5636_Write2Byte(0xD003);//设置DAC得参考电压和工作模式
    
    
    while(1)
    {

        LED1 = 0;
      delay_s(1);
        LED1 = 1;
        delay_s(1);
        
      tlc5636_Write2Byte(0x4FFF);
        
    }
    
}

#include “system.h”  系统位带定义头文件

#include “SysTick” 系统定时器的头文件

至此,TLV5636软件模拟SPI驱动DAC工作程序完成

三、总结问题

1.数据手册的时序很重要以及DAC芯片的工作原理。

2.配置时的数据可以不放入到循环中,而写入的数据时,函数必须放大循环内部,让DAC芯片不断的去读取,这样输出端才能输出电压。之前老是没有电压,可能是DAC输出的电压输出后就清0了,根据他的工作原理。时间很短,所以不能测量,所以需要不停的写入。(这块后续再理解理解,感觉这样解释很勉强)

后续:硬件SPI驱动TLC5636工作

    经过调试,之前不能写FS = 1的问题的理解是错误的,可以写。在使用SPI驱动时,出现CS拉高后不能测出电压的情况,经过调试,知道是SPI在发送数据的时候,指令SPI2_WriteByte(0xD003)仅仅是芯片给SPI的一个命令,给完芯片继续执行下一条指令,自己的程序没有考虑到SPI总线的数据缓冲器发送完16位数据所需要的时间,所以有可能没发送完就被CS_1()给断掉了。后续加入一个延时就可以了。

1.代码

//main.c

#include “system.h”
#include “gpioport.h”
#include “SysTick.h”
#include “spi.h”
#include “tlc5636.h”

int main(void)
{

    
    RCC_HSE_Config(RCC_PLLSource_HSE_Div2,RCC_PLLMul_2);//16MHz系统时钟
    SysTick_Init(8);//系统定时器初始化
    LED1_Init();//LED1初始化
    
    SPI2_Init();//初始化SPI2
    TLC5636_Init();//初始化DAC芯片
    
    while(1)
    {

        
        LED1 = 1;
        delay_s(1);//延时1s
        LED1 = 0;
        delay_s(1);
        TLC5636_Write16Bit(0x48ff);
        
        
    }

    
    
 

//tlc5636.h

#include “tlc5636.h”
#include “SysTick.h”
#include “gpioport.h”

void TLC5636_Init(void)
{

    
    CS_0();
    delay_us(10);
    
    while( SCLK != 0 );//SCLK为0退出
    FS_1();
    delay_us(20);
    FS_0();
    
    SPI2_WriteByte(0xD003);//配置DAC芯片
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);//等待发送区空  
    delay_us(1000);
    CS_1();
    FS_1();
    
    
    
}

void TLC5636_Write16Bit(u16 data)

{

    CS_0();//CS拉低,开启DAC
  delay_us(10);//延时10us
    
    while( SCLK != 0 );//判断SCLK为空闲状态
    FS_1();
    delay_us(20);
    FS_0();
    
    SPI2_WriteByte(data);//配置DAC芯片
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);//等待发送区空  
    delay_us(1000);//SPI时钟周期为32us,16位数据移位完成最少512us,延时1000us
    CS_1();//CS拉高
    FS_1();//FS拉高
    
    
    
}

//tlc5636.c

#include “tlc5636.h”
#include “SysTick.h”
#include “gpioport.h”

void TLC5636_Init(void)
{

    
    CS_0();
    delay_us(10);
    
    while( SCLK != 0 );//SCLK为0退出
    FS_1();
    delay_us(20);
    FS_0();
    
    SPI2_WriteByte(0xD003);//配置DAC芯片
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);//等待发送区空  
    delay_us(1000);
    CS_1();
    FS_1();
    
    
    
}

void TLC5636_Write16Bit(u16 data)

{

    CS_0();//CS拉低,开启DA
  delay_us(10);//延时10us
    
    while( SCLK != 0 );//判断SCLK为空闲状态
    FS_1();
    delay_us(20);
    FS_0();
    
    SPI2_WriteByte(data);//配置DAC芯片
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);//等待发送区空  
    delay_us(1000);//SPI时钟周期为32us,16位数据移位完成最少512us,延时1000us
    CS_1();//CS拉高
    FS_1();//FS拉高
    
    
    
}

//spi.h

#ifndef _spi_H
#define _spi_H

#include “system.h”

/* 定义GPIO端口 */
#define RCC_SCK     RCC_APB2Periph_GPIOB
#define PORT_SCK    GPIOB
#define PIN_SCK        GPIO_Pin_13

#define RCC_DIN     RCC_APB2Periph_GPIOB
#define PORT_DIN    GPIOB
#define PIN_DIN        GPIO_Pin_15

//#define RCC_DOUT     RCC_APB2Periph_GPIOB
//#define PORT_DOUT    GPIOB
//#define PIN_DOUT    GPIO_Pin_14

#define RCC_CS         RCC_APB2Periph_GPIOB
#define PORT_CS        GPIOB
#define PIN_CS        GPIO_Pin_12

#define RCC_FS    RCC_APB2Periph_GPIOA
#define PORT_FS   GPIOA
#define PIN_FS    GPIO_Pin_6

/* 定义口线置0和置1的宏 */
#define CS_0()        GPIO_ResetBits(PORT_CS, PIN_CS)
#define CS_1()        GPIO_SetBits(PORT_CS, PIN_CS)

#define SCK_0()        GPIO_ResetBits(PORT_SCK, PIN_SCK)
#define SCK_1()        GPIO_SetBits(PORT_SCK, PIN_SCK)

#define DI_0()        GPIO_ResetBits(PORT_DIN, PIN_DIN)
#define DI_1()        GPIO_SetBits(PORT_DIN, PIN_DIN)

#define FS_0()        GPIO_ResetBits(PORT_FS, PIN_FS)
#define FS_1()        GPIO_SetBits(PORT_FS, PIN_FS)

void SPI2_Init(void);             //初始化SPI2口
void SPI2_SetSpeed(u8 SpeedSet); //设置SPI2速度   
//u16 SPI2_ReadWriteByte(u16 TxData);//SPI2总线读写一个字节
void SPI2_WriteByte(u16 data);
#endif

 

//spi.c

#include “spi.h”
#include “gpioport.h” 

//SPI口初始化
void SPI2_Init(void)
{

    GPIO_InitTypeDef  GPIO_InitStructure;
    SPI_InitTypeDef  SPI_InitStructure;
    
    /* SPI的IO口和SPI外设打开时钟 */
  RCC_APB2PeriphClockCmd(    RCC_SCK | RCC_DIN | RCC_FS | RCC_CS, ENABLE );
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
    
    //配置SPI的外设端口
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 

    GPIO_InitStructure.GPIO_Pin = PIN_SCK;
    GPIO_Init(PORT_SCK, &GPIO_InitStructure);//时钟引脚初始化

    GPIO_InitStructure.GPIO_Pin = PIN_DIN;        
    GPIO_Init(PORT_DIN, &GPIO_InitStructure);//数据输出引脚初始化

    //配置CS,FS端口
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;    
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
    GPIO_InitStructure.GPIO_Pin = PIN_CS; 
    GPIO_Init(PORT_CS, &GPIO_InitStructure);//CS端初始化
    
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;    
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
    GPIO_InitStructure.GPIO_Pin = PIN_FS;
    GPIO_Init(PORT_FS, &GPIO_InitStructure);//FS端初始化

  //配置SPI的工作模式
    SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;  //SPI设置为单线传输模式,不需要读取DAC数据
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;        //设置SPI工作模式:设置为主SPI
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;        //设置SPI的数据大小:SPI发送接收16位帧结构
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;        //串行同步时钟的空闲状态为低电平,保持与TLC5636的时序一致
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;    //串行同步时钟的下降沿数据被采样
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;        //内部NSS信号有SSI位控制
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;//波特率预分频值为256
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;    //数据传输从MSB位开始,与TLC5636的规定一致
    SPI_InitStructure.SPI_CRCPolynomial = 7;    //CRC值计算的多项式
    SPI_Init(SPI2, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
    
    SPI_Cmd(SPI2, ENABLE); //使能SPI外设
    CS_1();//取消片选
    FS_0();//拉高同步信号
    
    SPI2_WriteByte(0xffff);//启动传输    

}

//SPI2速度设置函数
void SPI2_SetSpeed(u8 SPI_BaudRatePrescaler)
{

    SPI2->CR1&=0XFFC7;//位3-5清零,用来设置波特率
    SPI2->CR1|=SPI_BaudRatePrescaler;    //设置SPI速度 
    SPI_Cmd(SPI2,ENABLE); //使能SPI2

void SPI2_WriteByte(u16 data)
{                      

    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);//等待发送区空  
    SPI_I2S_SendData(SPI2,data);
//    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET); //等待接收完一个byte  
//    return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据                
}

 

今天的文章stm32驱动tm1638_芯片id是什么意思「建议收藏」分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/89521.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注