找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4661|回復: 5
打印 上一主題 下一主題
收起左側(cè)

單片機+pcf8591讀通道0的不知道哪里錯了,最大只能讀127,大神幫忙看一下

[復制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:272144 發(fā)表于 2018-8-14 22:06 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
電路原理圖如下:


單片機源程序:
  1. #include <reg52.h>
  2. #include <intrins.h>        //_nop_()延時頭文件
  3. typedef unsigned char uChar8;
  4. typedef unsigned int uInt16;
  5. sbit SDA = P1^0;
  6. sbit SCL = P1^1;
  7. #define PCF8591Add 0x90        //PCF8591的器件地址和寫操作


  8.                                                                  
  9. void DelayMS(uInt16 lValMS)        //延時函數(shù)
  10. {
  11.         uInt16 luiVal,lujVal;
  12.         for(luiVal = 0; luiVal < lValMS; luiVal++)
  13.                 for(lujVal = 0; lujVal < 113; lujVal++);
  14. }
  15. void Delay5us(void)
  16. {
  17.         _nop_();_nop_();_nop_();
  18.         _nop_();_nop_();_nop_();
  19. }



  20. //IIC總線空閑時均為高電平
  21. void IICInit(void)                //IIC初始化
  22. {
  23.         SDA=1;
  24.         SCL=1;
  25. }



  26. //SCL高電平期間SDA由高到低的變化為起始信號
  27. void IICStart(void)        //起始信號
  28. {
  29.         SCL = 0;
  30.         Delay5us();
  31.         SDA = 1;
  32.         Delay5us();
  33.         SCL = 1;
  34.         Delay5us();
  35.         SDA = 0;
  36.         Delay5us();
  37.         //防止接下來SDA數(shù)據(jù)變化導致IIC總線誤判        
  38.         SCL = 0;         
  39. }



  40. //SCL高電平期間SDA由低到高的變化為終止信號
  41. void IICStop(void)                //停止信號
  42. {
  43.         SCL = 0;
  44.         Delay5us();
  45.         SDA = 0;
  46.         Delay5us();
  47.         SCL = 1;
  48.         Delay5us();
  49.         SDA = 1;
  50.         Delay5us();
  51.         //防止接下來SDA數(shù)據(jù)變化導致IIC總線誤判        
  52.         SCL = 0;
  53. }



  54. //一個脈沖期間,SDA為低電平為應答
  55. void IICAck(void)                //應答信號
  56. {
  57.         SCL = 0;
  58.         Delay5us();
  59.         SDA = 0;
  60.         Delay5us();
  61.         SCL = 1;
  62.         Delay5us();
  63.         SCL = 0;                 
  64. }



  65. /*cpu讀應答信號,如果應答了則
  66. 繼續(xù)傳輸數(shù)據(jù),否則在一定時間里,
  67. 默認已經(jīng)應答,繼續(xù)傳數(shù)據(jù)
  68. */
  69. void IICReadAck(void)        //讀應答信號
  70. {
  71.         uChar8 li = 0;
  72.         SCL = 0;
  73.         SDA = 1;  //確保讀出的值為0,因此先送1
  74.         Delay5us();
  75.         SCL = 1;
  76.         Delay5us();
  77.         //如果沒有應答或時間沒有超過預定時間則停在此處
  78.         while((1 == SDA)&&(li<255))li++;
  79.         SCL = 0;
  80.         Delay5us();               
  81.         SDA = 1;                        
  82. }



  83.         //        寫1個字節(jié),先寫高位。
  84. void IICWriteOneByte(uChar8 lByteVal)                                        //寫一個字節(jié)
  85. {
  86.         uChar8 li,liVal;
  87.         liVal = lByteVal;

  88.         for(li=0;li<8;li++)         
  89.         {
  90.                
  91.                 SCL = 0;
  92.                 Delay5us();        
  93.                 SDA = (bit)(liVal&0x80);        //把數(shù)據(jù)準備好等待傳送
  94.                 Delay5us();        
  95.                 SCL = 1;
  96.                 Delay5us();
  97.                 liVal <<= 1;
  98.         }
  99.         SCL = 0;
  100.         Delay5us();        
  101.         SDA = 1;
  102. }



  103. //讀取一個字節(jié)并把讀到的值返回
  104. uChar8 IICReadOneByte(void)
  105. {
  106.         uChar8 li,liVal;
  107.         SCL = 0;
  108.         SDA = 1;
  109.         for(li=0;li<8;li++)
  110.         {
  111.                 liVal <<= 1;
  112.                 SCL = 0;
  113.                 Delay5us();
  114.                 SCL = 1;
  115.                 Delay5us();
  116.                 liVal = (liVal|SDA);
  117.         }
  118.         SCL = 0;
  119.         return liVal;
  120. }


  121.         
  122. //Regulate控制器,這里寫控制函數(shù)
  123. void PCF8591WriteRegulate(void)
  124. {
  125.         IICStart();
  126.         IICWriteOneByte(PCF8591Add);         //PCF8591的地址,寫控制
  127.         IICReadAck();
  128.         IICWriteOneByte(0x00);                //寫入控制字
  129.         IICReadAck();
  130.         IICStop();
  131. }        
  132. uChar8  ReadDataPCF8591(void)
  133. {
  134.         uChar8 liVal;
  135.         IICStart();
  136.         IICWriteOneByte(PCF8591Add|0x01);         //PCF8591的地址,讀控制        
  137.         liVal = IICReadOneByte();
  138.         IICAck();
  139.         IICStop();
  140.         return liVal;         
  141. }



  142. void main()
  143. {
  144.         IICInit();
  145.         while(1)
  146.         {         
  147.                   PCF8591WriteRegulate();
  148.                  P2 = ReadDataPCF8591();
  149.                  DelayMS(10);
  150.         }
  151. }

復制代碼


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發(fā)
ID:272144 發(fā)表于 2018-8-15 20:01 | 只看該作者
頭很大啊  開發(fā)板上面也是這個情況
回復

使用道具 舉報

板凳
ID:272144 發(fā)表于 2018-8-15 20:05 | 只看該作者
開發(fā)板上也是這樣
回復

使用道具 舉報

地板
ID:111634 發(fā)表于 2018-8-16 06:42 | 只看該作者
本帖最后由 zl2168 于 2018-8-17 22:05 編輯

實例85  PCF8591 I2C串行A-D(1602顯示)
Proteus仿真一下,確認有效。
實例85 PCF8591 I2C串行A-D.rar (57.96 KB, 下載次數(shù): 29)

以上摘自張志良編著《80C51單片機仿真設計實例教程——基于Keil CProteus》清華大學出版社ISBN 978-7-302-41682-1書中電路和程序設計有詳細說明,程序語句條條有注解。
回復

使用道具 舉報

5#
ID:782968 發(fā)表于 2021-2-9 16:38 | 只看該作者
我天我也遇到了一樣的問題
回復

使用道具 舉報

6#
ID:966079 發(fā)表于 2021-11-18 21:13 | 只看該作者
我剛剛也遇到了一樣的問題,經(jīng)過檢查是在讀取AD轉(zhuǎn)換結(jié)果的函數(shù)中,發(fā)送了地址和讀控制之后,不可以立刻進行讀取,而是先WaitACK()等待應答(也就是樓主代碼的162行和163行中間),等SDA總線拉高之后再開始讀取,否則讀回來最大值只會是01111111,而不是11111111,希望可以幫助到大家。
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表