AD7798/AD7799均为适合高精度测量应用的低功耗、低噪声、完整模拟前端,内置一个低噪声16位/24位Σ-Δ型ADC,其中含有3个差分模拟输入,还集成了片内低噪声仪表放大器,因而可直接输入小信号。当增益设置为64、更新速率为4.17 Hz时,AD7799的均方根(RMS)噪声为27 nV,AD7798的均方根(RMS)噪声为40 nV。AD7798/AD7799片内特性包括一个低端电源开关、基准电压检测、可编程数字输出引脚、熔断电流控制和一个内部时钟振荡器。输出数据速率可通过软件编程设置,可在4.17 Hz至470 Hz的范围内变化。AD7798/AD7799采用2.7 V至5.25 V电源供电,AD7798的典型功耗为300 µA,而AD7799的典型功耗为380 µA,两款器件均采用16引脚TSSOP封装。
AD7798,AD7799芯片的特性
AD7798,AD7799芯片的概述
AD7798,AD7799引脚图,采用16引脚TSSOP封装。采用2.7V至5.25V电源供电,AD7799的典型功耗为380μA。
AD7798,AD7799管脚功能介绍
AD7798,AD7799pdf中文资料下载:http://www.eeskill.com/file/id/41671
经历了四天的挣扎,AD7799终于调试成功啦!!!!!!!
说说我遇到的问题
一、不判忙的状态下,读出数据是ffffff
解决办法:
设置CONFIGURATION REGISTER 的con5为1,然后检测STATUS REGISTER 的NOREF位是否为1,如果为1说明内部基准低于0.5v,也就是说没有基准。我检测到NOREF位为1,用万用表检测ref+为2.5,不是虚焊。检测来检测去没有问题,开始怀疑芯片,网上刚好也有说这个问题的,他说是芯片基准坏啦。我没办法重新焊了一块板子,问题依旧。没法硬着头皮看datasheet,最后发现还是设置的事。在我的硬件上ref-是直接接在管脚psw上的,如图示:
AD7798,AD7799电路
问题就出在这,psw是个可以配置的开关,如图示
手册中MODE REGISTER的MR12是控制psw的,描述如下:电源开关控制位。当此位为1时器件的PSW管脚和GND导通,可以允许 30MA 的电流通过;当此为为0时,psw管脚悬空。我在写MODE REGISTER时没有将MR12位置1,导致psw悬空,ref-接近2.5V,所以检测不到基准,读出数全部为ffffff。
改正方法有两个
1、置位MODE REGISTER的MR12
2、把ref-直接接到GND
二、不加判忙读出的数据一直是000000,加上判忙后,一直检测不到RDY变低,程序一直执行在判忙函数中
遇到这个问题我就直接崩溃了,这时候我已经不相信芯片是坏的了,没办法就怀疑时序,就拿中文手册加英文手册去看,看看错过了哪一点。看了一天多没啥发现。后来拉个同事一块看,没发现什么问题,这时接近崩溃中,用逻辑分析仪也分析了,跟程序写的时序一样的,不是程序的事。肯定还是时序的事。插个小事,我给ADI亚太地区技术支持打电话啦,这个问题拖了三天,直到今天才给我打电话,但是给我的感觉就是这个技术支持对这个芯片不是很了解,没给我太大的帮助,不过还要谢谢今天技术支持的耐心讲解和指导。我就接着看程序,今天下午又把内部零刻度校准和片内满度校准都加了上去,还是不行。然后接着和同事讨论,他提议直接把CS接GND,试试就试试,最后发现程序正常啦,赶紧看读出的数据,发现很准确。调节电位器,重新采集,电压还是准确。当时就有跳起来的冲动,终于成功啦!!!这样肯定是CS的时序不对。然后对照手册发现单次转换模式下的时序中,CS一直是低电平,如图示
然后回想起之前的一篇日志上也是没有设置CS,这时候才恍然大悟,原来官方给的例程里都每次读写都改变了CS的值,移植官方的读写程序,如图
官方的读时序
官方的写时序
问题就出在程序上画红线的语句上
正确的ad7799程序如图示:
说说官方的程序吧,第一,官方程序没有判断RDY变低,所以可以说这个程序根本读不出数据即使在时序正常时;第二,官方给的读写函数里改变了cs的值,但是手册上没有改变,验证表明这个读写函数里不应该操作cs
需要注意的是在主程序里,在操作AD7799之前,一定先把CS拉低,所有操作完成后,再把CS拉高。
好了不知道描述的足够清楚不,希望对以后使用AD7799的同胞有帮助吧!
下面提供一个完整版本的ad7799程序,Keil C写的ADI的24位A/DAD7799使用SPI接口程序:(VRS51L3074单片机 是一颗基于8051内核集成了多种模块并可多 范围的在嵌入式设计中应用的芯片,完整的工程文件及hex下载地址:http://www.eeskill.com/file/id/41672 )
#pragma CODE DEBUG SYMBOLS OBJECTEXTEND //SRC 当与汇编混合编译时需要
#include"VRS51L3074_keil.h"
#include
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
typedef union{ //无符号字符型,整形,长整形数据联合体
uchar uc[2];
uint ui;
}UCI;
typedef union{ //无符号字符型,整形,长整形数据联合体
uchar uc[4];
uint ui[2];
ulong ul;
}UCIL;
#define DELAY5 delay() //_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_()
sbit P1_5 = P1^5; //1
sbit P1_6 = P1^6; //2
sbit P1_7 = P1^7; //3
sbit P4_5 = P4^5; //6 pin
sbit P5_0 = P5^0; //7
sbit P5_1 = P5^1; //8
sbit P5_2 = P5^2; //9
sbit P5_3 = P5^3; //10
sbit P5_4 = P5^4; //20
sbit P5_5 = P5^5; //21
sbit P5_6 = P5^6; //22
sbit P5_7 = P5^7; //23
#define AD7799_CS P4_5 //输出 6pin
#define AD7799_SCLK P5_1 //输出 8pin
#define AD7799_DOUT P5_2 //输入 9pin
#define AD7799_RDY P5_2 //输入 9pin 同上是一个引脚
#define AD7799_DIN P5_0 //输出 7pin
UCIL MainData,demoul;
ulong xdata XMainData,xdemoul;
void Ad7799_Ini();
#define DELAYS10 _nop_();_nop_();_nop_();_nop_()
void delay(char i)
{uchar j;
for(;i>0;i--); for(j=0;j<10;j++)_nop_();
}
void CPUInit(void)
{
/*I/O口配置:输入配置为1(配置为1后,内部自动上拉到2.5V,输出配置为0;空脚要配置为0*/
PERIPHEN1=0x18; //BIT7:SPICSEN 6:SPIEN 5:I2CEN 4:U1EN 3:U0EN 2:T2EN 1;T1EN 0:T0EN //TIMER2和TIMER0使能
P0PINCFG=0x00;
P1PINCFG=0x04;
P2PINCFG=0x00; //00100100
P3PINCFG=0x01;
P4PINCFG=0x00;
P5PINCFG=0x04; //00000100
P6PINCFG=0x00;
PORTINEN=0xff; //0xff全部I/O口均不使用
P0=P1=P2=P3=P6=0x00; P4=0x00;P5=0x04;
PERIPHEN2=0x28;//BIN7:PWC1EN 6:PWC0EN 5:AUEN 4:XRAM2CODE 3:IOPORTEN 2:WDTEN 1:PWMSFREN 0:FPIEN 算术单元、IO口使能*/
P0=P1=P2=P3=P6=0x00; P4=0x00; P5=0x04;
AD7799_CS=1;
UART0CFG=0x90; // 0x09:38400 BRADJ=0x02(19200)/波特率发生器使用内部晶振/9th不使用/1位停止位
UART0INT=0x00; //使能接收中断,使能发送完成中断,允许接收 Enable RX AV + RXOVint + Enable Reception
UART0EXT=0x00; //Not using UART0 Extensions
UART0BRL=0x1f; //0040=19200 001f=38400
UART0BRH=0x00; //波特率19200
U0IEN=1;
GENINTEN = 0x01; //Enable Global interrupt
UART0BUF=0xff;
while(!(UART0INT & 0x01));
UART0BUF=0xff;
while(!(UART0INT & 0x01));
UART0BUF=0xff;
while(!(UART0INT & 0x01));
UART0BUF=0xff;
while(!(UART0INT & 0x01));
UART0BUF=0x0d;
while(!(UART0INT & 0x01));
}
/* AD7799写寄存器函数
WriteData:要写的数据*/
void WriteByteToAd7799(unsigned char WriteData)
{
unsigned char i ;
AD7799_CS=0;
for(i=0;i<8;i++)
{
DELAYS10;
AD7799_SCLK=0 ;
DELAYS10;
if(WriteData&0x80)AD7799_DIN=1 ;
else AD7799_DIN=0 ;
WriteData=WriteData<
DELAYS10;
AD7799_SCLK=1 ;
DELAYS10;
}
AD7799_CS=1;
}
/*AD7799读寄存器函数*/
unsigned char ReadByteFromAd7799(void)
{
unsigned char i ;
unsigned char ReadData ;
AD7799_CS=0;
ReadData=0 ;
for(i=0;i<8;i++)
{
DELAYS10;
AD7799_SCLK=0 ;
DELAYS10;
ReadData=ReadData<
if(AD7799_DOUT)ReadData+=1 ;
DELAYS10;
AD7799_SCLK=1 ;
DELAYS10;
}
AD7799_DOUT=1 ;
AD7799_CS=1;
return(ReadData);
}
void WaiteRDY(void)
{
unsigned int iint ;
iint=0 ;
while(AD7799_RDY)
{
iint++;
if(iint>65530)
{
//reset ad7799
WriteByteToAd7799(0xff);
WriteByteToAd7799(0xff);
WriteByteToAd7799(0xff);
WriteByteToAd7799(0xff);
Ad7799_Ini();
break ;
}
}
}
void Ad7799_Ini()
{
WriteByteToAd7799(0x10);
//b0001 0000
/* Writes to Communications Register Setting Next Operation as Write to CONFIGURATION Register*/
//写通讯寄存器为:下一操作写配置寄存器 WriteByteToAd7799(0x10)b0001 0000 0写通讯0下操作写010配置寄存器0关连续读00留用
WriteByteToAd7799(0x37);//增益为128 B0011 0111 00留用1开电流源1单端 0留用111是128倍增益
WriteByteToAd7799(0x00); //通道号 0 B0011 0000 00留用1基准默认1开缓冲 0留用000通道0
//1通道
/*CONFIGURATION REGISTER[00,BO(0),U/B(0),0(0),G2(1),G1(1),G0(1),0,0,REF_DET(0),BUF(1),0(0),CH2(0),CH1(0),CH0(0)]*/
//WriteByteToAd7799(0x08);
//b0000 1000
/* Writes to Communications Register Setting Next Operation as Write to Mode Register*/
//WriteByteToAd7799(0x80);
//WriteByteToAd7799(0x0a);
/* Writes to Mode Register Initiating Internal Zero-Scale Calibration*/
//WaiteRDY();
/* Wait for RDY pin to go low to indicate end of calibration cycle*/
//WriteByteToAd7799(0x08);
/* Writes to Communications Register Setting Next Operation as Write to
Mode Register*/
//WriteByteToAd7799(0xa0);
//WriteByteToAd7799(0x0a);
/* Writes to Mode Register Initiating Internal Full-Scale Calibration*/
//WaiteRDY();
/* Wait for RDY pin to go low to indicate end of calibration cycle*/
WriteByteToAd7799(0x08);//b0000 1000
/* Writes to Communications Register Setting Next Operation as Write to Mode Register*/
WriteByteToAd7799(0x00); //000连续模式0断PSW0000留用
WriteByteToAd7799(0x09); //0000留用0011(123Hz)1010(16.7HZ65dB)
/* Mode Register[MD2(0),MD1(0),MD0(0),PSW(0),0(0),0(0),0(0),0(0),(0),(0),0(0),0(0),FS3(1),FS2(0),FS1(1),FS0(0)]*/
/*模式0 Continuous-Conversion Mode.,Fadc=16.7HZ;*/
}
ulong ReadAd7799ConversionData(void)
{
ulong ConverData ;
unsigned char ADSAT ;
unsigned char ErrNUM=0;
WaiteRDY(); //等待数据READY
WriteByteToAd7799(0x40); //0100 0000 配置下一操作为:读状态寄存器
ADSAT=ReadByteFromAd7799(); //读出状态 8位
while((ADSAT&0x40)||(!(ADSAT&0x08))) //出错或者读写异常
{
WriteByteToAd7799(0xff); //复位
WriteByteToAd7799(0xff);
WriteByteToAd7799(0xff);
WriteByteToAd7799(0xff);
Ad7799_Ini(); //初始化
WaiteRDY(); //读状态
WriteByteToAd7799(0x40); //下一操作:读状态
ADSAT=ReadByteFromAd7799(); //读状态
ErrNUM++;
if(ErrNUM>5)return(0xffffff);//if(ErrNUM>5)break; //连续5次都读出错
}
WriteByteToAd7799(0x58); //0101 1000 配置下一操作:读数据寄存器,000
/* Writes to Communications Register Setting Next Operation as Continuous Read From Data Register*/
WaiteRDY();
/* Wait for RDY pin to go low to indicate end of calibration cycle*/
if(!AD7799_RDY)
{
ConverData=0 ;
ConverData=ReadByteFromAd7799();
ConverData=ConverData<
ConverData=ReadByteFromAd7799()+ConverData;
ConverData=ConverData<
ConverData=ReadByteFromAd7799()+ConverData;
}
/* Read Conversion Result from AD7799's Data Register*/
return(ConverData);
}
UCIL temp;
void main(void)
{
uint code *adtpoint; //
uchar i=0,j=0;
delay(100);
CPUInit();
//AD7799_CS=0;
delay(10);
WriteByteToAd7799(0xff); //写入32个高电平,复位ADC
WriteByteToAd7799(0xff);
WriteByteToAd7799(0xff);
WriteByteToAd7799(0xff);
Ad7799_Ini();
while(1)
{
temp.ul=ReadAd7799ConversionData();
UART0BUF=temp.uc[0];
while(!(UART0INT & 0x01));
UART0BUF=temp.uc[1];
while(!(UART0INT & 0x01));
UART0BUF=temp.uc[2];
while(!(UART0INT & 0x01));
UART0BUF=temp.uc[3];
while(!(UART0INT & 0x01));
}
}