调试AD7799遇到的问题

经历了四天的挣扎,AD7799终于调试成功啦!!!!!!!

说说我遇到的问题

一、不判忙的状态下,读出数据是ffffff

解决办法:

设置CONFIGURATION REGISTER 的con5为1,然后检测STATUS REGISTER 的NOREF位是否为1,如果为1说明内部基准低于0.5v,也就是说没有基准。我检测到NOREF位为 1,用万用表检测ref+为2.5,不是虚焊。检测来检测去没有问题,开始怀疑芯片,网上刚好也有说这个问题的,他说是芯片基准坏啦。我没办法重新焊了一块板子,问题依旧。没法硬着头皮看datasheet,最后发现还是设置的事。在我的硬件上ref-是直接接在管脚psw上的,如图示: 

问题就出在这,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一直是低电平,如图示

然后回想起21IC上的一篇日志上也是没有设置CS,这时候才恍然大悟,原来官方给的例程里都每次读写都改变了CS的值,移植官方的读写程序,如图

官方的读时序 

官方的写时序

问题就出在程序上画红线的语句上

正确的程序如图示: 

 

说说官方的程序吧,第一,官方程序没有判断RDY变低,所以可以说这个程序根本读不出数据即使在时序正常时;第二,官方给的读写函数里改变了cs的值,但是手册上没有改变,验证表明这个读写函数里不应该操作cs 

需要注意的是在主程序里,在操作AD7799之前,一定先把CS拉低,所有操作完成后,再把CS拉高。

好了不知道描述的足够清楚不,希望对以后使用AD7799的同胞有帮助吧!

AD5439是双路 10bit 电流输出型DAC,由于没有搞过SPI接口的DAC,所以先在网上下载了一个该DAC的底层函数,如下

#include "macros.h"
#include "math.h"
#include "dac.h"

// 向AD5439写命令字以及待转换的数据
void WriteAD5439(unsigned int ControlBits,unsigned int data )
{
   unsigned char i;
  
  data = (data << 2);
  data = (ControlBits | data);
  
  SCLK_SET;
  SYNC_CLR;
  
  for(i=0;i<16;i++)
  {
      SCLK_SET;
    if((data & 0x8000) != 0)
   {
       SDIN_SET;
      }
   else
   {
       SDIN_CLR;
      }
   SCLK_CLR;
   data  = (data << 1);
  }
  SYNC_SET;
  LDAC_CLR;
  SCLK_CLR;
  LDAC_SET;
  delay_ms(1);
  
}

// 初始化AD5439,
void  InitAD5439( void )
{
    ADCCL_CLR;  // AD5439.CLR = LOW,清零
    delay_ms(5);
    ADCCL_SET;  // AD5439.CLR = High,准备工作
    WriteAD5439_CMD(0x9000);
}              

// 读出SDO的值
unsigned int readSDO(unsigned int channal)
{
    unsigned char i = 0;
    unsigned int readData = 0;
 
    // 写入控制字,选择读回的通道
    if(channal == ReadBack_I)
    {
     WriteAD5439_CMD(ReadBack_I);
 }
 if(channal == ReadBack_V)
 {
     WriteAD5439_CMD(ReadBack_V);
 }
 
 // 准备接收数据
 SYNC_CLR;
 SCLK_CLR;  
 
 // 读数据,并处理
 for(i=0;i<16;i++)
 {
     SCLK_SET; // 上升沿,读一位
     readData |= (PINB & 0x01) << (15-i);
  SCLK_CLR; // 准备下一回读出数据
  //delay_ms(1); 
 }
 SYNC_SET;
 
 readData = ((readData >> 2) & 0x3ff);// 根据5439的命令字格式进行调整
 
 // 返回数据
 return readData; 
}

// 针对Init5439(),readSDO(),只写命令字,不写数据                  
void WriteAD5439_CMD(unsigned int ControlBits)
{
     unsigned char i;
  unsigned int data = ControlBits; 
  
  SCLK_SET;
  SYNC_CLR;
  for(i=0;i<16;i++)
  {
      SCLK_SET;
    if((data & 0x8000) != 0)
   {
       SDIN_SET;
      }
   else
   {
       SDIN_CLR;
      }
   SCLK_CLR;
   data  = (data << 1);
  }
  SYNC_SET;
  LDAC_CLR;
  SCLK_CLR;
  LDAC_SET;
  delay_ms(20);
}

