STM32之LTC2656驱动

驱动如下:


#include <stdint.h>
#include <math.h>
#include "LTC2656.h"
#include "BSP.h"
#include "SysConfig.h"
#include "global.h"

#define  Debug_SPI      0

#define LTC2656_NUM_0    0U
#define LTC2656_NUM_1    1U
#define LTC2656_NUM_2    2U

// DAC Reference State
// Could have been zero or 1, this allows you to use the
// variable "reference_mode" as the command argument to a write
#define REF_INTERNAL  LTC2656_CMD_INTERNAL_REFERENCE   //!< Stored reference state is Internal
#define REF_EXTERNAL  LTC2656_CMD_EXTERNAL_REFERENCE   //!< Stored reference state is External

// Global variables
static uint8  shift_count = 0;        //!< The data align shift count. For 16-bit=0, for 12-bits=4
static uint8  reference_mode;         //!< Tells whether to set internal or external reference


// Global calibration variables
static int16 LTC2656_offset[9];      //!< DAC offset - index 8 for "all DACs"
static float LTC2656_lsb[9];         //!< The LTC2656 lsb - index 8 for "all DACs"

//! Lookup table for DAC address. Allows the "All DACs" address to be indexed right after DAC D in loops.
//! This technique is very useful for devices with non-monotonic channel addresses.
const uint8 address_map[9] = {LTC2656_DAC_A, LTC2656_DAC_B, LTC2656_DAC_C, LTC2656_DAC_D, LTC2656_DAC_E,
                              LTC2656_DAC_F, LTC2656_DAC_G, LTC2656_DAC_H,LTC2656_DAC_ALL
                             };  //<! Map entered option 0..2 to DAC address

typedef union LT_union_int16_2bytes
{
  int16  LT_int16;    
  uint16 LT_uint16;   
  uint8  LT_byte[2];  
}U_LT_Write;
  

static void LTC2656_1_Operation(const uint8* p_u8WriteBuf,  uint8 *p_u8ReadBuf, uint8 u8Size);
static void LTC2656_2_Operation(const uint8* p_u8WriteBuf,  uint8 *p_u8ReadBuf, uint8 u8Size);
static void LTC2656_3_Operation(const uint8* p_u8WriteBuf,  uint8 *p_u8ReadBuf, uint8 u8Size);
static void LTC2656_write(uint8 LTC2656_Num, uint8 dac_command, uint8 dac_address, uint16 dac_code);
static uint16 LTC2656_voltage_to_code(float dac_voltage, float LTC2656_lsb, int16_t LTC2656_offset);
static void LTC2656_calibrate(uint16 dac_code1, uint16 dac_code2, float voltage1, float voltage2, float *LTC2656_lsb, int16_t *LTC2656_offset);

/*
*******************************************************************************
功能:初始化
参数: 
      LTC2656_Num    LTC2656序号
返回: 无
*******************************************************************************
*/ 
void LTC2656_Init(uint32 u32_hard_version, uint8 LTC2656_Num)
{
	uint8 i;
  f32 dac_count = 0.0;  /* The number of codes, 4096 for 12 bits, 65536 for 16 bits*/
  f32 full_scale = 0.0; /* To avoid confusion - in internal ref mode, FS=Vref, in ext mode, FS=2*Vref*/

	/* 设置外部参考电压模式*/
  reference_mode = REF_EXTERNAL; /* Redundant if already set*/
  /* Write the reference mode to the DAC right away*/
  LTC2656_write(LTC2656_Num, reference_mode, 0x0F, 0x0000);    

  if(u32_hard_version <= DEFAULT_HARDWARE_VERSION)
  {
    /* V1.0.0.0硬件版本,LTC2656基准为5.0V */
    full_scale = 5.0F;
  }
  else
  {
    /* V1.0.0.0之后硬件版本,LTC2656基准为4.096V */
	  full_scale = 4.096F;
  }
  /* Set up default values, shift count, DAC count*/
	/* LTC2656CUF-H12, 12-bits, 4.096V full scale*/
	shift_count = 4U;
	dac_count = 4096U;

  for (i = 0; i <= 8; i++)
  {
    LTC2656_offset[i] = 0;
    LTC2656_lsb[i] = full_scale / dac_count;
  }
}

