|
用12864顯示,AD芯片采用IIC通訊方式,需要用多路時要做小許修改。
- #include<reg52.h>
- #include<intrins.h>
- //P0口為12864數據輸出口
- #define uchar unsigned char
- #define uint unsigned int
- #define Delay4us(){_nop_();_nop_();_nop_();_nop_();}
- sbit LCD_RS=P2^6;
- sbit LCD_RW=P2^5;
- sbit LCD_EN=P2^7;
- sbit PM=P1^0;
- sbit SCL=P1^1; //I2C時鐘引腳
- sbit SDA=P1^2;//I2C數據輸入輸出引腳
- uchar Recv_Buffer[4];//數據接收緩沖
- uint Voltage[]={'0','0','0'};//數據分解為電壓x.xx
- bit bdata IIC_ERROR; //I2C錯誤標志位
- uchar LCD_Line_1[]={"1- . V 2- . V"};
- uchar LCD_Line_2[]={"3- . V 4- . 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)(P0&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_();
- P0=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;P0=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);
- LCD_Write_Command(pos);
- }
- //顯示一行
- 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();
- //PCF8591地址定義1001****,高四位固定1001
- //第3,2,1位對應A2,A1,A0第0位為讀寫標志位,1為讀0為寫
- //下面代碼中0x90,0x91分別為10010000,10010001
-
- 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(); //收到一字節后發送一個應答位
- /*------------------------------
- 個人認為下面句子有問題,但是不知道怎么改,如果把
- Recv_Buffer[i++]=IIC_ReceiveByte();中的++去掉,整個四組都是一個結果
- 但是加上好像有些重復,并且13組相同,還是不很好啊
- */
- for(i=0;i<4;i++)
- {
- Recv_Buffer[i++]=IIC_ReceiveByte();
- Slave_ACK();//收到一個字節后發送一個應答位
- }
- Slave_NOACK();
- IIC_Stop();//收到一個字節后發送一個非應答位
- }
- // 向 PCF8591發送1字節進行AD轉換
- void DAC_PCF8591(uchar CtrlByte,uchar dat)
- {
- IIC_Start();
- Delay4us();//啟動I2C
- IIC_SendByte(0x90); //發送地址字節
- if(IIC_ERROR==1)return;
- IIC_SendByte(CtrlByte); //發送控制字節
- if(IIC_ERROR==1)return;
- IIC_SendByte(dat);//發送待轉換為模擬量的數值
-
- if(IIC_ERROR==1)return;
- IIC_Stop();
- Delay4us();
- Delay4us();
- }
- void timer0init()
- {
- PM=0;//傳感器的輸入信號
- TMOD=0x11;//設置定時器0為工作方式1
- TH0=(65536-40)/256;
- TL0=(65536-40)%256;
- ET0=1;//開定時器0中斷
- TR0=1;//啟動定時器0
- EA=0; //開總中斷
- }
- //主程序
- /*
- PCF8591控制字節定義:0***0***,第3,7位固定為0
- 第6位取0時為模擬輸入,取1時為模擬輸出
- 第4,5位為00表示4路單端的模擬輸入
- 第二位為自動遞增標志,取1時自動遞增
- 第0,1位取值為00,01,10,11分別表示通道0,1,2,3
- 調用ADC_PCF8591時參數為00000100,即0x04
- 調用DAC_PCF8591時參數為01000000,即0x40
- */
- void main()
- {
- LCD_Initialise();
- timer0init();
- 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];
- Convert_To_Voltage(Recv_Buffer[1]);
- LCD_Line_1[11]=Voltage[2];
- LCD_Line_1[13]=Voltage[1];
- LCD_Line_1[14]=Voltage[0];
- Convert_To_Voltage(Recv_Buffer[2]);
- LCD_Line_2[2]=Voltage[2];
- LCD_Line_2[4]=Voltage[1];
- LCD_Line_2[5]=Voltage[0];
- Convert_To_Voltage(Recv_Buffer[3]);
- LCD_Line_2[11]=Voltage[2];
- LCD_Line_2[13]=Voltage[1];
- LCD_Line_2[14]=Voltage[0];
- // 液晶兩行顯示四個通道的轉換結果
- LCD_Display_A_Line(0x80, LCD_Line_1);
- LCD_Display_A_Line(0x90, LCD_Line_2);
- // 將0通道模擬轉換后的數值重新轉換為模擬量并從Aout輸出
-
- //通過LED亮度表現出來
- // DAC_PCF8591(0x40,Recv_Buffer[0]);
- }
- }
- void timer0() interrupt 1
- {
- int N;
- TH0=(65536-40)/256;
- TL0=(65536-40)%256;
- N++;
- //if(N==7)
- //PM=1;
- if(N==8)
- PM=0;
- if(N>=250)
- {
- PM=1;
- N=0;
- }
- }
-
復制代碼
|
-
-
pcf8591.zip
2018-6-18 13:05 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
2.4 KB, 下載次數: 12, 下載積分: 黑幣 -5
主要文件,工程需自建
|