|
爱科技、爱创意、爱折腾、爱极致,我们都是技术控
您需要 登录 才可以下载或查看,没有账号?立即注册
x
请大神帮助谢谢啧啧啧!!!!
//#include <at89c52.h>
#include <intrins.h>
#include <reg52.H>
#define DataPort P0
unsigned char code one[] = "20 / / "; //固定字符
unsigned char code two[] = " : : "; //固定字符
unsigned char code wendu[] = {0x18, 0x1a, 0x05, 0x04, 0x04, 0x05, 0x02, 0x00};//温度符号
unsigned char code week_char[] = "MON TUE WED THU FRI STA SUN"; //星期字符串
unsigned char miao, fen, shi, ri, yue, nian, week;
unsigned int tp;
bit time_flag, temp_flag;
/******************************
LCD1602
4PIN----RS
5PIN----RW
6PIN----EN
*****************************/
sbit beep = P1^0; //蜂鸣器
sbit DQ = P2^3; //18B20端口
sbit RS = P2^5; //1602寄存器选择
sbit RW = P2^6; //1602读写控制
sbit EN = P2^7; //1602使能端
sbit key1 = P1^5; //菜单键
sbit key2 = P1^6; //加
sbit key3 = P1^7; //减
sbit RST = P3^2; //1302复位
sbit SDA = P3^3; //1302数据
sbit SCK = P3^4; //1302时钟
void delay_us(unsigned char t)
{
while(--t);
}
/***********ms延时程序***********/
void delay_ms(unsigned int ms)
{
unsigned int a, b;
for(a = ms; a > 0; a--)
for(b = 110; b > 0; b--);
}
/********蜂鸣器响一声**********/
void beepplay()
{
beep = 0;
delay_ms(60);
beep = 1;
}
/*********LCD判忙*************/
void lcd_busy()
{
DataPort = 0xff;
RS = 0;
RW = 1;
EN = 1;
delay_ms(1);
while(DataPort & 0x80);
EN = 0;
}
/**********LCD写数据************/
void write_date(unsigned char dat)
{
lcd_busy();
RS = 1;
RW = 0;
DataPort = dat;
delay_ms(2);
EN = 1;
delay_ms(2);
EN = 0;
}
/*********LCD写指令***********/
void write_com(unsigned char com)
{
lcd_busy();
RS = 0;
RW = 0;
DataPort = com;
delay_ms(2);
EN = 1;
delay_ms(2);
EN = 0;
}
/*********LCD初始化*************/
void initLCD()
{
unsigned char i;
delay_ms(5); //延时启动,等待电压稳定
write_com(0x38); //设置16*2显示,5*7点阵,8位数据口
write_com(0x0c); //设置开显示,不显示光标
write_com(0x06); //写一个字符地址指针加1
write_com(0x01); //清屏
delay_ms(1); //第一行起始地址0x80,第二行起始地址0xc0
write_com(0x81); //第一行首空一个字符,开始写入第一行固定字符
for(i = 0; i < 10; i++)
write_date(one[i]);
delay_ms(1);
write_com(0xc2); //第二行首空两个字符,开始写入第二行的固定字符
for(i = 0; i < 8; i++)
write_date(two[i]);
write_com(0xcd); //显示地址
write_date('.'); //显示"."
write_date(0x20); //0x20显示就是空
// write_date('C'); //显示C
write_com(0x40);
for(i = 0; i < 8; i++)
write_date(wendu[i]);
write_com(0xcf);
write_date(0x00);
}
/*********10转BCD**********/
unsigned char toBCD(unsigned char dat)
{
unsigned char tmp;
tmp=(((dat / 10) * 16)+(dat % 10));
return(tmp);
}
/**********DS1302写一个字节*********/
void writebyte(unsigned char dat)
{
unsigned char i;
for(i = 0; i < 8; i++)
{
SDA = dat & 0x01;
SCK = 1;
_nop_();_nop_();
SCK = 0;
dat >>= 1;
}
}
/********写DS1302寄存器********/
void write1302(unsigned char dizhi,shuju)
{
RST = 0;
SCK = 0;
RST = 1;
writebyte(dizhi); //写入的地址
writebyte(shuju); //写入的数据
SCK = 1;
RST = 0;
}
/*******读取DS1302寄存器********/
unsigned char read1302(unsigned char dizhi)
{
unsigned char i, dat, tmp;
RST = 0;
SCK = 0;
RST = 1;
writebyte(dizhi | 0x01);
for(i = 8; i > 0; i--)
{
dat >>= 1;
if(SDA)
dat |= 0x80;
SCK=1;
_nop_();_nop_();
SCK=0;
}
RST = 0;
tmp = dat >> 4;
tmp = ((tmp * 10)+(dat &= 0x0f));
return(tmp);
}
/*******DS18B20初始化*********/
void init1820()
{
DQ = 1;
_nop_();_nop_();
DQ = 0;
delay_us(200);
delay_us(200);
DQ = 1;
delay_us(80);
DQ = 1;
}
/*******向DS18B20中读出一个字节*********/
unsigned char readonebyte_18b20()
{
unsigned char i=0, dat=0;
for(i = 8; i > 0; i--)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
dat |= 0x80;
delay_us(25);
}
return(dat);
}
/******向DS18B20中写入一个字节*******/
void writeonebyte_18b20(unsigned char dat)
{
unsigned char i=0;
for(i = 8; i > 0; i--)
{
DQ = 0;
DQ = dat & 0x01;
delay_us(25);
DQ = 1;
dat >>= 1;
}
delay_us(25);
}
/*********读取温度*********/
unsigned int readtemp(void)
{
unsigned int xx, tempL=0, tempH=0;
init1820();
writeonebyte_18b20(0xcc);
writeonebyte_18b20(0x44);
delay_us(100);
init1820();
writeonebyte_18b20(0xcc);
writeonebyte_18b20(0xbe);
tempL = readonebyte_18b20();
tempH = readonebyte_18b20();
tempH <<= 8;
xx = tempL | tempH;
return(xx);
}
/********显示函数*********/
void display(unsigned char dizhi, dat)
{
unsigned char a, b;
a = dat / 10; //取得十位数字
b = dat % 10; //取得个位数字
write_com(dizhi); //设定显示的地址
write_date(a + 0x30); //数字+0x30得到该数字的LCD1602显示码
write_date(b + 0x30);
}
/***********温度显示函数**************/
void display_wendu(unsigned char dizhi, dat)
{
write_com(dizhi);
write_date(dat);
}
/**********显示周字符**********/
void display_week(unsigned char week)
{
unsigned char i;
write_com(0x8d); //设置星期显示地址
switch(week)
{
case 1: for(i = 0; i < 3; i++)
write_date(week_char[i]);break;
case 2: for(i = 4; i < 7; i++)
write_date(week_char[i]);break;
case 3: for(i = 8; i < 11; i++)
write_date(week_char[i]);break;
case 4: for(i = 12; i < 15; i++)
write_date(week_char[i]);break;
case 5: for(i = 16; i < 19; i++)
write_date(week_char[i]);break;
case 6: for(i = 20; i < 23; i++)
write_date(week_char[i]);break;
case 7: for(i = 24; i < 27; i++)
write_date(week_char[i]);break;
}
}
/*********按键扫描********/
void keyscan()
{
unsigned char num;
if(key1 == 0) //判断key1是不是按下
{
delay_ms(20); //按键消抖
if(key1 == 0) //再次检测key1是否按下
{
beepplay();
while(!key1); //等待key1释放
num++;
switch(num)
{
case 1: TR0 = 0; //关闭中断
temp_flag = 0;
time_flag = 0;
write1302(0x8e, 0x00); //允许写入DS1302
write1302(0x80, 0x80); //时间暂停
write_com(0x0f); //设置光标闪烁
write_com(0xc9);break; //秒钟闪烁地址
case 2: write_com(0xc6);break; //分闪烁地址
case 3: write_com(0xc3);break; //时闪烁地址
case 4: write_com(0x8f);break; //星期闪烁地址
case 5: write_com(0x8a);break; //日闪烁地址
case 6: write_com(0x87);break; //月闪烁地址
case 7: write_com(0x84);break; //年闪烁地址
case 8: write_com(0x0c); //设置光标不闪烁
write1302(0x90,0xa9); //充电
write1302(0x8c, toBCD(nian));
write1302(0x86, toBCD(ri));
write1302(0x88, toBCD(yue));
write1302(0x8a, toBCD(week));
write1302(0x84, toBCD(shi));
write1302(0x82, toBCD(fen));
write1302(0x80, toBCD(miao)); //写入秒
write1302(0x8e, 0x80); //禁止写入DS1302
num = 0;TR0 = 1;break; //定时器打开计数清零
}
}
}
if(num != 0) //i>0,按键key2,key3无效
{
if(key2 == 0)
{
delay_ms(20);
if(key2 == 0)
{
beepplay();
while(!key2); //等待释放
switch(num)
{
case 1: miao++;if(miao >= 60)miao = 0; //秒++
display(0xc8, miao); //显示秒
write_com(0xc9);break; //因为显示地址指针自动加1,重新定义秒的地址
case 2: fen++;if(fen == 60)fen = 0; //分++
display(0xc5, fen); //显示当前调入分数据
write_com(0xc6);break;
case 3: shi++;if(shi == 24)shi = 0;
display(0xc2, shi);
write_com(0xc3);break;
case 4: week++;if(week == 8)week = 1;
display_week(week);
write_com(0x8f);break;
case 5: ri++;if(ri == 32)ri = 1;
display(0x89, ri);
write_com(0x8a);break;
case 6: yue++;if(yue == 13)yue = 1;
display(0x86, yue);
write_com(0x87);break;
case 7: nian++;if(nian == 100)nian = 0;
display(0x83, nian);
write_com(0x84);break;
}
}
}
if(key3==0) //按键0有效,判断key3按下是不是0
{
delay_ms(20); //按键消抖
if(key3==0)
{
beepplay(); //调用蜂鸣器响一声
while(!key3); //等待释放key3
switch(num)
{
case 1: miao--;if(miao == 255 | miao > 60)miao = 59; //减1,减到0再减1就是255
display(0xc8, miao);
write_com(0xc9);break;
case 2: fen--;if(fen == 255)fen = 59;
display(0xc5, fen);
write_com(0xc6);break;
case 3: shi--;if(shi == 255)shi = 23;
display(0xc2, shi);
write_com(0xc3);break;
case 4: week--;if(week == 0)week = 7;
display_week(week);
write_com(0x8f);break;
case 5: ri--;if(ri == 0)ri = 31;
display(0x89, ri);
write_com(0x8a);break;
case 6: yue--;if(yue == 0)yue = 12;
display(0x86, yue);
write_com(0x87);break;
case 7: nian--;if(nian == 255)nian = 99;
display(0x83, nian);
write_com(0x84);break;
}
}
}
}
}
/***********更新时间***********/
void update_time()
{
if(time_flag == 1)
{
time_flag = 0;
miao = read1302(0x81); //读秒
fen = read1302(0x83); //读分
shi = read1302(0x85); //读时
ri = read1302(0x87); //读日
yue = read1302(0x89); //读月
week = read1302(0x8b); //读周
nian = read1302(0x8d); //读年
display(0xc8, miao); //更新秒
display(0xc5, fen); //更新分
display(0xc2, shi); //更新时
display(0x89, ri); //更新日
display(0x86, yue); //更新月
display(0x83, nian); //更新年
display_week(week); //更新周
}
}
/**********更新温度*********/
void update_temp()
{
unsigned int temp;
if(temp_flag == 1)
{
temp_flag = 0;
temp = readtemp();
tp = temp;
if(tp & 0x8000)
tp = (~tp)+1;
tp = ((tp * 5) >> 3);
if(temp & 0x8000)
{
display_wendu(0xcb, '-');
display_wendu(0xcc, (tp % 100 / 10) + 0x30);
display_wendu(0xce, (tp % 10) + 0x30);
}
else
{
if((tp / 100 % 10) == 0)
display_wendu(0xcb, 0x20);
else
display_wendu(0xcb, (tp / 100 % 10) + 0x30);
display_wendu(0xcc, (tp % 100 / 10) + 0x30);
display_wendu(0xce, (tp % 10) + 0x30);
}
}
}
/********定时器初始化************/
void init_Time0()
{
TMOD = 0x01; //设置定时器工作模式
TH0 = 0;
TL0 = 0;
EA = 1; //开总中断
ET0 = 1; //开定时器0中断
TR0 = 1; //启动定时器
}
/**********主函数*************/
void main()
{
initLCD(); //初始化LCD
init_Time0(); //初始化定时器
while(1)
{
keyscan(); //键盘扫描
update_time(); //更新时间
update_temp(); //更新温度
}
}
/************中断程序***************/
void Time0()interrupt 1 //中断程序不易过多
{
static unsigned char x, y;
TH0 = (65536-10000) / 256; //赋值10ms
TL0 = (65536-10000) % 256;
x++;
if(x == 10)
{
x = 0; y++;
time_flag = 1;
if(y == 5)
{
y = 0;
temp_flag = 1;
}
}
}
|
|