//! Power down DAC
void LTC2656_power_down_dac(uint8 LTC2656_Num, uint8 selected_dac)
{
  // Power down DAC
  LTC2656_write(LTC2656_Num, LTC2656_CMD_POWER_DOWN, address_map[selected_dac], 0x0000);
}

//!Write data to DAC register (which updates output immediately)
void LTC2656_write_and_update_dac(uint8 LTC2656_Num, uint8 selected_dac, f32 dac_voltage)
{
  uint16_t dac_code;
	
  dac_code = LTC2656_voltage_to_code(dac_voltage, LTC2656_lsb[selected_dac], LTC2656_offset[selected_dac]);
  if(dac_code >= 4096)
  {
    dac_code = 4095;
  }
  
  LTC2656_write(LTC2656_Num, LTC2656_CMD_WRITE_UPDATE, address_map[selected_dac], dac_code << shift_count);
}

//! Write data to input register, but do not update DAC output
void LTC2656_write_to_input_register(uint8 LTC2656_Num, uint8 selected_dac, float dac_voltage)
{
  uint16_t dac_code;

  dac_code = LTC2656_voltage_to_code(dac_voltage, LTC2656_lsb[selected_dac], LTC2656_offset[selected_dac]);
  if(dac_code >= 4096)
  {
    dac_code = 4095;
  }
  
  LTC2656_write(LTC2656_Num, LTC2656_CMD_WRITE, address_map[selected_dac], dac_code << shift_count);
}

//! Update DAC with data that is stored in input register, power up if sleeping
 void LTC2656_update_power_up_dac(uint8 LTC2656_Num, uint8 selected_dac)
{
  // Update DAC
  LTC2656_write(LTC2656_Num, LTC2656_CMD_UPDATE, address_map[selected_dac], 0x0000);
}


/*
*******************************************************************************
功能:读写操作
参数: 
      p_u8WriteBuf    要写入的数据
      p_u8ReadBuf     读出的数据
      u8Size         要写入数据的长度
返回: 无
*******************************************************************************
*/ 
static void LTC2656_1_Operation(const uint8* p_u8WriteBuf,  uint8 *p_u8ReadBuf, uint8 u8Size)
{
  uint8 u8Index = 0U;
  uint8 u8WriteData = 0U;
  uint8 u8ReadData  = 0U;

  SPI1_CS_LOW();  
  for(u8Index = 0U; u8Index < u8Size; u8Index++)
  {
    u8WriteData = *(p_u8WriteBuf + u8Index);
    u8ReadData  = SPI1_u8ReadWriteByte(u8WriteData);            
    *(p_u8ReadBuf + u8Index) = u8ReadData;
  } 
  SPI1_CS_HIGH();  
}

/*
*******************************************************************************
功能:读写操作
参数: 
      p_u8WriteBuf    要写入的数据
      p_u8ReadBuf     读出的数据
      u8Size         要写入数据的长度
返回: 无
*******************************************************************************
*/ 
static void LTC2656_2_Operation(const uint8* p_u8WriteBuf,  uint8 *p_u8ReadBuf, uint8 u8Size)
{
  uint8 u8Index = 0U;
  uint8 u8WriteData = 0U;
  uint8 u8ReadData  = 0U;

  SPI2_CS_LOW();
  for(u8Index = 0U; u8Index < u8Size; u8Index++)
  {
    u8WriteData = *(p_u8WriteBuf + u8Index);
    u8ReadData  = SPI2_u8ReadWriteByte(u8WriteData);            
    *(p_u8ReadBuf + u8Index) = u8ReadData;
  } 
  SPI2_CS_HIGH();    
}

