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)--------------------------//
constunsignedchartext_of_setup[4]={0X04,0X08,0X10,0X28};//非缓冲模式,数字滤波同步
//constunsignedchartext_of_setup[4]={0X06,0X0A,0X12,0X2A};//缓冲模式,数字滤波同步
externvolatileunsignedcharcommand[7];//校准命令全局数组
externvolatileunsignedcharscale;//记录系统量程
externvolatileunsignedcharNO_CALI_TYPE;//未校准类型
externvolatileunsignedlongintZS,GS;//当前量程的校准系数
externvolatileunsignedchartime_count;//超时标志
//----------------------------------------------------------------------------
//函数:reset_AD7705
//功能:AD7705串行接口失步后将其复位。复位后要延时500us再访问
//参数:无
//返回:无
//变量:无
//备注:无
//----------------------------------------------------------------------------
voidreset_AD7705(void)
{
unsignedchari;
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读一个字节的数据
//参数:无
//返回:读到的一字节数据
//变量:无
//备注:无
//------------------------------------------------------------------------------------------
unsignedcharread_AD7705_byte(void)
{
unsignedchardata=0;
unsignedchari=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");
}
returndata;
}
//------------------------------------------------------------------------------------------
//函数:read_AD7705_word
//功能:从AD7705读一个字的数据,共16bit
//参数:无
//返回:读到的一字节数据
//变量:无
//备注:无
//------------------------------------------------------------------------------------------
unsignedintread_AD7705_word(void)
{
unsignedintdata=0;
unsignedchari=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");
}
returndata;
}
//------------------------------------------------------------------------------------------
//函数:read_AD7705_dword
//功能:从AD7705读一个24的数据
//参数:无
//返回:读到的一字节数据
//变量:无
//备注:AD7705是一个24位AD,选定刷新频率在16.7HZ下,有效位是19位,暂时读出全部24位数据
//------------------------------------------------------------------------------------------
unsignedlongintread_AD7705_dword(void)
{
unsignedlongdata=0;
unsignedchari=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");
}
returndata;
}
//------------------------------------------------------------------------------------------
//函数:write_AD7705_byte
//功能:往AD7705写8位数据
//参数:IN-uint8_tdata,要写入AD7705的数据
//返回:无
//变量:无
//备注:无
//------------------------------------------------------------------------------------------
voidwrite_AD7705_byte(unsignedchardata)
{
for(unsignedchari=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_tdata,要写入AD7705的数据
//返回:无
//变量:无
//备注:无
//------------------------------------------------------------------------------------------
voidwrite_AD7705_dword(unsignedlongintdata)
{
for(unsignedchari=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变量的常量指针
//--------------------------------------------------------------------------
voidReadData7705(unsignedint*constpdata)
{
unsignedintdata=0,fiter[5]={0};
unsignedlonginttemp=0;
unsignedchari=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=((unsignedlongint)fiter[1]+(unsignedlongint)fiter[2]
+(unsignedlongint)fiter[3])/3;
data=(unsignedint)temp;
if((data<0xfff0)&&(data&0x000f)>0x0008)
{
data>>=4;
data++;
}
else
{
data>>=4;
}
if(1!=scale)
{
data-=0x0800;
}
*pdata=data&0x0fff;
}
//---------------------------------------------------------------------------------------
//校准命令格式
//STXDataLongCommandCodeParameterCheckSumETX
//0x55数据长度(2)量程指示00H/01HCRC16(2)0x0D
voidAD7705_calibration(void)
{
unsignedcharreadtimes=0;
unsignedcharcali_scale=0;
unsignedlonginttemp=0;
unsignedcharcoefficient[8]={0};//test[8]={0};
//16位校验和的临时变量
unsignedintcrcvalue=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();
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]=(unsignedchar)(temp%256);
coefficient[1]=(unsignedchar)((temp/256)%256);
coefficient[2]=(unsignedchar)((temp/65536)%256);
}
elseif(FULL_CALIBRATION==command[3])
{
temp=(unsignedlongint)(coefficient[0])+(unsignedlongint)(coefficient[1])*256
+(unsignedlongint)(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]=(unsignedchar)(temp%256);
coefficient[4]=(unsignedchar)((temp/256)%256);
coefficient[5]=(unsignedchar)((temp/65536)%256);
}
else
{
AD_CS1;
_delay_us(5);
return;
}
AD_CS1;
_delay_us(5);
crcvalue=checksum(&coefficient[0],6);
coefficient[6]=(unsignedchar)(crcvalue%256);//
coefficient[7]=(unsignedchar)(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;
}
//
voidstart_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();
}