ad7705应用经验总结

网络整理 2017-11-15 18:59:05 0评
tag: ad7705

  AD7705为完整16位低成本、Σ-Δ型ADC。采用SP IQ SPI兼容的三线串行接口,能够方便地与各种微控制器和DSP连接,也比并行接口方式大大节省了CPU的 I O口。本文主要以ad7705应用经验及应用所需注意的事项为中心而展开的讨论。

  ad7705应用经验总结

  1.时序注意要点:数字接口迷失的时候可以通过ADIN输入持续32个脉冲周期(DCLK)以上的高电平将复位AD7705的数字接口,复位之后要等待500us以上才能访问AD7705芯片,这种复位方式不会影响AD7705内部的任何寄存器,所有的寄存器将保持复位之前的内容,但所有的寄存器在数字接口迷失的状态下内容是不确定的,因此强烈建议在复位之后重新设置AD7705内部所有的寄存器,防止错误。而芯片管脚RESET的复位将使片内所有的寄存器恢复到上电的默认值。时钟输入信号DCLK是一种施密特出发信号,能够适应光耦合器的慢速边沿,其他数字输入信号的上升和下降时间不应超过1us。

  2.AD7705时钟大于2M时,时钟设置寄存器的CLK位应置1,小于2M时应置0。DCLK的脉冲宽度要满足最小的脉宽要求。在时钟DCLK下降之后的低电平期间读取数据ADOUT。在时钟DCLK的低电平期间设置要写入数据ADIN,然后在DCLK的上升沿写入到7705。写入数据以及读取数据的时钟DCLK的数目要与(被写入或被读取的寄存器)的位数长度一致,多于或少于(寄存器位长度)的时钟DCLK数目都将导致操作错误。在两次写操作之间,ADIN应最好保持在高电平:因为任何(读或写)操作都必须从写通信寄存器开始,而且写入通信寄存器的8个位中的第1位必须为0,后续的位才能被写入到通信寄存器。所以当ADIN为0的时候,万一时钟DCLK受到干扰导致0写入通信寄存器,AD7705会误认为是写通信寄存器的操作开始而等待后续的7位位串,发生这种干扰之后会导致AD7705的数字接口迷失,从而导致内部寄存器的内容也许会变得未知状态。此外,时钟信号DCLK在两次操作AD7705之间要保持高电平。即:在不访问AD7705的空闲时刻,或者两次操作之间的空闲时刻,ADIN、DCLK都最好保持高电平为最可靠。

  3.DRDY信号为数据AD转换完成的指示信号,低电平期间表示AD转换完成,可以读取数据寄存器的内容,高电平期间表示AD转换正在进行,这时不能访问数据寄存器。对于系统校准和内部校准也一样,低电平期间表示校准完成,可以读取校准寄存器的内容,高电平期间表示校准正在进行,这时不能访问校准寄存器。违反这些规定的操作,结果时未知的。此外程序中千万不能把DRDY的逻辑搞反,否则结果不可预料。

  4.不管是校准还是数据AD转换,数字滤波器同步位FSYNC都要置为0,这样AD7705的校准或者数据AD转换工作才能进行,否则校准和AD转换不会进行,DRDY信号也不会变低。当FSYNC=0时,在校准或AD转换结束后DRDY信号将变低,此时可以读取校准系数或者数据寄存器。

  5.采用非缓冲模式时,AD7705模拟输入前端的电阻电容的变化对AD转换精度影响很大。若系统工作时的信号源、温度环境、器件参数变化很大,导致AD7705模拟输入前端电路的参数跟系统校准时的参数不一致,误差会非常大。缓冲模式能解决这种问题,当使能缓冲模式时,AD7705会在模拟输入端和AD转换器之间接入一个缓冲器Buffer,这样AD7705就能适应模拟输入前端信号源的大阻抗、器件参数(电阻电容)的变化、温度环境的变化等各种与系统校准时的不一致情况(即器件工作条件的变化)。所以,AD7705的校准和正常工作最好都要在缓冲模式下进行。

  6.电压输入范围:对于非缓冲模式,模拟输入信号范围是GND-30mV至VDD+30mV之间。对于缓冲模式,模拟输入信号范围是GND+50mV至VDD-1.5V之间。

  7.非缓冲模式、单极性、增益为GAIN:此时AD7705的反相输入端VIN-的范围是GND-30mV至VDD+30mV-VREF/GAIN之间,其中VREF为AD7705的参考电压。正相输入端VIN+的范围是V-至V-+VREF/GAIN。如右图,即V+和V-都必须大于GND小于VDD,同时还要考虑单极性的输入范围,即V-还必须小于VDD+30mV-VREF/GAIN,才不至于模拟输入为V+max=V-+VREF/GAIN时大于VDD+30mV。

  8.非缓冲、双极性、增益为GAIN:此时V+和V-都必须大于GAN小于VDD,V-还必须小于VDD+30V-VREF/GAIN,这样输入V+max=V-+VREF/GAIN不至于大于VDD+30mV。V-还必须大于GND-30mV +VREF/GAIN,才不至于输入V+min=V――VREF/GAIN时小于GND-30mV。正相输入端VIN+的正信号输入范围是V-至V-+VREF/GAIN,正相输入端VIN+的负信号输入范围是V-至V--REF/GAIN。

  9.缓冲模式、单极性、增益为GAIN:此时AD7705的反相输入端VIN-的范围是【GND+50mV】至【VDD-1.5V-VREF/GAIN】之间,其中VREF为AD7705的参考电压。正相输入端VIN+的范围是【V-】至【V-+VREF/GAIN】。如右图,即V+和V-都必须大于GND+50mV小于VDD-1.5V,同时还要考虑单极性的输入范围,即V-还必须小于VDD-1.5V-VREF/GAIN,才不至于输入V+max=【V-+VREF/GAIN】时大于VDD-1.5V。

  10.缓冲模式、双极性、增益为GAIN:此时AD7705的反相输入端VIN-的范围是【GND+50mV+VREF/GAIN】至【VDD-1.5V-VREF/GAIN】之间,这样才不至于输入VIN+max=【V-+VREF/GAIN】时导致VIN+大于VDD-1.5V、输入VIN+min=【V――VREF/GAIN】时导致VIN+小于GND+50mV。其中VREF为AD7705的参考电压。正相输入端VIN+的正信号输入范围是【V-】至【V-+VREF/GAIN】,正相输入端VIN+的负信号输入范围是【V-】至【V--REF/GAIN】。

  AD7705应用注意要点和程序

  (1) DRDY逻辑不要搞反,高电平时等待转换状态,低电平为可以读取转换数据

  (2) 系统校准时输入信号要大于所选量程的4/5,否则校准不到32767。

  (3)校准时要等待一定的时间,读取数据也一样,不能超过转换速率。

  (4) 一般的应用只要内部校准,这个很简单,只要初始化就可以。如果测量范围不是芯片的范围,可以通过系统校准来实现,满量程校准电压要大于量程的4/5

  #include 《util/delay.h》

  #include 《avr/eeprom.h》

  #include “ad7705.h”

  #include “main.h”

  #include “crc16.h”

  #include “Usart.h”

  /针对四个量程的设置寄存器的设置内容

  //(1)对于单极性V级别输入0-5V、0-20mA、0-10V这三个量程,输入范围为0-2V,无极性,增益为1,缓冲模式--0-2V

  //(2)对于双极性V级别输入+-2.5V、+-5V这两个量程,输入范围为+-1V,双极性,增益为2,缓冲模式--+-2V

  //(3)对于双精度mV级别输入+-500mV,增益为4,双极性,缓冲模式--+-2V

  //(4)对双精度mV级别+-50mV,增益为32,双极性,缓冲模式--+-1.6V

  //------MD1(0) MD0(0) G2(0) G1(0) G0(0) B/U(0) BUF(0) FSYNC(0)

  --------------------------//

  const unsigned char text_of_setup[4]={0X04,0X08,0X10,0X28}; //非缓冲模式,数字滤波同步

  //const unsigned char text_of_setup[4]={0X06,0X0A,0X12,0X2A}; //缓冲模式,数字滤波同步

  extern volatile unsigned char command[7]; //校准命令全局数组

  extern volatile unsigned char scale; //记录系统量程

  extern volatile unsigned char NO_CALI_TYPE; //未校准类型

  extern volatile unsigned long int ZS,GS; //当前量程的校准系数

  extern volatile unsigned char time_count; //超时标志

  //----------------------------------------------------------------------------

  //函数:reset_AD7705

  //功能:AD7705串行接口失步后将其复位。复位后要延时500us再访问

  //参数:无

  //返回:无

  //变量:无

  //备注:无

  //----------------------------------------------------------------------------

  void reset_AD7705(void)

  {

  unsigned char i;

  AD_DIN1;

  for( i=0; i《36; i++ )

  {

  AD_CLK0;

  asm(“nop”);

  asm(“nop”);

  asm(“nop”);

  AD_CLK1;

  asm(“nop”);

  asm(“nop”);

  asm(“nop”);

  }

  _delay_ms(1);

  }

  //------------------------------------------------------------------------------------------

  //函数:read_AD7705_byte

  //功能:从AD7705读一个字节的数据

  //参数:无

  //返回:读到的一字节数据

  //变量:无

  //备注:无

  //------------------------------------------------------------------------------------------

  unsigned char read_AD7705_byte(void)

  {

  unsigned char data = 0;

  unsigned char i = 0;

  for( i=0; i《8; i++ )

  {

  data 《《= 1;

  AD_CLK0;

  asm(“nop”);

  asm(“nop”);

  asm(“nop”);

  if(AD_DOUT)

  {

  data++;

  }

  AD_CLK1;

  asm(“nop”);

  asm(“nop”);

  asm(“nop”);

  }

  return data;

  }

  //------------------------------------------------------------------------------------------

  //函数:read_AD7705_word

  //功能:从AD7705读一个字的数据,共16bit

  //参数:无

  //返回:读到的一字节数据

  //变量:无

  //备注:无

  //------------------------------------------------------------------------------------------

  unsigned int read_AD7705_word(void)

  {

  unsigned int data = 0;

  unsigned char i = 0;

  for( i=0; i《16; i++ )

  {

  data 《《= 1;

  AD_CLK0;

  asm(“nop”);

  asm(“nop”);

  asm(“nop”);

  if(AD_DOUT)

  {

  data++;

  }

  AD_CLK1;

  asm(“nop”);

  asm(“nop”);

  asm(“nop”);

  }

  return data;

  }

  //------------------------------------------------------------------------------------------

  //函数:read_AD7705_dword

  //功能:从AD7705读一个24的数据

  //参数:无

  //返回:读到的一字节数据

  //变量:无

  //备注:AD7705是一个24位AD,选定刷新频率在16.7HZ下,有效位是19位,暂时读出全部24位数据

  //------------------------------------------------------------------------------------------

  unsigned long int read_AD7705_dword(void)

  {

  unsigned long data = 0;

  unsigned char i = 0;

  for( i=0; i《24; i++ )

  {

  data 《《= 1;

  AD_CLK0;

  asm(“nop”);

  asm(“nop”);

  asm(“nop”);

  if(AD_DOUT)

  {

  data++;

  }

  AD_CLK1;

  asm(“nop”);

  asm(“nop”);

  asm(“nop”);

  }

  return data;

  }

  //------------------------------------------------------------------------------------------

  //函数:write_AD7705_byte

  //功能:往AD7705写8位数据

  //参数:IN - uint8_t data,要写入AD7705的数据

  //返回:无

  //变量:无

  //备注:无

  //------------------------------------------------------------------------------------------

  void write_AD7705_byte(unsigned char data)

  {

  for(unsigned char i=0; i《8; i++)

  {

  AD_CLK0;

  if(data&0x80)

  AD_DIN1;

  else

  AD_DIN0;

  asm(“nop”);

  asm(“nop”);

  asm(“nop”);

  AD_CLK1;

  asm(“nop”);

  asm(“nop”);

  asm(“nop”);

  data 《《= 1;

  }

  AD_DIN1;

  }

  //------------------------------------------------------------------------------------------

  //函数:write_AD7705_dword

  //功能:往AD7705写24位数据,因为AD7705是24位的器件

  //参数:IN - int32_t data,要写入AD7705的数据

  //返回:无

  //变量:无

  //备注:无

  //------------------------------------------------------------------------------------------

  void write_AD7705_dword(unsigned long int data)

  {

  for(unsigned char i = 0; i《24; i++)

  {

  AD_CLK0;

  if(data&0x800000)

  AD_DIN1;

  else

  AD_DIN0;

  asm(“nop”);

  asm(“nop”);

  asm(“nop”);

  AD_CLK1;

  asm(“nop”);

  asm(“nop”);

  asm(“nop”);

  data 《《= 1;

  }

  AD_DIN1;

  }

  //--------------------------------------------------------------------------

  //-------------------------读取AD7705转换数据函数--------------------------

  //入口参数:指向main()主函数定义的ad_data变量的常量指针

  //--------------------------------------------------------------------------

  void ReadData7705(unsigned int *const pdata)

  {

  unsigned int data=0, fiter[5]={0};

  unsigned long int temp=0;

  unsigned char i=0, sort_flag=1;

  AD_CS0;

  _delay_us(5);

  start_AD7705();

  for( i=0; i《5; i++ )

  {

  start_timer0();

  _delay_ms(2);

  while( AD_DRDY )

  {

  if( time_count 》= time_read_data )

  {

  stop_timer0();

  AD_CS1;

  return;

  }

  }

  stop_timer0();

  write_AD7705_byte( RD_DATA_REG );

  fiter[i] = read_AD7705_word();

  }

  AD_CS1;

  sort_flag = 1;

  while( sort_flag )

  {

  sort_flag = 0;

  for( i=0; i《4; i++ )

  {

  if( fiter[i] 》 fiter[i+1] )

  {

  data = fiter[i];

  fiter[i] = fiter[i+1];

  fiter[i+1] = data;

  sort_flag = 1;

  }

  }

  }

  temp = ( (unsigned long int)fiter[1] + (unsigned long int)fiter[2]

  + (unsigned long int)fiter[3] )/3;

  data = (unsigned int)temp;

  if( (data《0xfff0) && (data&0x000f)》0x0008 )

  {

  data 》》= 4;

  data++;

  }

  else

  {

  data 》》= 4;

  }

  if( 1 != scale )

  {

  data -= 0x0800;

  }

  *pdata = data & 0x0fff;

  }

  //---------------------------------------------------------------------------------------

  gina 发表于 2008-9-22 10:35

  //校准命令格式

  //STX Data Long Command Code Parameter CheckSum ETX

  //0x55 数据长度(2) 量程指示 00H/01H CRC16(2) 0x0D

  void AD7705_calibration(void)

  {

  unsigned char readtimes =0;

  unsigned char cali_scale =0;

  unsigned long int temp =0;

  unsigned char coefficient[8] ={0}; //test[8]={0};

  //16位校验和的临时变量

  unsigned int crcvalue =0;

  AD_CS1;

  cali_scale = command[2]; //获取上位机发送的要校准的量程类型

  eeprom_busy_wait();

  eeprom_read_block( &coefficient[0], (void*)(ADDR_EEPROM_1+(cali_scale-1)*10), 8 );

  crcvalue = checksum( &coefficient[0], 6 );

  if( (coefficient[7]*256+coefficient[6]) != crcvalue )

  {

  readtimes++;

  }

  if( 1 == readtimes )

  {

  eeprom_busy_wait();

  &nnbsp; eeprom_read_block( &coefficient[0], (void*)(ADDR_EEPROM_2+(cali_scale-1)*10), 8 );

  crcvalue = checksum( &coefficient[0], 6 ); //

  if( (coefficient[7]*256+coefficient[6]) != crcvalue )

  {

  readtimes++;

  }

  }

  if( 2 == readtimes )

  {

  eeprom_busy_wait();

  eeprom_read_block( &coefficient[0], (void*)(ADDR_EEPROM_3+(cali_scale-1)*10), 8 );

  }

  ADDR409_MASK;

  AD_CS0;

  _delay_us(5);

  reset_AD7705();

  write_AD7705_byte( WR_CLOCK_REG );

  write_AD7705_byte( CLOCK_REG_SET );

  if( ZERO_CALIBRATION == command[3] ) //校准命令为零校准

  {

  write_AD7705_byte( WR_SETUP_REG );

  write_AD7705_byte( text_of_setup[cali_scale-1] | SYS_ZERO_CALI);

  //等待校准完成

  start_timer0();

  while( time_count 《 time_sys_cali );

  stop_timer0();

  while( AD_DRDY );

  //读OFFSET寄存器

  write_AD7705_byte( RD_OFFSET_REG );

  temp = read_AD7705_dword();

  if( cali_scale == scale)

  {

  ZS = temp; NO_CALI_TYPE = NO_FULL_CALIBRATION;

  }

  coefficient[0] = (unsigned char)( temp%256 );

  coefficient[1] = (unsigned char)( (temp/256)%256 );

  coefficient[2] = (unsigned char)( (temp/65536)%256 );

  }

  else if( FULL_CALIBRATION == command[3] )

  {

  temp = (unsigned long int)(coefficient[0]) + (unsigned long int)(coefficient[1])*256

  + (unsigned long int)(coefficient[2])*65536;

  write_AD7705_byte( WR_OFFSET_REG );

  write_AD7705_dword( temp );

  write_AD7705_byte( WR_SETUP_REG );

  write_AD7705_byte( text_of_setup[cali_scale-1] | SYS_FULL_CALI );

  //等待校准完成

  start_timer0();

  while( time_count 《 time_sys_cali );

  stop_timer0();

  while( AD_DRDY );//

  //读FULL寄存器

  write_AD7705_byte( RD_FULL_REG );

  temp = read_AD7705_dword();

  if( cali_scale == scale )

  {

  GS = temp;

  NO_CALI_TYPE = ALREADY_CALIBRATION;

  }

  coefficient[3] = (unsigned char)( temp%256 );

  coefficient[4] = (unsigned char)( (temp/256)%256 );

  coefficient[5] = (unsigned char)( (temp/65536)%256 );

  }

  else

  {

  AD_CS1;

  _delay_us(5);

  return;

  }

  AD_CS1;

  _delay_us(5);

  crcvalue = checksum(&coefficient[0],6);

  coefficient[6] = (unsigned char)(crcvalue%256);//

  coefficient[7] = (unsigned char)(crcvalue/256);

  eeprom_busy_wait();

  eeprom_write_block( &coefficient[0], (void*)(ADDR_EEPROM_1+(cali_scale-1)*10), 8 );

  eeprom_busy_wait();

  eeprom_write_block( &coefficient[0], (void*)(ADDR_EEPROM_2+(cali_scale-1)*10), 8 );

  eeprom_busy_wait();

  eeprom_write_block( &coefficient[0], (void*)(ADDR_EEPROM_3+(cali_scale-1)*10), 8 );

  Txout( &coefficient[0] );//输出校准数据给上位机

  return;

  }

  //

  void start_AD7705(void)

  {

  reset_AD7705();

  //写OFFSET寄存器

  write_AD7705_byte( WR_OFFSET_REG );

  write_AD7705_dword( ZS );

  //写满量程校准寄存器

  write_AD7705_byte( WR_FULL_REG );

  write_AD7705_dword( GS );

  //CLOCK寄存器设置,无分频,50HZ输出更新速率

  write_AD7705_byte( WR_CLOCK_REG );

  write_AD7705_byte( CLOCK_REG_SET );

  //写设置寄存器

  write_AD7705_byte( WR_SETUP_REG );

  write_AD7705_byte( text_of_setup[scale-1] );

  start_timer0();

  while( time_count 《 time_read_data );

  stop_timer0();

  }

相关文章

0个回复

我要评论

热门标签