/*
*******************************************************************************
功能:读写操作
参数: 
      p_u8WriteBuf    要写入的数据
      p_u8ReadBuf     读出的数据
      u8Size         要写入数据的长度
返回: 无
*******************************************************************************
*/ 
static void LTC2656_3_Operation(const uint8* p_u8WriteBuf,  uint8 *p_u8ReadBuf, uint8 u8Size)
{
  uint8 u8Index = 0U;
  uint8 u8WriteData = 0U;
  uint8 u8ReadData  = 0U;

  SPI2_CS_HIGH();    
  for(u8Index = 0U; u8Index < u8Size; u8Index++)
  {
    u8WriteData = *(p_u8WriteBuf + u8Index);
    u8ReadData  = SPI3_u8ReadWriteByte(u8WriteData);            
    *(p_u8ReadBuf + u8Index) = u8ReadData;
  } 
  SPI2_CS_LOW();
}

static void LTC2656_write(uint8 LTC2656_Num, uint8 dac_command, uint8 dac_address, uint16 dac_code)
// Write the 16-bit dac_code to the LTC2656
{
  uint8 data_array[3], rx_array[3];
  U_LT_Write data;

  data.LT_uint16 = dac_code;

  data_array[0] = dac_command | dac_address;
  data_array[1] = data.LT_byte[1];
  data_array[2] = data.LT_byte[0];

  #if  Debug_SPI
  {
    uint8 u8Index = 0U;
    uint8 u8WriteData = 0U;
    uint8 u8ReadData  = 0U;
      
    SPI2_CS_LOW();
    for(u8Index = 0U; u8Index < 3; u8Index++)
    {
      u8WriteData = *(data_array + u8Index);
      u8ReadData  = SPI2_u8ReadWriteByte(u8WriteData);            
      *(rx_array + u8Index) = u8ReadData;
    } 
    SPI2_CS_HIGH();
  }
  #else
	if(LTC2656_NUM_0 == LTC2656_Num)
	{
		LTC2656_1_Operation(data_array, rx_array, (uint8)3);
	}
	else if(LTC2656_NUM_1 == LTC2656_Num)
	{
		LTC2656_2_Operation(data_array, rx_array, (uint8)3);		
	}
  else if(LTC2656_NUM_2 == LTC2656_Num)
  {
		LTC2656_3_Operation(data_array, rx_array, (uint8)3);		    
  }
  else
  {
    /* nothing*/
  }
  
  #endif  
}

static uint16 LTC2656_voltage_to_code(float dac_voltage, float LTC2656_lsb, int16_t LTC2656_offset)
// Calculate a LTC2656 DAC code given the desired output voltage and DAC address (0-7)
{
  int32_t dac_code;
  float float_code;
  float_code = dac_voltage / LTC2656_lsb;                                                             //! 1) Calculate the DAC code
  float_code = (float_code > (floor(float_code) + 0.5)) ? ceil(float_code) : floor(float_code);       //! 2) Round
  dac_code =(int32_t)float_code - LTC2656_offset;                                                     //! 3) Subtract offset
  if (dac_code < 0)                                                                                   //! 4) If DAC code < 0, Then DAC code = 0
    dac_code = 0;
  return ((uint16_t)dac_code);                                                                        //! 5) Cast DAC code as uint16_t
}

float LTC2656_code_to_voltage(uint16_t dac_code, float LTC2656_lsb, int16_t LTC2656_offset)
// Calculate the LTC2656 DAC output voltage given the DAC code and DAC address (0-7)
{
  float dac_voltage;
  dac_voltage = ((float)(dac_code + LTC2656_offset)* LTC2656_lsb);                                    //! 1) Calculates the dac_voltage
  return (dac_voltage);
}

/* 以下为修正用函数*/
static void LTC2656_calibrate(uint16 dac_code1, uint16 dac_code2, float voltage1, float voltage2, float *LTC2656_lsb, int16_t *LTC2656_offset)
// Calculate the LTC2656 offset and LSB voltage given two measured voltages and their corresponding codes
{
  float temp_offset;
  *LTC2656_lsb = (voltage2 - voltage1) / ((float) (dac_code2 - dac_code1));                           //! 1) Calculate the LSB
  temp_offset = voltage1/(*LTC2656_lsb) - (float)dac_code1;                                           //! 2) Calculate the offset
  temp_offset = (temp_offset > (floor(temp_offset) + 0.5)) ? ceil(temp_offset) : floor(temp_offset);  //! 3) Round offset
  *LTC2656_offset = (int16_t)temp_offset;                                                             //! 4) Cast as int16_t
}

