作者: 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既資料, 係唔係我理解錯左呢?
- #include<reg52.h>
- #include<intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define Delay4us(){_nop_();_nop_();_nop_();_nop_();}
- sbit LCD_RS=P2^0;
- sbit LCD_RW=P2^1;
- sbit LCD_EN=P2^2;
- sbit SCL=P1^0; //I2C時鐘引腳
- sbit SDA=P1^1; //I2C資料登錄輸出引腳
- uchar Recv_Buffer[4]; //資料接收緩衝
- uint Voltage[]={'0','0','0','0'}; //資料分解為電壓x.xx
- bit bdata IIC_ERROR; //I2C錯誤標誌位元
- uchar LCD_Line_1[]={" . V "};
- //延時
- void delay(int ms)
- {
- uchar i;
- while(ms--) for(i=0;i<250;i++) Delay4us();
- }
- //LCD忙檢測
- bit LCD_Busy_Check()
- {
- bit Result;
- LCD_RS=0;
- LCD_RW=1;
- LCD_EN=1;
- Delay4us();
- Result=(bit)(P3&0x80);
- LCD_EN=0;
- return Result;
- }
- //寫指令
- void LCD_Write_Command(uchar cmd)
- {
- while(LCD_Busy_Check());
- LCD_RS=0;
- LCD_RW=0;
- LCD_EN=0;
- _nop_();
- _nop_();
- P3=cmd;
- Delay4us();
- LCD_EN=1;
- Delay4us();
- LCD_EN=0;
- }
- // 寫數據
- void LCD_Write_Data(uchar dat)
- {
- while(LCD_Busy_Check());
- LCD_RS=1;
- LCD_RW=0;
- LCD_EN=0;
- P3=dat;
- Delay4us();
- LCD_EN=1;
- Delay4us();
- LCD_EN=0;
- }
- //初始化
- void LCD_Initialise()
- {
- LCD_Write_Command(0x38);
- delay(5);
- LCD_Write_Command(0x0c);
- delay(5);
- LCD_Write_Command(0x06);
- delay(5);
- LCD_Write_Command(0x01);
- delay(5);
- }
- //設置顯示位置
- void LCD_Set_Position(uchar pos)
- {
- LCD_Write_Command(pos|0x80);
- }
- //顯示一行
- void LCD_Display_A_Line(uchar Line_Addr,uchar s[])
- {
- uchar i;
- LCD_Set_Position(Line_Addr);
- for(i=0;i<16;i++)LCD_Write_Data(s[i]);
- }
- // 將模數轉換後得到的值分解存入緩存
- void Convert_To_Voltage(uchar val)
- {
- uchar Tmp; //最大值為255,對應5V,255/5=51
- Voltage[2]=val/51+'0'; //整數部分
- Tmp=val%51*10; // 第一位小數
- Voltage[1]=Tmp/51+'0';
- Tmp=Tmp%51*10;
- Voltage[0]=Tmp/51+'0';
- }
- //啟動I2C匯流排
- void IIC_Start()
- {
- SDA=1;
- SCL=1;
- Delay4us();
- SDA=0;
- Delay4us();
- SCL=0;
- }
- //停止I2C匯流排
- void IIC_Stop()
- {
- SDA=0;
- SCL=1;
- Delay4us();
- SDA=1;
- Delay4us();
- SCL=0;
- }
- // 從機發送應答位
- void Slave_ACK()
- {
- SDA=0;
- SCL=1;
- Delay4us();
- SCL=0;
- SDA=1;
- }
- // 從機發送非應答位
- void Slave_NOACK()
- {
- SDA=1;
- SCL=1;
- Delay4us();
- SCL=0;
- SDA=0;
- }
- //發送一位元組
- void IIC_SendByte(uchar wd)
- {
- uchar i;
- for(i=0;i<8;i++) //迴圈移入8位
- {
- SDA=(bit)(wd&0x80);
- _nop_();
- _nop_();
- SCL=1;
- Delay4us();
- SCL=0;
- wd<<=1;
- }
- Delay4us();
- SDA=1; //釋放匯流排並準備讀取應答
- SCL=1;
- Delay4us();
- IIC_ERROR=SDA; //IIC_ERROR=1表示無應答
- SCL=0;
- Delay4us();
- }
- //接收一位元組
- uchar IIC_ReceiveByte()
- {
- uchar i,rd=0x00;
- for(i=0;i<8;i++)
- {
- SCL=1;
- rd<<=1;
- rd|=SDA;
- Delay4us();
- SCL=0;
- Delay4us();
- }
- SCL=0;
- Delay4us();
- return rd;
- }
- //連續讀入4路通道的A/D轉換結果並保存到Recv_Buffer
- void ADC_PCF8591(uchar CtrlByte)
- {
- uchar i;
- IIC_Start();
- IIC_SendByte(0x90); //發送寫地址
- if(IIC_ERROR==1)return;
- //IIC_SendByte(CtrlByte); //發送控制位元組
- //if(IIC_ERROR==1)return;
- IIC_Start(); //重新發送開始命令
- IIC_SendByte(0x91); //發送讀地址
- if(IIC_ERROR==1)return;
- IIC_ReceiveByte(); //空讀一次,調整讀順序
- Slave_ACK(); //收到一位元組後發送一個應答位元
- for(i=0;i<4;i++)
- {
- Recv_Buffer[i++]=IIC_ReceiveByte();
- Slave_ACK(); //收到一個位元組後發送一個應答位元
- }
- Slave_NOACK();
- IIC_Stop(); //收到一個位元組後發送一個非應答位
- }
- //向 PCF8591發送1位元組進行AD轉換
- //主程序
- void main()
- {
- LCD_Initialise();
- while(1)
- {
- ADC_PCF8591(0x04);
- Convert_To_Voltage(Recv_Buffer[0]);
- LCD_Line_1[2]=Voltage[2];
- LCD_Line_1[4]=Voltage[1];
- LCD_Line_1[5]=Voltage[0];
- LCD_Display_A_Line(0x00, LCD_Line_1);
-
- }
- }
作者: 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, 我以為作者無用所以照去, 先多謝師兄提點, 等我轉頭試試再爬下文先.
