#include<reg51.h>
#include <math.h>
#include"intrins.h"
#define uchar unsigned char
#define uint unsigned int
uchar hour,min,sec,count,hour1,hour2,
sec1,sec2,min1,min2,keystopc,temp;
sbit lcden=P2^7;
sbit lcdrw=P2^6;
sbit lcdrs=P2^5;
sbit SCL=P1^0; //PCF8591T的 SCL 引腳接于單片機的P1^7引腳上
sbit SDA=P1^1; //PCF8591T的 SDA 引腳接于單片機的P1^6引腳上
//HC-SR04相關I/O設置
sbit TIRG=P3^4; //定義IO口
sbit ECHO=P3^2; //定義IO口
bit flag =0;
unsigned char k;
uchar code table[]={
'0','1','2','3','4','5','6','7','8','9',':','.'};
uint num=0;
float f_temp;
unsigned char ADbuf1,ADbuf2;//設置8位的寄存器用來暫存A/D轉換結果
void init() //定時器初始化
{
count=0;
hour=0; //時
min=0; //分
sec=0; //秒
TMOD=0x01;
TH0=(65536-50000)/256; //TH0=60
TL0=(65536-50000)%256; //TL0=6
TR0=0;
EA=0;
ET0=0;
}
void delay(uint z) //延時程序
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/**************************************************************
LCD1602顯示函數
*************************************************************/
void write_com(uchar com) //寫命令函數
{
lcdrs=0;
P0=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_data(uchar date) //寫數據函數
{
lcdrs=1;
P0=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void init_1602() //初始化1602
{
lcden=0;
lcdrw=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
}
void write_Char(unsigned char x,unsigned char y,unsigned char date) //在1602上顯示數據位置
{
if (y == 0)
{
write_com(0x80 + x);
}
else
{
write_com(0xC0 + x);
}
write_data(date);
}
void display(uchar hour1,uchar hour2,uchar min1,uchar min2,uchar sec1,uchar sec2) //顯示程序
{
write_Char(4,1,table[hour1]);
write_Char(5,1,table[hour2]);
write_Char(6,1,table[0x0a]);
write_Char(7,1,table[min1]);
write_Char(8,1,table[min2]);
write_Char(9,1,table[0x0a]);
write_Char(10,1,table[sec1]);
write_Char(11,1,table[sec2]);
}
// 計時器/定時器0
void count0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
count++;
if(count==20)
{
count=0;
sec++;
if(sec==60)
{
sec=0;
min++;
if(min==60)
{
min=0;
hour++;
if(hour==12)
{
hour=0;
}
}
}
}
}
//名稱:生IIC啟動信號函數
void IICstart(void)
{
SDA=1; //先將SDA=1,以準備在SCL=1時,將SDA=0
SCL=1; //時鐘總線拉高
_nop_(); //略做延時
_nop_(); //略做延時
SDA=0; //SCL=1時,將SDA拉低即產生啟動信號
_nop_(); //略做延時
_nop_(); //略做延時
SCL=0; //將SCL=0,完成啟動信號操作
}
//名稱:IIC停止信號函數
void IICstop(void)
{
SDA=0; //先將SDA=0,以準備在SCL=1時,將SDA=1
SCL=1; //時鐘總線拉高
_nop_(); //略做延時
_nop_(); //略做延時
SDA=1; //SCL=1時,將SDA拉高即產生停止信號
_nop_(); //略做延時
_nop_(); //略做延時
SCL=0; //將SCL=0,完成啟動信號操作
}
//名稱:向IIC總線寫入1個字節函數
void Write1Byte(unsigned char Buf1)
{
unsigned char k; //1個字節要分8次寫入,需要定義一個寄存器用來計數
for(k=0;k<8;k++) //做一個8次的循環,每次寫入1位,需要寫8次
{
if(Buf1&0x80) //從最高位開始寫
{
SDA=1; //如果欲寫入數據為1,就將數據線置1
}
else
{
SDA=0; //如果欲寫入數據為0,就將數據線寫0
}
_nop_(); //略做延時
_nop_(); //略做延時
SCL=1; //時鐘線做一個上升沿,將一位數據寫入
Buf1=Buf1<<1; //數據左移一位,將下次要寫入的位數據移到最高位
_nop_(); //略做延時
SCL=0; //將SCL=0,以準備通過上升沿將數據寫入
_nop_(); //略做延時
}
SDA=1; //將SDA=1,準備讀應答信號
_nop_(); //略做延時
SCL=1; //將SCL=1,做個上升沿準備讀應答信號
_nop_(); //略做延時
_nop_(); //略做延時
SCL=0; //將SCL=0,結束應答信號讀操作
}
//名稱:從IIC總線讀入1個字節函數
unsigned char Read1Byte(void)
{
unsigned char k; //1個字節要分8次讀出,需要定義一個寄存器用來計數
unsigned char t=0; //定義一個寄存器用保存讀出數據
for(k=0;k<8;k++) //做一個8次的循環,每次讀入1位,需要讀8次
{
t=t<<1; //數據左移一位,空出最低位以準備保存讀入的一位數據
SDA=1; //將SDA寫1準備讀
SCL=1; //將SCL=1,做個上升沿準備讀一位數據
_nop_(); //略做延時
_nop_(); //略做延時
if(SDA==1) //讀一位數據,并判斷
{
t=t|0x01; //如果讀入數據為1,就將接收緩沖區最低一位置1
}
else
{
t=t&0xfe; //如果讀入數據為0,就將接收緩沖區最低一位寫0
}
SCL=0; //SCL恢復為0,結束一位數據讀操作
_nop_(); //略做延時
_nop_(); //略做延時
}
return t; //將讀入的一個字節返回
}
//名稱:軟件模擬IIC向PCF8591指定地址寫一個字節函數
void WritePCF8591(unsigned char Databuf)
{ //直接調用本函數即可啟動PCF8591的D/A轉換
IICstart(); //IIC啟動信號
Write1Byte(0x90); //發送PCF8591的器件地址和寫信號
Write1Byte(0x40); //發送器件子地址
Write1Byte(Databuf); //發送數據
IICstop(); //產生IIC停止信號
}
//名稱:軟件模擬IIC從PCF8563指定地址讀一個字節函數
unsigned ReadPCF8591(unsigned char Ch)
{ //直接調用本函數即可從PCF8591的Ch通道讀出數據返回
unsigned char buf; //定義一個寄存器用來暫存讀出的數據
IICstart(); //IIC啟動信號
Write1Byte(0x90); //發送PCF8591的器件地址和寫信號
Write1Byte(0x40|Ch); //發送器件通道參數Ch=0-3
IICstart(); //IIC啟動信號
Write1Byte(0x91); //發送PCF8591的器件地址和讀信號
buf=Read1Byte();//讀一個字節數據
IICstop(); //產生IIC停止信號
return(buf); //將讀出數據返回
}
/*********************************1602數據顯示函數88*********************************/
void dis_guangzhao(uchar t)
{
uchar i;
t=t*100/255;
i=t/100;
write_com(0x80+0x07); //顯示光照百位
write_data(table[i]);
i=t%100/10;
write_com(0x80+0x08); //顯示光照十位
write_data(table[i]);
i=t%100%10;
write_com(0x80+0x09); //顯示光照個位
write_data(table[i]);
}
/**************************************************************
主函數
*************************************************************/
void main()
{
unsigned char b=255;
unsigned char a;
init();
init_1602();
delay(1000);
delay(1000);
while(1)
{
delay(1000);
ADbuf1=ReadPCF8591(0); //將AIN0通道A/D轉換結果暫存在ADbuf
dis_guangzhao(b-ADbuf1);
delay(1000);
delay(1000); //延時等待
a=b-ADbuf1;
if(a>=80)
{
//init();
delay(1000);
TR0=1;
EA=1;
ET0=1;
hour1=hour/10;
hour2=hour%10;
min1=min/10;
min2=min%10;
sec1=sec/10;
sec2=sec%10;
display(hour1,hour2,min1,min2,sec1,sec2); //一直顯示時鐘
}
}
}
|