Board logo

標題: 關於 PCF8591 AD/DA 晶片o既問題 [打印本頁]

作者: superman9394    時間: 2013-10-28 01:51     標題: 關於 PCF8591 AD/DA 晶片o既問題

本帖最後由 superman9394 於 2013-10-28 02:02 編輯

唔知有冇師兄玩過呢粒 AD/DA IC 呢? 小弟最近係網上搵到以下 C 語言o既程式碼, 我想係 LCD 輸出 PCF8591 其他 Channel o既資料但失敗.

詳情係咁o既我見到較後部份o既 void ADC_PCF8591(uchar CtrlByte) 作者係話 "連續讀入4路通道的A/D轉換結果並保存到 Recv_Buffer", 入面亦見到係有個 for loop 行左 4次 Recv_Buffer[i++]=IIC_ReceiveByte(); 照咁睇 Recv_Buffer 應該有4筆資料, 但係我嘗試改動最後 void main() 入面o既 Convert_To_Voltage(Recv_Buffer[0]) 呢個位做 1/2/3, 但係都一樣係顯示返之前個 Channel o既資料, 係唔係我理解錯左呢?
  1. #include<reg52.h>
  2. #include<intrins.h>
  3. #define uchar unsigned char
  4. #define uint unsigned int
  5. #define Delay4us(){_nop_();_nop_();_nop_();_nop_();}
  6. sbit LCD_RS=P2^0;
  7. sbit LCD_RW=P2^1;
  8. sbit LCD_EN=P2^2;
  9. sbit SCL=P1^0;                            //I2C時鐘引腳
  10. sbit SDA=P1^1;                            //I2C資料登錄輸出引腳
  11. uchar Recv_Buffer[4];                     //資料接收緩衝
  12. uint Voltage[]={'0','0','0','0'};         //資料分解為電壓x.xx
  13. bit bdata IIC_ERROR;                      //I2C錯誤標誌位元
  14. uchar LCD_Line_1[]={"   .  V         "};

  15. //延時
  16. void delay(int ms)
  17. {
  18. uchar i;
  19. while(ms--) for(i=0;i<250;i++) Delay4us();
  20. }

  21. //LCD忙檢測
  22. bit LCD_Busy_Check()
  23. {
  24. bit Result;
  25. LCD_RS=0;
  26. LCD_RW=1;
  27. LCD_EN=1;
  28. Delay4us();
  29. Result=(bit)(P3&0x80);
  30. LCD_EN=0;
  31. return Result;
  32. }

  33. //寫指令
  34. void LCD_Write_Command(uchar cmd)
  35. {
  36. while(LCD_Busy_Check());
  37. LCD_RS=0;
  38. LCD_RW=0;
  39. LCD_EN=0;
  40. _nop_();
  41. _nop_();
  42. P3=cmd;
  43. Delay4us();
  44. LCD_EN=1;
  45. Delay4us();
  46. LCD_EN=0;
  47. }

  48. // 寫數據
  49. void LCD_Write_Data(uchar dat)
  50. {
  51. while(LCD_Busy_Check());
  52. LCD_RS=1;
  53. LCD_RW=0;
  54. LCD_EN=0;
  55. P3=dat;
  56. Delay4us();
  57. LCD_EN=1;
  58. Delay4us();
  59. LCD_EN=0;
  60. }

  61. //初始化
  62. void LCD_Initialise()
  63. {
  64. LCD_Write_Command(0x38);
  65. delay(5);
  66. LCD_Write_Command(0x0c);
  67. delay(5);
  68. LCD_Write_Command(0x06);
  69. delay(5);
  70. LCD_Write_Command(0x01);
  71. delay(5);
  72. }

  73. //設置顯示位置
  74. void LCD_Set_Position(uchar pos)
  75. {
  76. LCD_Write_Command(pos|0x80);
  77. }

  78. //顯示一行
  79. void LCD_Display_A_Line(uchar Line_Addr,uchar s[])
  80. {
  81. uchar i;
  82. LCD_Set_Position(Line_Addr);
  83. for(i=0;i<16;i++)LCD_Write_Data(s[i]);
  84. }

  85. // 將模數轉換後得到的值分解存入緩存
  86. void Convert_To_Voltage(uchar val)
  87. {
  88. uchar Tmp;                       //最大值為255,對應5V,255/5=51
  89. Voltage[2]=val/51+'0';           //整數部分
  90. Tmp=val%51*10;                   // 第一位小數
  91. Voltage[1]=Tmp/51+'0';
  92. Tmp=Tmp%51*10;
  93. Voltage[0]=Tmp/51+'0';
  94. }

  95. //啟動I2C匯流排
  96. void IIC_Start()
  97. {
  98. SDA=1;
  99. SCL=1;
  100. Delay4us();
  101. SDA=0;
  102. Delay4us();
  103. SCL=0;
  104. }

  105. //停止I2C匯流排
  106. void IIC_Stop()
  107. {
  108. SDA=0;
  109. SCL=1;
  110. Delay4us();
  111. SDA=1;
  112. Delay4us();
  113. SCL=0;
  114. }

  115. // 從機發送應答位
  116. void Slave_ACK()
  117. {
  118. SDA=0;
  119. SCL=1;
  120. Delay4us();
  121. SCL=0;
  122. SDA=1;
  123. }

  124. // 從機發送非應答位
  125. void Slave_NOACK()
  126. {
  127. SDA=1;
  128. SCL=1;
  129. Delay4us();
  130. SCL=0;
  131. SDA=0;
  132. }

  133. //發送一位元組
  134. void IIC_SendByte(uchar wd)
  135. {
  136. uchar i;
  137. for(i=0;i<8;i++)                                        //迴圈移入8位
  138. {
  139. SDA=(bit)(wd&0x80);
  140. _nop_();
  141. _nop_();
  142. SCL=1;
  143. Delay4us();
  144. SCL=0;
  145. wd<<=1;
  146. }
  147. Delay4us();
  148. SDA=1;                                //釋放匯流排並準備讀取應答
  149. SCL=1;
  150. Delay4us();
  151. IIC_ERROR=SDA;                                //IIC_ERROR=1表示無應答
  152. SCL=0;
  153. Delay4us();
  154. }

  155. //接收一位元組
  156. uchar IIC_ReceiveByte()
  157. {
  158. uchar i,rd=0x00;
  159. for(i=0;i<8;i++)
  160. {
  161. SCL=1;
  162. rd<<=1;
  163. rd|=SDA;
  164. Delay4us();
  165. SCL=0;
  166. Delay4us();
  167. }
  168. SCL=0;
  169. Delay4us();
  170. return rd;
  171. }

  172. //連續讀入4路通道的A/D轉換結果並保存到Recv_Buffer
  173. void ADC_PCF8591(uchar CtrlByte)
  174. {
  175. uchar i;
  176. IIC_Start();
  177. IIC_SendByte(0x90);                        //發送寫地址
  178. if(IIC_ERROR==1)return;
  179. //IIC_SendByte(CtrlByte);                //發送控制位元組
  180. //if(IIC_ERROR==1)return;
  181. IIC_Start();                                //重新發送開始命令
  182. IIC_SendByte(0x91);                        //發送讀地址
  183. if(IIC_ERROR==1)return;
  184. IIC_ReceiveByte();                        //空讀一次,調整讀順序
  185. Slave_ACK();                                //收到一位元組後發送一個應答位元
  186. for(i=0;i<4;i++)
  187. {
  188. Recv_Buffer[i++]=IIC_ReceiveByte();
  189. Slave_ACK();                                //收到一個位元組後發送一個應答位元
  190. }
  191. Slave_NOACK();
  192. IIC_Stop();                                //收到一個位元組後發送一個非應答位
  193. }

  194. //向 PCF8591發送1位元組進行AD轉換
  195. //主程序
  196. void main()
  197. {
  198. LCD_Initialise();
  199. while(1)
  200. {
  201. ADC_PCF8591(0x04);
  202. Convert_To_Voltage(Recv_Buffer[0]);
  203. LCD_Line_1[2]=Voltage[2];
  204. LCD_Line_1[4]=Voltage[1];
  205. LCD_Line_1[5]=Voltage[0];

  206. LCD_Display_A_Line(0x00, LCD_Line_1);
  207.                
  208. }
  209. }
複製代碼

作者: Charcoal99    時間: 2013-10-28 17:24

#194 行是你comment的嗎?
連續讀入是需要把 control-byte 的auto-increment flag 設置的, (即送出 CtrlByte 04),
但這code 跟本沒有把 control byte 送出去。
作者: superman9394    時間: 2013-10-28 19:23

回復 2# Charcoal99

因為 i2c 協定我都未係太了解, 呢句係原裝 mark 左做 comment, 我以為作者無用所以照去, 先多謝師兄提點, 等我轉頭試試再爬下文先.





歡迎光臨 電腦領域 HKEPC Hardware (https://h2.hkepc.com/forum/) Powered by Discuz! 7.2