void WriteVoltage(unsigned int ControlBits,unsigned int data)
{
  unsigned int  channal,i; // 选择通道
  unsigned int  dataInUse = data; // 用以重新调用write5439(),防止data受到破坏
  unsigned int  dataReadBack = 0;   

  if(ControlBits == Load_I)
  {
      channal = ReadBack_I;
  }
  if(ControlBits == Load_V)
  {
      channal = ReadBack_V;
  }

  i=0;
  for(;;)
  {
  
     WriteAD5439(ControlBits,dataInUse);
   
      dataReadBack = readSDO(channal);
      if(dataInUse == dataReadBack)
   {
          WriteAD5439(Updata_AB,dataInUse);
    break;
   } 
   else
   {
      i++;
   }
     if(i > 10) // 连续10次写不正确,则关机退出
   {
       SoftStartOff;     
   }
  }

}

void main(void)
{
    init_MCU(); // 初始化MCU

    WriteVoltage(Load_V,1024);  

    while(1)
    {
         process();  
    }

我首先看的是中文的pdf,我结合着这个程序去看该DAC的读写时序图,没发现程序有什么问题!那就开工吧,我用的是STC89C52RC作为主控,用io 口模拟SPI,没多久程序一个简单的测试程序就出来啦,编译没错误没警告。下载,调试,示波器上显示出一个-5v的电压,哦,忘了说我用的是哪个电路啦,上图

我是用的双极性输出电路,我采用5v的基准,那么输出电压范围为-5到+5v。

下面需要解决的问题就是,为何DAC一直输出-5v

我所采用解决方法如下:

第一:采用逻辑分析仪看我程序输出的时序是否正确,经观察时序和pdf上的时序一样。找不到问题,我没办法只好硬着头皮去看英文pdf,勉强可以看懂,看一遍后没发现问题所在。。。。。。这消耗了两天多的时间,最后确实没辙啦,好吧找技术支持,第二天技术支持给我回复啦,他提出了两个问题

(1)SCLK占空比不是50%(2)独立模式下,数据建立时间是否足够长

                                                        独立模式时序图

                                                      时序图上对应的各个时间

我解决SCLK占空比不是50%的问题,方法如下

通过给时钟加延时来实现占空比为50%,如红线示

通过时序图我们可以知道数据建立时间为t5,5ns,使用52作为主控,数据建立时间肯定大于5ns,程序改好,上电,观察示波器还是-5v,崩溃。。。。。。再次拿起英文pdf从头到尾看了一篇,还是没思路,先放放吧,去焊接个板子去吧,让大家看看板子的图,嘻嘻

同样的板子焊接了两块

焊接结束我接着调试我的DAC测试板,一样的没有进展,一样的办法我接着看英文pdf,然后接着迷茫。。。。。。

最后在一个阳光明媚的下午,突然间我想起啦上次调试AD7799出现的问题就是因为CS的信号有问题,我看了看AD5439的时序图,发现SYNC貌似和 CS有同样的功能,我直接把SYNC拉低,输出电压时0v,貌似不是这里的问题,我又把SYNC接回单片机引脚,这时候竟然奇迹的电压变化啦,我试了好几个数据电压输出却是变啦,但是没试几次就不管用啦,又回到了-5v。这时候我隐约觉得是不是SYNC的时序真的有问题呢?重看时序,发现问题啦!!!

红框框里标记的我理解的是16个脉冲结束后,SYNC置高,拉低都可以,我当时按参考程序上来的,直接给SYNC置高!

void WriteAD5439(uint ContralBits,uint DAdata)
{
 unsigned char i;
 uint buf;
 uint wave_data;
 buf=DAdata;
 buf = (buf<<2);
 wave_data = (ContralBits | buf);
 SYNC_SET();
 delay(1);
 SCLK_SET();
 SYNC_CLR();
 for(i=0;i<16;i++)
   {
    SCLK_SET();
    if((wave_data & 0x8000) != 0)
   {SDIN_SET();}
 else
   {SDIN_CLR();}
    delay(1);
 SCLK_CLR();
    delay(1);
 wave_data = (wave_data << 1);
    }
 SYNC_SET();
 LDAC_CLR();
 delay(1);
 SCLK_SET();
 LDAC_SET();
 delay(1);
 } 

我就想改下试试吧,然后我就把写数据的函数改为下面的

void WriteAD5439(uint ContralBits,uint DAdata)
{
 unsigned char i;
 uint buf;
 uint wave_data;
 buf=DAdata;
 buf = (buf<<2);
 wave_data = (ContralBits | buf);
 SYNC_SET();
 delay(1);
 SCLK_SET();
 SYNC_CLR();
 for(i=0;i<16;i++)
   {
    SCLK_SET();
    if((wave_data & 0x8000) != 0)
   {SDIN_SET();}
 else
   {SDIN_CLR();}
    delay(1);
 SCLK_CLR();
    delay(1);
 wave_data = (wave_data << 1);
    }
 SYNC_CLR();
 SCLK_SET();
 delay(1);
 }

重新上电,示波器上的数据终于会变化啦!!!搞定!收尾附上我的测试程序,以方便别人学习!!! 

#include 

#define uchar unsigned char
#define uint  unsigned int

#define SDIN_SET() P0_0=1;
#define SDIN_CLR() P0_0=0;

#define SCLK_SET() P0_1=1;
#define SCLK_CLR() P0_1=0;

#define SYNC_SET() P0_2=1;
#define SYNC_CLR() P0_2=0;

#define LDAC_SET() P0_3=1;
#define LDAC_CLR() P0_3=0;

#define DACLR_SET() P0_4=1;
#define DACLR_CLR() P0_4=0;

uint num;

void delay(uint t)
{
  uint i;
  while(t--)
  {
   for(i=0;i<125;i++);
   }
 }

void WriteAD5439_CMD(uint CMDBits)
{
  unsigned char i;
     unsigned int data1 = CMDBits; 
  SYNC_SET();
  delay(1);
     SCLK_SET();
  SYNC_CLR();
  for(i=0;i<16;i++)
  {
      SCLK_SET();
    if((data1 & 0x8000) != 0)
   {
       SDIN_SET();
      }
   else
   {
       SDIN_CLR();
      }
         delay(1);
   SCLK_CLR();
         delay(1);
   data1  = (data1 << 1);
  }
  SYNC_CLR();
  //LDAC_CLR();
  //delay(1);
  SCLK_SET();
  //LDAC_SET();
  delay(20);
}

void WriteAD5439(uint ContralBits,uint DAdata)
{
 unsigned char i;
 uint buf;
 uint wave_data;
 buf=DAdata;
 buf = (buf<<2);
 wave_data = (ContralBits | buf);
 SYNC_SET();
 delay(1);
 SCLK_SET();
 SYNC_CLR();
 for(i=0;i<16;i++)
   {
    SCLK_SET();
    if((wave_data & 0x8000) != 0)
   {SDIN_SET();}
 else
   {SDIN_CLR();}
    delay(1);
 SCLK_CLR();
    delay(1);
 wave_data = (wave_data << 1);
    }
 SYNC_CLR();
 //LDAC_CLR();
 //delay(1);
 SCLK_SET();
 //LDAC_SET();
 delay(1);
 }

unsigned int readSDO(void)
{
    unsigned char i = 0;
    unsigned int readData = 0;
    bit  itemp;
 
 WriteAD5439_CMD(0X2000);
 SYNC_SET();
    delay(1);
 SYNC_CLR();
 
 for(i=0;i<16;i++)
 {
     SCLK_SET();
        readData <<= 1;
        delay(1);
     itemp = P0_5;
  SCLK_CLR(); 
  if(itemp)
          readData |= 1;
  delay(1);
     }
 SYNC_CLR();
 return readData; 
}

void  InitAD5439( void )
{
    DACLR_CLR();  
    delay(5);
    DACLR_SET();  
}        

void main (void)
{
 num=1023;
 //InitAD5439();
 WriteAD5439_CMD(0x9000);
 WriteAD5439(0x1000,num);
 //readSDO();
 while(1)
   {
   num=1023;
   WriteAD5439(0x1000,num);
   delay(10);
   num=0;
   WriteAD5439(0x1000,num);
   delay(10);
   };
}

永不止步步 发表于11-12 11:42 浏览65535次
分享到:

已有0条评论

暂时还没有回复哟,快来抢沙发吧

添加一条新评论

只有登录用户才能评论,请先登录注册哦!

话题作者

永不止步步
金币:67410个|学分:345327个
立即注册
畅学电子网,带你进入电子开发学习世界
专业电子工程技术学习交流社区,加入畅学一起充电加油吧!

x

畅学电子网订阅号