//! Calibrate all DACs by measuring two known outputs
// Calibrate the selected DAC using a voltmeter. The routine does a linear curve fit given two data points.
void calibrate_dacs(uint8 LTC2656_Num)
{
  // Calibrate the DACs using a multimeter
  uint8 index;
  uint16 code1 = 0x0200;                            //! Calibration code 1
  uint16 code2 = 0xFFFF;                            //! Calibration code 2
  float voltage1;                                   //! Calibration voltage 1
  float voltage2;                                   //! Calibration voltage 2
	
  for (index = 0; index < 8; index++)
  {
		// Left align 12-bit code1 to 16 bits & write to DAC
		LTC2656_write(LTC2656_Num, LTC2656_CMD_WRITE_UPDATE, index, code1 << shift_count);

		/* 用万用表读出测量值*/
	  //  voltage1 = read_float();

		// Left align 12-bit code2 to 16 bits & write to DAC
		LTC2656_write(LTC2656_Num, LTC2656_CMD_WRITE_UPDATE, index, code2 << shift_count);

		/* 用万用表读出测量值*/
	  //  voltage2 = read_float();

		LTC2656_calibrate(code1, code2, voltage1, voltage2, &LTC2656_lsb[index], &LTC2656_offset[index]);
  }
}

头文件如下:


#ifndef LTC2656_H
#define LTC2656_H

#include "SPI.h"

//! @name LTC2656 Command Codes
//! @{
//! OR'd together with the DAC address to form the command byte
#define  LTC2656_CMD_WRITE               0x00  //!< Write to input register n
#define  LTC2656_CMD_UPDATE              0x10  //!< Update (power up) DAC register n
#define  LTC2656_CMD_WRITE_UPDATE_ALL    0x20  //!< Write to input register n, update (power up) all
#define  LTC2656_CMD_WRITE_UPDATE        0x30  //!< Write to input register n, update (power up) all
#define  LTC2656_CMD_POWER_DOWN          0x40  //!< Power down n
#define  LTC2656_CMD_POWER_DOWN_ALL      0x50  //!< Power down chip (all DACs and reference)
#define  LTC2656_CMD_INTERNAL_REFERENCE  0x60  //!< Select internal reference (power up reference)
#define  LTC2656_CMD_EXTERNAL_REFERENCE  0x70  //!< Select external reference (power down internal reference)
#define  LTC2656_CMD_NO_OPERATION        0xF0  //!< No operation
//! @}

//! @name LTC2656 DAC Addresses
//! @{
//! Which DAC to operate on
#define  LTC2656_DAC_A     0x00
#define  LTC2656_DAC_B     0x01
#define  LTC2656_DAC_C     0x02
#define  LTC2656_DAC_D     0x03
#define  LTC2656_DAC_E     0x04
#define  LTC2656_DAC_F     0x05
#define  LTC2656_DAC_G     0x06
#define  LTC2656_DAC_H     0x07
#define  LTC2656_DAC_ALL   0x0F
//! @}

/*
*******************************************************************************
功能:初始化
参数: 
      LTC2656_Num    LTC2656序号
返回: 无
*******************************************************************************
*/ 
extern void LTC2656_Init(uint32 u32_hard_version, uint8 LTC2656_Num);
	
//! Power down DAC
extern void LTC2656_power_down_dac(uint8 LTC2656_Num, uint8 selected_dac);

//!Write data to DAC register (which updates output immediately)
extern void LTC2656_write_and_update_dac(uint8 LTC2656_Num, uint8 selected_dac, float dac_voltage);


//! Write data to input register, but do not update DAC output
extern void LTC2656_write_to_input_register(uint8 LTC2656_Num, uint8 selected_dac, float dac_voltage);


//! Update DAC with data that is stored in input register, power up if sleeping
extern void LTC2656_update_power_up_dac(uint8 LTC2656_Num, uint8 selected_dac);


#endif  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值