|
#include<reg51.h> //加載頭文件 #include<intrins.h> #define uchar unsigned char //宏定義 #define uint unsigned int #define AddWr 0x90 //PCF8591地址 #define LCD_DATA P0 //液晶數(shù)據(jù)口定義 #define RS_CLR LCD_RS=0 //液晶控制口宏定義 #define RS_SET LCD_RS=1 #define RW_CLR LCD_RW=0 #define RW_SET LCD_RW=1 #define EN_CLR LCD_EN=0 #define EN_SET LCD_EN=1 sbit LCD_RS=P2^7; //液晶控制口定義 sbit LCD_RW=P2^6; sbit LCD_EN=P2^5; sbit SCL=P2^2; //I2C時(shí)鐘-PCF8591 sbit SDA=P2^1; //I2C數(shù)據(jù)-PCF8591 sbit lamp=P2^3;//燈 sbit k1=P1^2;//按鈕 sbit k2=P1^3; int light=0; //光照度變量 uchar dis; //ADC用變量 uint limit=100;//光強(qiáng) uint time=0; uint pwm=0,sec=0; bit ack; //應(yīng)答標(biāo)志位 void Delay_US(uchar t) //US延時(shí)函數(shù) { while(--t); } void Delay_MS(uchar t) //MS延時(shí)函數(shù) { while(t--) { Delay_US(245); Delay_US(245); } } void Lcd_W_Com(uchar com) //液晶寫指令函數(shù) { RS_CLR; RW_CLR; LCD_DATA=com; Delay_MS(1); EN_SET; Delay_MS(1); EN_CLR; } void Lcd_W_Dat(uchar dat) //液晶寫數(shù)據(jù)函數(shù) { RS_SET; RW_CLR; LCD_DATA=dat; Delay_MS(1); EN_SET; Delay_MS(1); EN_CLR; } void Lcd_Clr_Scr() //液晶清屏函數(shù) { Lcd_W_Com(0x01); Delay_MS(5); } void Lcd_Show_String(uchar x,uchar y,uchar *s) //液晶顯示字符串函數(shù) { if(y==0) Lcd_W_Com(0x80+x); //表示第一行 else Lcd_W_Com(0xC0+x); //表示第二行 while(*s) { Lcd_W_Dat(*s); s++; } } void Lcd_Show_Char(uchar x,uchar y,uchar dat) //液晶寫字符函數(shù) { if(y==0) Lcd_W_Com(0x80+x); else Lcd_W_Com(0xC0+x); Lcd_W_Dat(dat); } void Lcd_Init() //液晶初始化函數(shù) { Lcd_W_Com(0x38); //顯示模式設(shè)置 Lcd_W_Com(0x08); //顯示關(guān)閉 Lcd_W_Com(0x01); //顯示清屏 Lcd_W_Com(0x06); //顯示光標(biāo)移動(dòng)設(shè)置 Lcd_W_Com(0x0C); //顯示開及光標(biāo)設(shè)置 } void IIC_Start() //總線啟動(dòng)函數(shù) { SDA=1; //發(fā)送起始條件的數(shù)據(jù)信號(hào) _nop_(); SCL=1; _nop_(); //起始條件建立時(shí)間大于4.7us,延時(shí) _nop_(); _nop_(); _nop_(); _nop_(); SDA=0; //發(fā)送起始信號(hào) _nop_(); //起始條件鎖定時(shí)間大于4μs _nop_(); _nop_(); _nop_(); _nop_(); SCL=0; //鉗住I2C總線,準(zhǔn)備發(fā)送或接收數(shù)據(jù) _nop_(); _nop_(); } void IIC_Stop() //總線結(jié)束函數(shù) { SDA=0; //發(fā)送結(jié)束條件的數(shù)據(jù)信號(hào) _nop_(); //發(fā)送結(jié)束條件的時(shí)鐘信號(hào) SCL=1; //結(jié)束條件建立時(shí)間大于4μs _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); SDA=1; //發(fā)送I2C總線結(jié)束信號(hào) _nop_(); _nop_(); _nop_(); _nop_(); } void IIC_Send_Byte(uchar c) //IIC發(fā)送字節(jié)函數(shù) { uchar i; for(i=0;i<8;i++) //要傳送的數(shù)據(jù)長(zhǎng)度為8位 { if((c<<i)&0x80) SDA=1; //判斷發(fā)送位 else SDA=0; _nop_(); SCL=1; //置時(shí)鐘線為高,通知被控器開始接收數(shù)據(jù)位 _nop_(); _nop_(); //保證時(shí)鐘高電平周期大于4μs _nop_(); _nop_(); _nop_(); SCL=0; } _nop_(); _nop_(); SDA=1; //8位發(fā)送完后釋放數(shù)據(jù)線,準(zhǔn)備接收應(yīng)答位 _nop_(); _nop_(); SCL=1; _nop_(); _nop_(); _nop_(); if(SDA==1) ack=0; else ack=1; //判斷是否接收到應(yīng)答信號(hào) SCL=0; _nop_(); _nop_(); } uchar IIC_Receive_Byte() //IIC接收字節(jié)函數(shù) { uchar retc=0,i; SDA=1; //置數(shù)據(jù)線為輸入方式 for(i=0;i<8;i++) { _nop_(); SCL=0; //置時(shí)鐘線為低,準(zhǔn)備接收數(shù)據(jù)位 _nop_(); _nop_(); //時(shí)鐘低電平周期大于4.7μs _nop_(); _nop_(); _nop_(); SCL=1; //置時(shí)鐘線為高使數(shù)據(jù)線上數(shù)據(jù)有效 _nop_(); _nop_(); retc=retc<<1; if(SDA==1) retc=retc+1; //讀數(shù)據(jù)位,接收的數(shù)據(jù)位放入retc中 _nop_(); _nop_(); } SCL=0; _nop_(); _nop_(); return(retc); } void IIC_Ack(bit a) //IIC應(yīng)答函數(shù) { if(a==0) SDA=0; //在此發(fā)出應(yīng)答或非應(yīng)答信號(hào) else SDA=1; //0為發(fā)出應(yīng)答,1為非應(yīng)答信號(hào) _nop_(); _nop_(); _nop_(); SCL=1; _nop_(); _nop_(); //時(shí)鐘低電平周期大于4μs _nop_(); _nop_(); _nop_(); SCL=0; //清時(shí)鐘線,住I2C總線以便繼續(xù)接收 _nop_(); _nop_(); } bit Pcf_Send_Byte(uchar addr,uchar channel) //PCF8591寫一個(gè)控制指令 { //addr(器件地址),channel(轉(zhuǎn)換通道) IIC_Start(); //啟動(dòng)總線 IIC_Send_Byte(addr); //發(fā)送器件地址 if(ack==0) return(0); IIC_Send_Byte(0x40|channel); //發(fā)送控制字節(jié) if(ack==0) return(0); IIC_Stop(); //結(jié)束總線 return(1); } uchar Pcf_Receive_Byte(uchar addr) //PCF8591讀取一個(gè)轉(zhuǎn)換值 { uchar dat; IIC_Start(); //啟動(dòng)總線 IIC_Send_Byte(addr+1); //發(fā)送器件地址 if(ack==0) return(0); dat=IIC_Receive_Byte(); //讀取數(shù)據(jù)0 IIC_Ack(1); //發(fā)送非應(yīng)答信號(hào) IIC_Stop(); //結(jié)束總線 return(dat); } //主函數(shù) void main() { Lcd_Init(); //液晶初始化 Lcd_Clr_Scr(); //液晶清屏 Lcd_Show_String(1,0,"Light"); //液晶顯示固定字符 Lcd_Show_String(13,0,"lx"); Lcd_Show_String(1,1,"lim"); Lcd_Show_String(13,1,"lx"); TMOD|=0X01; TH0=0X3C; TL0=0XB0; ET0=1;//打開定時(shí)器0中斷允許 EA=1;//打開總中斷 TR0=1;//打開定時(shí)器 while(1) { if(!k1)//加 { limit++; while(!k1); } if(!k2)//減 { limit--; while(!k2); } //PWM if(sec<99) sec++; else sec=1; if(pwm<sec) lamp=1; else lamp=0; } } //定時(shí)器0中斷 void Timer0() interrupt 1 { if(time<10)//定時(shí)0.5s time++; else { time=0; Pcf_Send_Byte(AddWr,0); dis=Pcf_Receive_Byte(AddWr); //ADC0 模數(shù)轉(zhuǎn)換0 光敏電阻 light=-39*dis+10000; Lcd_Show_Char(7,0,light/10000+'0'); //光照度顯示 萬(wàn) Lcd_Show_Char(8,0,light%10000/1000+'0'); //千 Lcd_Show_Char(9,0,light%1000/100+'0'); //百 Lcd_Show_Char(10,0,light%100/10+'0'); //十 Lcd_Show_Char(11,0,light%10+'0'); // 個(gè) Lcd_Show_Char(7,1,light%10000/1000+'0'); //千 Lcd_Show_Char(8,1,limit/100+0x30); // 百 Lcd_Show_Char(9,1,limit%100/10+0x30); // 十 Lcd_Show_Char(10,1,limit%10+0x30); // 個(gè) if(light>limit)//功能1 { pwm=0; } else { pwm=99-light*100/limit;//輸出PWM占空比,光照強(qiáng)度越低,pwm占空比越大 } } TH0=0X3C; TL0=0XB0; } |
|