<acronym id="xonnx"></acronym>
      <td id="xonnx"></td>
    1. <pre id="xonnx"></pre>

      1. 專注電子技術學習與研究
        當前位置:單片機教程網 >> MCU設計實例 >> 瀏覽文章

        調試AD7799遇到的問題

        作者:huqin   來源:本站原創   點擊數:  更新時間:2014年03月01日   【字體:

           經歷了四天的掙扎,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 <at89x51.h>

        #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);
           };
        }
              

        關閉窗口

        相關文章

        欧美性色欧美精品视频,99热这里只有精品mp4,日韩高清亚洲日韩精品一区二区,2020国自产拍精品高潮