功能说明:
LCD1602液晶显示年、月、日、时、分、秒、星期、温度,三个按键控制时间日期调整以及闹钟设定。
三个按键:
1、“校时”键,每次按下分别对应调整秒、调整分钟、调整小时、调整星期、调整日、调整月份、调整年份、调整闹钟分钟、调整闹钟小时、退出校时模式;
2、“增加/开闹钟功能”键,校时模式下按下此键则数值加一,非校时模式下按下此键则显示出闹钟时间并打开闹钟功能(屏幕显示字母A);
3、“减小/关闹钟功能”键,校时模式下按下此键则数值减一,非校时模式下按下此键则关闭闹钟显示并关闭闹钟功能(屏幕字母A消失);
#include
typedef unsigned char uchar;
typedef unsigned int uint;
#define rs_h P3|=0x01//单片机向LCD1602液晶RS引脚输出高电平
#define rs_l P3&=0xfe
#define rw_h P3|=0x02
#define rw_l P3&=0xfd
#define en_h P3|=0x04
#define en_l P3&=0xfb
#define temp_h P3|=0x40//单片机向DS18B20输出高电平
#define temp_l P3&=0xbf//单片机向DS18B20输出低电平
#define rst_h P3|=0x08//单片机向DS1302时钟芯片RST引脚输出高电平
#define rst_l P3&=0xf7
#define sck_h P3|=0x10
#define sck_l P3&=0xef
#define io_h P3|=0x20
#define io_l P3&=0xdf
#define SECADD 0X80//秒寄存器地址
#define MINADD 0x82
#define HRADD 0x84
#define DATEADD 0x86
#define MONTHADD 0x88
#define DAYADD 0x8a
#define YEARADD 0x8c
#define CONTROLADD 0x8e
#define PORT (P2)//P2连接LCD1602的8个数据引脚
sbit time=P3^5;//DS1302输入输出引脚
sbit tmp=P3^6;//DS18B20输入输出引脚
void delayms(uint x);//延时函数
void lcd_com(uchar com);//LCD1602液晶写命令函数
void lcd_dat(uchar dat);//LCD1602液晶写数据函数
void lcd_write(uchar c,uchar r,uchar dat);//向LCD1602液晶指定行、指定列写数据函数
void lcd_init();//LCD1602液晶初始化
void Ds1302Init();//DS1302初始化
void WriteByte(uchar dat);//往DS1302写一字节
uchar ReadByte();//从DS1302读一字节
uchar BCDtoDex(uchar dat);//BCD码转十进制
uchar DextoBCD(uchar dat);//十进制转BCD码
void Ds1302Write(uchar add,uchar dat);//往DS1302指定地址写数据
uchar Ds1302Read(uchar add);//读DS1302制定地址的数据
void Ds18b20_reset();//DS18B20温度传感器复位
void Ds18b20_write(uchar dat);//往DS18B20写一字节
void showtem();//显示温度
uchar Ds18b20_read();//从DS18B20读一字节
char keyscan();//按键检测,有键按下返回1,否则返回0
uchar Timflag;//表示50ms时间到
uchar Temflag;//让"命令DS18B20转换温度"和"读温度值"两个模块错开执行
uchar dat1,dat2;//读回的温度值,dat1保存低字节,dat2保存高字节
uchar keystate=2;//按键状态标志,初始化为2,是为了程序第一次运行时能够进入keystat1分支
#define keystate0 1//keystate0在keyscan()函数中,代表按下确认功能
#define keystate1 2//keystate1在keyscan()函数中,代表无按键按下
uchar keynum;//调用keyscan()函数,如果该函数返回1,说明有键按下,keynum保存按键值
uchar keynum1=0;//指示键1按下了多少次
uchar TimeShowEn=1;//设置此变量是为了在校时状态期间,不让主函数再刷新时间显示
uchar TimeChanged;//用来指示用户是否修改了时间
sbit led1=P0^0;//键1指示灯,按下键1此灯变换状态
sbit led2=P0^1;//键2指示灯,按下键2此灯变换状态
sbit led3=P0^2;//键3指示灯,按下键3此灯变换状态
sbit buzz=P1^0;//蜂鸣器接口
uchar AlarmEn,AlarmCome;//AlarmEn指示是否开启了闹钟功能,AlarmCome指示定时时间是否到了
char AlarmMin,AlarmHr;//保存闹钟分钟、闹钟小时
uchar CountForAlarm;//用于累加时间,时间到,翻转蜂鸣器接口电平,决定蜂鸣器响声频率
uchar ToShowAlarm;//ToShowAlarm为1,则允许主函数中显示闹钟时间模块执行
uchar CountForShowAlarm;//CountForShowAlarm用于累加闹钟显示时间
...
...
...
...
...
...
void Timer0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
Timflag=1;//Timflag 为1说明50ms定时时间到了
}
void Ds1302Init()
{
rst_l;
sck_l;
Ds1302Write(CONTROLADD,0);//关闭写保护
Ds1302Write(MINADD,DextoBCD(06));
Ds1302Write(HRADD,DextoBCD(19));
Ds1302Write(DATEADD,DextoBCD(20));
Ds1302Write(MONTHADD,DextoBCD(5));
Ds1302Write(DAYADD,DextoBCD(7));
Ds1302Write(YEARADD,DextoBCD(12));
Ds1302Write(SECADD,DextoBCD(30));//写秒,同时启动时钟
//Ds1302Write(CONTROLADD,0x80);//写保护
}
void WriteByte(uchar dat)//上升沿输出
{
uchar i;
for(i=8;i>0;i--)
{
sck_l;//低电平时数据线可变
if(dat&0x01)
io_h;
else
io_l;
sck_h;
dat>>=1;
}
}
uchar BCDtoDex(uchar dat)//BCD码转十进制
{
uchar i;
i=dat/16;
dat%=16;
i=i*10+dat;
return i;
}
uchar DextoBCD(uchar dat)//十进制转BCD码
{
uchar i;
i=dat/10;
dat%=10;
i=i*16+dat;
return i;
}
uchar ReadByte()//下降沿输出
{
uchar i;
uchar dat;
for(i=8;i>0;i--)//要考虑之前写完后的状态,第一次进入此循环体即有下降沿
{
dat>>=1;
sck_l;
if(time==1)
dat|=0x80;
sck_h;
}
return dat;
}
void Ds1302Write(uchar add,uchar dat)
{
rst_l;
sck_l;
rst_h;
WriteByte(add);//最低位为0表示写
WriteByte(dat);
rst_l;
}
uchar Ds1302Read(uchar add)
{
uchar dat;
rst_l;
sck_l;
rst_h;
WriteByte(add+1);//地址最低位置1表示读
dat=ReadByte();
rst_l;
return dat;
}
void delayms(uint x)//延时1ms
{
uint y,z;
for(y=x;y>0;y--)
for(z=111;z>0;z--);
}
void lcd_init()//LCD1602初始化
{
lcd_com(0x38);
lcd_com(0x0c);
lcd_com(0x06);
lcd_write(0,5,0xb0);//显示-
lcd_write(0,8,0xb0);//显示-
lcd_write(1,3,0x3a);//显示:
lcd_write(1,6,0x3a);//显示:
}
void lcd_com(uchar com)//向LCD1602写命令
{
rs_l;
rw_l;
PORT=com;
delayms(1);
en_h;
delayms(1);
en_l;
}
void lcd_dat(uchar dat)//向LCD1602写数据
{
rs_h;
rw_l;
PORT=dat;
delayms(1);
en_h;
delayms(1);
en_l;
}
void lcd_write(uchar c,uchar r,uchar dat)//向LCD1602指定行、指定列、写数据
{
lcd_com(0x80+0x40*c+r);
lcd_dat(dat);
}
...
...
...
...
...
...