/*------------------------------------------------------------------------------------------
名称:12864万历时钟
内容:显示年月日、24小时、星期、所在年份、实时温度基本功能,带1路可设置闹钟;亮屏20s自动熄灭
晶振:12MHZ
单片机:AT89S52
显示屏:12864带中文字库
DS18B20数字温度采集
作者:爱好者
交流QQ群:481250892
日期:2017/8/5
////////////////////////////////////////////////////////////////////////////////////////////
按键功能:
sbit k1=P3^0; //单独使用 闹钟响起时关闭闹铃、亮屏
sbit k2=P3^1; //菜单 设置功能键
sbit k3=P3^2; //确认 确认键
sbit k4=P3^3; //+ 加
sbit k5=P3^4; //- 减
备注:当画面处于主页界面:(1)只有k2按键有效。
(2)k3、k4同时按下可快速打开或关闭闹钟
当画面处于设置界面:(1)k2、k3同时按下直接返回主页
////////////////////////////////////////////////////////////////////////////////////////////
12864引脚接线
sbit RS = P2^3;
sbit RW = P2^4;
sbit E = P2^5;
sbit RES = P2^7;
sbit PSB = P2^0;
sbit LCD_led=P1^2; //背光控制
#define DataPort P0 //MCU P0<------> LCD_12864 data
-------------------------------------------------------------------------------------------------*/
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit RS = P2^3;
sbit RW = P2^4;
sbit E = P2^5;
sbit RES = P2^7;
sbit PSB = P2^0;
sbit LCD_led=P1^2; //背光控制
sbit k1=P3^0; //主页面
sbit k2=P3^1; //菜单
sbit k3=P3^2; //确认
sbit k4=P3^3; //+
sbit k5=P3^4; //-
sbit deep=P1^0; //闹钟响铃输出
#define DataPort P0 //MCU P0<------> LCD_12864 data
uchar num,num1=55,num2=59,num3=23,max,wan,qian,bai,shi,ge,nian=17,yue=8,ri=1;
uchar n_num1,n_num2,n_num3;
uchar day=1,k=0,dip=0,flag=0,clok=0,set=0,set_time=0,set_t=0;
uchar t_set=0;
uint tr1_time=0;
//-----------------------------------------------
uchar xdata lcdPosX, lcdPosY; //X,Y坐标
uchar xdata halfScr, halfLineCnt, basicBlock; //半屏,半屏行数,N*8块
//-----------------------------------------------
sbit DQ=P1^1; //18B20数据接口
uchar point,n,temp,flag,aa;
uchar code ditab[16]= {0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09}; //小数补偿
////////////////////////////////////////////////////////////////////////
//设定哪一行,从那一个位置开始到那一个位置结束使用反白
//x=液晶屏上汉字的位置(1~8);end_x=汉字结束的地址(1~8);y=1~4行
//clear=1:清除反白;clear=0:设置反白;
void Set_White(uchar x,uchar y,uchar end_x,uchar clear);
/*------------------------------------------------
uS延时函数,含有输入参数 unsigned char t,无返回值
unsigned char 是定义无符号字符变量,其值的范围是
0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
长度如下 T=tx2+5 uS
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{
while(--t);
}
/*------------------------------------------------
mS延时函数,含有输入参数 unsigned char t,无返回值
unsigned char 是定义无符号字符变量,其值的范围是
0~255 这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
void delay(uint t)
{
uint i,j;
for(i=t;i>0;i--)
for(j=112;j>0;j--);
}
void delays(uint t) //微妙延时
{
for(;t>0;t--);
}
/*---------------------------------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------------------------------*/
unsigned char code sum[11][64]={
{// 图片数字0
0x00,0x00,0x3F,0xFC,0x5F,0xFA,0x6F,0xF6,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x70,0x0E,
0x70,0x0E,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x60,0x06,0x40,0x02,0x00,0x00,
0x40,0x02,0x60,0x06,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x70,0x0E,
0x70,0x0E,0x70,0x0E,0x70,0x0E,0x6F,0xF6,0x5F,0xFA,0x3F,0xFC,0x00,0x00,0x00,0x00},
{// 图片数字1
0x00,0x00,0x00,0x20,0x00,0x60,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,
0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0x60,0x00,0x20,0x00,0x00,0x00,0x20,
0x00,0x60,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,
0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0x60,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00},
{// 图片数字2
0x00,0x00,0x3F,0xFC,0x1F,0xFA,0x0F,0xF6,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,
0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x06,0x1F,0xFA,0x3F,0xFC,
0x5F,0xF8,0x60,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,
0x70,0x00,0x70,0x00,0x70,0x00,0x6F,0xF8,0x5F,0xFC,0x3F,0xFE,0x00,0x00,0x00,0x00},
{// 图片数字3
0x00,0x00,0x3F,0xFC,0x1F,0xFA,0x0F,0xF6,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,
0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x06,0x1F,0xFA,0x3F,0xFC,
0x1F,0xFA,0x00,0x06,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,
0x00,0x0E,0x00,0x0E,0x00,0x0E,0x0F,0xF6,0x1F,0xFA,0x3F,0xFC,0x00,0x00,0x00,0x00},
{// 图片数字4
0x00,0x00,0x40,0x02,0x60,0x06,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x70,0x0E,
0x70,0x0E,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x60,0x06,0x5F,0xFA,0x3F,0xFC,
0x1F,0xFA,0x00,0x06,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,
0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x06,0x00,0x02,0x00,0x00,0x00,0x00},
{// 图片数字5
0x00,0x00,0x3F,0xFC,0x5F,0xF8,0x6F,0xF0,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,
0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x60,0x00,0x5F,0xF8,0x3F,0xFC,
0x1F,0xFA,0x00,0x06,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,
0x00,0x0E,0x00,0x0E,0x00,0x0E,0x0F,0xF6,0x1F,0xFA,0x3F,0xFC,0x00,0x00,0x00,0x00},
{// 图片数字6
0x00,0x00,0x3F,0xFC,0x5F,0xF8,0x6F,0xF0,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,
0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x60,0x00,0x5F,0xF8,0x3F,0xFC,
0x5F,0xFA,0x60,0x06,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x70,0x0E,
0x70,0x0E,0x70,0x0E,0x70,0x0E,0x6F,0xF6,0x5F,0xFA,0x3F,0xFC,0x00,0x00,0x00,0x00},
{// 图片数字7
0x00,0x00,0x3F,0xFC,0x1F,0xFA,0x0F,0xF6,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,
0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x06,0x00,0x02,0x00,0x00,
0x00,0x02,0x00,0x06,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,
0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x06,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00},
{// 图片数字8
0x00,0x00,0x3F,0xFC,0x5F,0xFA,0x6F,0xF6,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x70,0x0E,
0x70,0x0E,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x60,0x06,0x5F,0xFA,0x3F,0xFC,
0x5F,0xFA,0x60,0x06,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x70,0x0E,
0x70,0x0E,0x70,0x0E,0x70,0x0E,0x6F,0xF6,0x5F,0xFA,0x3F,0xFC,0x00,0x00,0x00,0x00},
{// 图片数字9
0x00,0x00,0x3F,0xFC,0x5F,0xFA,0x6F,0xF6,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x70,0x0E,
0x70,0x0E,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x60,0x06,0x5F,0xFA,0x3F,0xFC,
0x1F,0xFA,0x00,0x06,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,
0x00,0x0E,0x00,0x0E,0x00,0x0E,0x1F,0xF6,0x3F,0xFA,0x7F,0xFC,0x00,0x00,0x00,0x00},
{// 图片":" 10
//6X6方点
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xE0,0x07,0xE0,
0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,
0x07,0xE0,0x07,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
};
//16x16图标-----------------------------------------------------------------//
//PCtoLCD2002取模:顺向,逐行式/
unsigned char code bmp1616[5][32]={
//"℃" tt=0
{0x00,0x00,0x30,0x00,0x48,0x00,0x49,0xC0,0x33,0xE8,0x06,0x38,0x0C,0x18,0x0C,0x08,
0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x06,0x08,0x03,0x10,0x01,0xE0,0x00,0x00},
//温度计图标
{0x00,0x00,0x01,0x80,0x02,0x40,0x02,0x40,0x02,0xC0,0x02,0x40,0x02,0xC0,0x02,0x40,
0x02,0xC0,0x02,0x40,0x03,0xC0,0x07,0xE0,0x0F,0xF0,0x0F,0xF0,0x07,0xE0,0x03,0xC0},
//闹钟图标
{
0x00,0x00,0x38,0x1C,0x60,0x06,0x43,0xC2,0x4C,0x32,0x11,0x08,0x11,0x08,0x21,0x04,
0x21,0xF4,0x20,0x04,0x10,0x08,0x10,0x08,0x0C,0x30,0x13,0xC8,0x20,0x04,0x00,0x00},
//无任何图片显示
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
//。显示
{
0x00,0x00,0x00,0x00,0x07,0xE0,0x08,0x10,0x10,0x08,0x20,0x04,0x20,0x04,0x21,0x84,
0x21,0x84,0x20,0x04,0x20,0x04,0x10,0x08,0x08,0x10,0x07,0xE0,0x00,0x00,0x00,0x00,}
};
/*********************************************************/
/*---------------------------------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------------------------------*/
/*------------------------------------------------
检测忙位
------------------------------------------------*/
void Check_Busy()
{
RS=0;
RW=1;
E=1;
DataPort=0xff;
while((DataPort&0x80)==0x80);//忙则等待
E=0;
}
/*------------------------------------------------
写命令
------------------------------------------------*/
void Write_Cmd(unsigned char Cmd)
{
Check_Busy();
RS=0;
RW=0;
E=1;
DataPort=Cmd;
DelayUs2x(5);
E=0;
DelayUs2x(5);
}
/*------------------------------------------------
写数据
------------------------------------------------*/
void Write_Data(unsigned char Data)
{
Check_Busy();
RS=1;
RW=0;
E=1;
DataPort=Data;
DelayUs2x(5);
E=0;
DelayUs2x(5);
}
/*------------------------------------------------
液晶屏初始化
------------------------------------------------*/
void Init_ST7920()
{
PSB = 1; //并口方式
delay(1); //延时
Write_Cmd(0x30); //基本指令, 扩充指令为34H
delay(10);
RES=0; //复位
delay(1); //延时
RES=1;
Write_Cmd(0x0c); //显示开, 关光标
delay(10);
Write_Cmd(0x01); //清屏
delay(10);
}
/*------------------------------------------------
显示字符串
x:横坐标值,范围0~8
y:纵坐标值,范围1~4
*s指针,表示对s地址中的内容进行操作
------------------------------------------------*/
void LCD_PutString(unsigned char x,unsigned char y,unsigned char *s)
{
switch(y)
{
case 1: Write_Cmd(0x80+x);break;
case 2: Write_Cmd(0x90+x);break;
case 3: Write_Cmd(0x88+x);break;
case 4: Write_Cmd(0x98+x);break;
default:break;
}
while(*s>0)
{
Write_Data(*s);
s++;
DelayUs2x(50);
}
}
/*------------------------------------------------
清屏
------------------------------------------------*/
void ClrScreen()
{
Write_Cmd(0x01);
delay(15);
}
///*------------------------------------------------
// 显示图片
//------------------------------------------------*/
//void LCD_PutGraphic(unsigned char code *img)
//{
// int i,j;
////显示上半屏内容设置
// for(i=0;i<32;i++)
// {
// Write_Cmd(0x80 + i); //SET 垂直地址 VERTICAL ADD
// Write_Cmd(0x80); //SET 水平地址 HORIZONTAL ADD
// for(j=0;j<16;j++)
// {
// Write_Data(*img);
// img++;
// }
// }
////显示下半屏内容设置
// for(i=0;i<32;i++)
// {
// Write_Cmd(0x80 + i); //SET 垂直地址 VERTICAL ADD
// Write_Cmd(0x88); //SET 水平地址 HORIZONTAL ADD
// for(j=0;j<16;j++)
// {
// Write_Data(*img);
// img++;
// }
// }
//
//}
/*------------------------------------------------
白屏
------------------------------------------------*/
void LCD_cluck(void)
{
int i,j;
//显示上半屏内容设置
for(i=0;i<32;i++)
{
Write_Cmd(0x80 + i); //SET 垂直地址 VERTICAL ADD
Write_Cmd(0x80); //SET 水平地址 HORIZONTAL ADD
for(j=0;j<16;j++)
{
Write_Data(0x00);
//img++;
}
}
//显示下半屏内容设置
for(i=0;i<32;i++)
{
Write_Cmd(0x80 + i); //SET 垂直地址 VERTICAL ADD
Write_Cmd(0x88); //SET 水平地址 HORIZONTAL ADD
for(j=0;j<16;j++)
{
Write_Data(0x00);
}
}
}
/*------------------------------------------------
设置到绘图模式
------------------------------------------------*/
void SetGraphicMode()
{
Write_Cmd(0x36); //关闭绘图显示功能
DelayUs2x(20);
}
void SetNormalMode()
{
Write_Cmd(0x30); //打开绘图显示功能
DelayUs2x(20);
}
void huatu(unsigned char x,unsigned char code *img)
{
unsigned char i,j;
SetGraphicMode();
for(i=0;i<32;i++)
{
if(i<16)
{
Write_Cmd(0x80+16+i); //将D15 ——D8写入到RAM中
Write_Cmd(0x80+x);
}
if(i>=16)
{
Write_Cmd(0x80+i-16); //将D7——D0写入到RAM中;
Write_Cmd(0x88+x);
}
for(j=0;j<2;j++)
{
Write_Data(*img);
img++;
}
}
SetNormalMode();
}
/*使用绘图的方法让一个16*16的汉字符反白----------------------------------------------*/
//形式参数:uchar x,uchar y,uchar wide,uchar bkcor
//行参说明:坐标水平位置,坐标垂直位置,反白行数,要反白还是清除(1:反白,0:清除)
void write1616GDRAM(uchar x,uchar y,uchar sign,uchar *bmp)
{ //x-列,y-行,sign-反白选择(1不反白,0反白),bmp-图画的选择
uchar i,j,basex;
Write_Cmd(0x36); //扩展指令,绘图模式命令,开显示也可以绘.(关图片显示0x34)
if(y==1||y==2) //第一第二行
{
basex=0x80; //上半屏
y=(y-1)*16; //垂直位址从0X80开始.
}
if(y==3||y==4) //第三第四行
{
basex=0x88; //下半屏
y=(y-3)*16; //垂直位址都是从0X80开始的,不管上下半屏。
}
for(i=0;i<16;i++) //
{
Write_Cmd(0x80+y+i); //写入垂直位址。
Write_Cmd(basex+x-1); //再写入水平位址(上半屏第一字为0X80,……第七字为0X87)
//下半屏第一字为0X88,……第七字为0X8F;
for(j=0;j<2;j++) //再写入两个8位元的数据,AC会自动增一,接着写数据
{
if(sign==1)
Write_Data(~(*bmp++));
else
Write_Data(*bmp++);
}
}
Write_Cmd(0x36); //写完数据,开图片显示
}
/**************************************************************************************
//函数功能:显示16X16图形,适用于st7920型液晶
//形式参数:uchar x,uchar y,uchar *bmp
//行参说明:横坐标X列,纵坐标Y行,sign=1反白、=0不反,tt是要显示的图形bmp1616中的第几个
//************************************************************************************/
void set1616pic(uchar x,uchar y,uchar sign,uchar tt)
{ //x-列,y-行,sign-反白选择(1不反白,0反白),tt-图画的选择
uchar (*pp)[32]; //定义指针
pp=bmp1616; //二维数组首地址给指针,故指针指向下一个数组地址应为加64
write1616GDRAM(x,y,sign,pp[tt]); //写入小时的十位
}
/******************************************************************************/
//十二生肖显示
/******************************************************************************/
void lcmshengxiao()
{
uchar y=0;
y=(2000+nian-1900)%12;
switch(y)
{
case 0: LCD_PutString(0, 4,"子鼠");
break;
case 1: LCD_PutString(0, 4,"丑牛");
break;
case 2: LCD_PutString(0, 4,"寅虎");
break;
case 3: LCD_PutString(0, 4,"卯兔");
break;
case 4: LCD_PutString(0, 4,"辰龙");
break;
case 5: LCD_PutString(0, 4,"巳蛇");
break;
case 6: LCD_PutString(0, 4,"午马");
break;
case 7: LCD_PutString(0, 4,"未羊");
break;
case 8: LCD_PutString(0, 4,"申猴");
break;
case 9: LCD_PutString(0, 4,"酉鸡");
break;
case 10: LCD_PutString(0, 4,"戌狗");
break;
case 11: LCD_PutString(0, 4,"亥猪");
break;
}
}
/*------------------------------------------------
定时器初始化子程序
------------------------------------------------*/
void Init_Timer0(void)
{
TMOD=0x11;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1; //定时器开关打开
ET1=1;
TR1=1; //定时器开关打开
}
/*------------------------------------------------
调时
------------------------------------------------*/
void set1_TIME(void) //时间设置
{
LCD_PutString(0,1,"设置: "); //设置时、分、日期
Write_Cmd(0x90+2);
Write_Data(0x30+num3/10);
Write_Data(0x30+num3%10);
Write_Data(0x3a);
Write_Data(0x30+num2/10);
Write_Data(0x30+num2%10);
Write_Data(0x3a);
Write_Data(0x30+num1/10);
Write_Data(0x30+num1%10);
//日期
Write_Cmd(0x98+1);
Write_Data(0x32);
Write_Data(0x30);
Write_Data(0x30+nian/10);
Write_Data(0x30+nian%10);
LCD_PutString(3,5,"年");
Write_Data(0x30+yue/10);
Write_Data(0x30+yue%10);
LCD_PutString(5,5,"月");
Write_Data(0x30+ri/10);
Write_Data(0x30+ri%10);
LCD_PutString(7,5,"日");
LCD_PutString(5,1,"sun: "); //星期
Write_Cmd(0x80+7);
Write_Data(0x30+day);
if(t_set==0) {Write_Cmd(0x88+2); Write_Data(0x1e);Write_Cmd(0x90+7); Write_Data(0x20);}
if(t_set==1) {Write_Cmd(0x88+4); Write_Data(0x1e);Write_Cmd(0x88+2); Write_Data(0x20);}
if(t_set==2) {Write_Cmd(0x88+5); Write_Data(0x1e);Write_Cmd(0x88+4); Write_Data(0x20);}
if(t_set==3) {Write_Cmd(0x88+2); Write_Data(0x1f);Write_Cmd(0x88+5); Write_Data(0x20);}
if(t_set==4) {Write_Cmd(0x88+4); Write_Data(0x1f);Write_Cmd(0x88+2); Write_Data(0x20);}
if(t_set==5) {Write_Cmd(0x88+6); Write_Data(0x1f);Write_Cmd(0x88+4); Write_Data(0x20);}
if(t_set==6) {Write_Cmd(0x90+7); Write_Data(0x1e);Write_Cmd(0x88+6); Write_Data(0x20);}
}
/*------------------------------------------------
闹钟
-------------------------------------------------*/
void set3_clok(void)
{
LCD_PutString(0,1,"闹钟设置: "); //设置时、分、日期
Write_Cmd(0x90+2);
Write_Data(0x30+n_num3/10);
Write_Data(0x30+n_num3%10);
Write_Data(0x3a);
Write_Data(0x30+n_num2/10);
Write_Data(0x30+n_num2%10);
Write_Data(0x3a);
Write_Data(0x30+n_num1/10);
Write_Data(0x30+n_num1%10);
LCD_PutString(0,4,"状态 : "); //
if(clok==0) LCD_PutString(3,4,"关闭");
if(clok==1) LCD_PutString(3,4,"开启");
if(t_set==0) {Write_Cmd(0x88+2); Write_Data(0x1e);Write_Cmd(0x98+5); Write_Data(0x20);}
if(t_set==1) {Write_Cmd(0x88+4); Write_Data(0x1e);Write_Cmd(0x88+2); Write_Data(0x20);}
if(t_set==2) {Write_Cmd(0x88+5); Write_Data(0x1e);Write_Cmd(0x88+4); Write_Data(0x20);}
if(t_set==3) {Write_Cmd(0x98+5); Write_Data(0x11);Write_Cmd(0x88+5); Write_Data(0x20);}
}
/*--------------------------------------------------------------------------------------------------------------------------------
18B20温度
--------------------------------------------------------------------------------------------------------------------------------*/
void ow_reset(void) //18B20复位
{
uint i;
DQ=0;
i=103;
while(i>0)i--;
DQ=1;
i=4;
while(i>0)i--;
}
/* 等待应答脉冲 */
void Rx_Wait(void)
{
uint i;
while(DQ);
while(~DQ); // 检测到应答脉冲
i = 4;
while (i>0)i--;
}
void write_byte(uchar val) //写字节
{
uchar i;
for(i=8;i>0;i--)
{
DQ=1;_nop_();_nop_();
DQ=0;_nop_();_nop_();_nop_();_nop_();_nop_();
DQ=val&0x01;
delays(6);
val>>=1;
}
DQ=1;
delays(1);
}
//读字节
uchar read_byte(void)
{
uchar i;
uchar value=0;
for(i=8;i>0;i--)
{
DQ=1;_nop_();_nop_();
value >>=1;
DQ=0;
_nop_();_nop_();_nop_();_nop_();
DQ=1;
_nop_();_nop_();_nop_();_nop_();
if(DQ) value|=0x80;
delays(6);
}
DQ=1;
return(value);
}
//18B20初始化
void tmpchange(void)
{
ow_reset(); //复位
Rx_Wait(); //等待应答信号
write_byte(0xcc); //跳过序列号
write_byte(0x44); //发转换命令
}
//读温度函数
void read_temp()
{
uchar temp_l,temp_h;//定义高低字节
ow_reset();
Rx_Wait(); //等待应答信号
write_byte(0xcc); //跳过序列号
write_byte(0xbe); //读取暂存器内容
temp_l=read_byte(); //低字节在前
temp_h=read_byte(); //高字节在后
if(temp_h>127) //温度小于0度时取补
{
temp_h=(~temp_h);
temp_l=(~temp_l)+1; //取反加一,将补码变成原码
n=1;
}
else n=0;
temp=((temp_l&0xf0)>>4)|((temp_h&0x0f)<<4);
point=temp_l&0x0f;
}
//读出温度数据进行分离,在显示屏上显示
void dis_temp()
{
if(n==0)//温度大于0度
{
Write_Cmd(0x98+5);
// Write_Data(0x30+temp/10);
Write_Data(0x30+(temp%100)/10);
Write_Data(0x30+temp%10);
Write_Data(0x2e);
Write_Data(0x30+ditab[point]);
}
//温度小于0度
if(n==1)
{
Write_Cmd(0x98+5);
Write_Data('-');
Write_Data(0x30+(temp%100)/10);
Write_Data(0x30+temp%10);
}
}
/*--------------------------------------------------------------------------------------------------------------------------------
12864液晶屏显示
--------------------------------------------------------------------------------------------------------------------------------*/
void display()
{
if(dip==0) //模式0显示-主界面
{
huatu(0,sum[max=num3/10]); //时
huatu(1,sum[wan=num3%10]);
huatu(2,sum[10]);
huatu(3,sum[qian=num2/10]); //分
huatu(4,sum[bai=num2%10]);
huatu(5,sum[10]);
huatu(6,sum[shi=num1/10]); //秒
huatu(7,sum[ge=num1%10]);
LCD_PutString(6,1,"周"); //星期
if(day==1) LCD_PutString(7,1,"一");
if(day==2) LCD_PutString(7,1,"二");
if(day==3) LCD_PutString(7,1,"三");
if(day==4) LCD_PutString(7,1,"四");
if(day==5) LCD_PutString(7,1,"五");
if(day==6) LCD_PutString(7,1,"六");
if(day==7) LCD_PutString(7,1,"日");
lcmshengxiao(); //显示所在年分的生肖
tmpchange();//转换初始化
read_temp();//读出温度
dis_temp();//显示温度
//日期
Write_Cmd(0x80);
Write_Data(0x32);
Write_Data(0x30);
Write_Data(0x30+nian/10);
Write_Data(0x30+nian%10);
Write_Data('-');
Write_Data(0x30+yue/10);
Write_Data(0x30+yue%10);
Write_Data('-');
Write_Data(0x30+ri/10);
Write_Data(0x30+ri%10);
set1616pic(8,4,0,0); //温度符号
set1616pic(5,4,0,1); //温度图标
if(clok==0) //闹钟关闭标志
{
set1616pic(4,4,0,3);
deep=1; //闹钟输出关闭
}
if(clok==1) //闹钟开启标志
{
set1616pic(4,4,0,2);
if((n_num3==num3)&&(n_num2==num2)&&(n_num1==num1)) //闹钟时间到达,开启闹钟
{
deep=0;
}
if((n_num3!=num3)||(n_num2!=num2)) //闹钟时间过期,关闭闹钟
{
deep=1;
}
}
}
if(dip==1) //模式1显示 --菜单
{
if(flag==0)
{
TR0=0;
Init_ST7920(); //液晶屏初始化
SetGraphicMode(); //设置成绘图模式
LCD_cluck(); //液晶屏显示为白屏,进行清屏
delay(500);
SetNormalMode(); //设置成文字模式
flag=1;
}
//显示菜单
LCD_PutString(1,1,"1.时间设置"); //设置时、分、日期
LCD_PutString(1,2,"2.闹钟设置"); //闹钟时间设置
LCD_PutString(1,3,"3.闹钟开关"); //闹钟 开、关
if(clok==0) LCD_PutString(7,3,"×");
if(clok==1) LCD_PutString(7,3,"√");
LCD_PutString(0,4,"确认 取消"); //闹钟 开、关
if(set==0)
{
LCD_PutString(0,1,"☆");
LCD_PutString(0,2," ");
LCD_PutString(0,3," ");
}
if(set==1)
{
LCD_PutString(0,1," ");
LCD_PutString(0,2,"☆");
LCD_PutString(0,3," ");
}
if(set==2)
{
LCD_PutString(0,1," ");
LCD_PutString(0,2," ");
LCD_PutString(0,3,"☆");
}
}
if(dip==4) ////模式4显示,时间设置界面
{
if(set_time==0)
{
set_time=1;
Init_ST7920(); //液晶屏初始化
SetGraphicMode(); //设置成绘图模式
LCD_cluck(); //液晶屏显示为白屏,进行清屏
delay(500);
SetNormalMode(); //设置成文字模式
}
set1_TIME();
}
if(dip==5) ////模式5显示,闹钟设置界面
{
if(set_time==0)
{
set_time=1;
Init_ST7920(); //液晶屏初始化
SetGraphicMode(); //设置成绘图模式
LCD_cluck(); //液晶屏显示为白屏,进行清屏
delay(500);
SetNormalMode(); //设置成文字模式
}
set3_clok();
}
}
/*-------------------------------------------------------------------------------------
按键识别
-------------------------------------------------------------------------------------*/
void key1()
{
///////////////////////////////////////////////////////////////////////
if(((k2==0)&&(k3==0))&&(dip!=0)) //返回主页面
{
delay(5);
if(((k2==0)&&(k3==0))&&(dip!=0))
{
tr1_time=0;
TR1=1;
while(!k2||!k3);
dip=0,flag=0,set=0,set_time=0,set_t=0,TR0=1,t_set=0;;
Init_ST7920(); //液晶屏初始化
SetGraphicMode(); //设置成绘图模式
LCD_cluck(); //液晶屏显示为白屏,进行清屏
delay(500);
}
}
//////////////////////////////////////////////////////////////////
if((k2==0)&&(dip==0)) //菜单键
{
delay(5);
if((k2==0)&&(dip==0))
{
while(!k2);
tr1_time=0;
TR1=1;
dip=1;
// if(dip==2)
// {
// dip=0;
// set=0;
// Init_ST7920(); //液晶屏初始化
// SetGraphicMode(); //设置成绘图模式
// LCD_cluck(); //液晶屏显示为白屏,进行清屏
// delay(500);
// TR0=1;
// flag=0;
// }
}
}
/////////////////////////菜单设置界面/////////////////////////////////////////
if(dip==1)
{
if(k4==0) //菜单往下
{
delay(5);
if(k4==0)
{
while(!k4);
set++;
if(set==3)
{
set=0;
}
}
}
if(k5==0) //菜单往上
{
delay(5);
if(k5==0)
{
while(!k5);
set--;
if(set==-1)
{
set=2;
}
}
}
/////////////////////////////////////////////////////////////////
if((k3==0)&&(set==2)) //选择闹钟开、关
{
delay(5);
if((k3==0)&&(set==2))
{
while(!k3);
clok++;
if(clok==3) clok=0;
}
}
/////////////////////////////////////////////////////////////////
if((k3==0)&&(set==0)) //选择时间设置
{
delay(5);
if((k3==0)&&(set==0))
{
while(!k3);
dip=4;
}
}
}
if(dip==4) //时间设置界面
{
if(k3==0) //往下
{
delay(5);
if(k3==0)
{
while(!k3);
t_set++;
if(t_set==7)
{
t_set=0;
}
}
}
if(k4==0) //加
{
delay(5);
if(k4==0)
{
while(!k4);
if(t_set==0) num3++; if(num3==24) num3=0;
if(t_set==1) num2++; if(num2==60) num2=0;
if(t_set==2) num1++; if(num1==60) num1=0;
if(t_set==3) nian++; if(nian==100) nian=0;
if(t_set==4) yue++; if(yue==13) yue=1;
if(t_set==5) ri++;
if((ri==32)&&((yue==1)||(yue==3)||(yue==5)||(yue==7)||(yue==8)||(yue==10)||(yue==12))) ri=1;
if((ri==31)&&((yue==4)||(yue==6)||(yue==9)||(yue==11))) ri=1;
if((ri==29)&&((yue==2)&&(nian%4!=0))) ri=1;
if((ri==30)&&((yue==2)&&(nian%4==0))) ri=1;
if(t_set==6) day++; if(day==8) day=1;
}
}
if(k5==0) //减
{
delay(5);
if(k5==0)
{
while(!k5);
if(t_set==0) num3--; if(num3==-1) num3=23;
if(t_set==1) num2--; if(num2==-1) num2=59;
if(t_set==2) num1--; if(num1==-1) num1=59;
if(t_set==3) nian--; if(nian==-1) nian=99;
if(t_set==4) yue--; if(yue==0) yue=12;
if(t_set==5) ri--; if(ri==0) ri=31;
if((ri==-1)&&((yue==1)||(yue==3)||(yue==5)||(yue==7)||(yue==8)||(yue==10)||(yue==12))) ri=31;
if((ri==-1)&&((yue==4)||(yue==6)||(yue==9)||(yue==11))) ri=30;
if((ri==-1)&&((yue==2)&&(nian%4!=0))) ri=28;
if((ri==-1)&&((yue==2)&&(nian%4==0))) ri=29;
if(t_set==6) day--; if(day==0) day=7;
}
}
}
////////////////////////、、、、、、、、、///////////////////////////////////////////
if((k3==0)&&((set==1)&&(dip==1))) //闹钟设置界面
{
delay(5);
if((k3==0)&&((set==1)&&(dip==1)))
{
while(!k3);
dip=5;
}
}
if(dip==5) //闹钟设置界面
{
if(k3==0) //往下
{
delay(5);
if(k3==0)
{
while(!k3);
t_set++;
if(t_set==4)
{
t_set=0;
}
}
}
if(k4==0) //加
{
delay(5);
if(k4==0)
{
while(!k4);
if(t_set==0) n_num3++; if(n_num3==24) n_num3=0;
if(t_set==1) n_num2++; if(n_num2==60) n_num2=0;
if(t_set==2) n_num1++; if(n_num1==60) n_num1=0;
if(t_set==3) clok++; if(clok==2) clok=0; if(clok==0) LCD_PutString(3,4,"关");
if(clok==1) LCD_PutString(3,4,"开");
}
}
if(k5==0) //减
{
delay(5);
if(k5==0)
{
while(!k5);
if(t_set==0) n_num3--; if(n_num3==-1) n_num3=23;
if(t_set==1) n_num2--; if(n_num2==-1) n_num2=59;
if(t_set==2) n_num1--; if(n_num1==-1) n_num1=59;
if(t_set==3) clok--; if(clok==-1) clok=1; if(clok==0) LCD_PutString(3,4,"关");
if(clok==1) LCD_PutString(3,4,"开");
}
}
}
///////////////////////////////////////////////////////////////////////////////////
if((k1==0)||(k2==0)||(k3==0)||(k4==0)||(k5==0)) //任何按键按下,LCD显示屏亮20s
{
tr1_time=0;
TR1=1;
}
///////////////////////////////////////////////////////////////////////////////////
if((dip==0)&&((k4==0)&&(k3==0))) //闹钟开启、关闭快捷键
{
delay(5);
if((dip==0)&&((k4==0)&&(k3==0)))
{
while(!k4||!k3);
clok++;
if(clok==3) clok=0;
}
}
///////////////////////////////////////////////////////////////////////////////////
if((deep==0)&&((dip==0)&&((k1==0)||(k3==0)||(k4==0)||(k5==0)))) //闹钟响起时,按下任何键可关闭闹铃
{
deep=1;
}
}
/*----------------------------------------------------------------------------
主程序
-----------------------------------------------------------------------------*/
void main()
{
deep=1;
Init_ST7920(); //液晶屏初始化
LCD_PutString(2,1,"Welcome");
LCD_PutString(2,2,"欢迎使用");
LCD_PutString(1,3," <联创电子> ");
LCD_PutString(0,4,"LCD12864万历时钟");
delay(5000);
Init_ST7920(); //液晶屏初始化
Init_Timer0(); //定时器初始化
SetGraphicMode(); //设置成绘图模式
LCD_cluck(); //液晶屏显示为白屏,进行清屏
delay(500);
ow_reset();
write_byte(0xcc);//跳过序列号
write_byte(0x44);
LCD_led=1;
while(1)
{
display(); //显示屏显示
key1();
}
}
/*------------------------------------------------
定时器0中断子程序
------------------------------------------------*/
void Timer0_isr(void) interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
num++;
if(num==20)
{
num=0;num1++;
if(num1==60)
{
num1=0;num2++;
if(num2==60)
{
num2=0;num3++;
if(num3==24)
{
num3=0;
day++;
if(day==8)
{
day=1;
}
ri++;
if((ri==32)&&((yue==1)||(yue==3)||(yue==5)||(yue==7)||(yue==8)||(yue==10)||(yue==12))) //大月
{
ri=1;
yue++;
if(yue==13)
{
yue=1;
nian++;
if(nian==99) nian=0;
}
}
if((ri==31)&&((yue==4)||(yue==6)||(yue==9)||(yue==11))) //小月
{
ri=1;
yue++;
if(yue==13)
{
yue=1;
nian++;
if(nian==99) nian=0;
}
}
if((ri==29)&&((yue==2)&&(nian%4!=0))) //2月份有28天
{
ri=1;
yue++;
if(yue==13)
{
yue=1;
nian++;
if(nian==99) nian=0;
}
}
if((ri==30)&&((yue==2)&&(nian%4==0))) //2月份有29天
{
ri=1;
yue++;
if(yue==13)
{
yue=1;
nian++;
if(nian==99) nian=0;
}
}
}
}
}
}
}
/*------------------------------------------------
定时器0中断子程序
------------------------------------------------*/
void Timer1_isr(void) interrupt 3
{
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
tr1_time++;
if(tr1_time)
{
LCD_led=0;
if(tr1_time==400) //亮屏20s自动熄屏
{
tr1_time=1;
LCD_led=1;
TR1=0;
}
}
}
|