网上很多类似的电子时钟的单片机采用的是89C51或89C52,而用2051的时钟功能又较少,基本只用于显示时间,不带温度显示和按键调整,原因可能2051的I/O口较少。其中LCD1602正常需要RS、RW、EN、D0~D7,共11个接口与单片机相连,于是本人通过将LCD1602用四线传输数据的方法节省出4个I/O口,并将RW端口直接接地再节省出1个I/O口。由此可节省出5个I/O口作为按键接口和温度数据传输接口。
本人接触单片机不久,所以从网上搜索了一些89C51时钟的程序,再原有基础上进行改写和整合得到了控制程序。
本时钟具有日期、星期、时间和温度的显示,并可以通过按键来调整。另外,硬件上还留有一个P3.5端口,可作它用,如添加闹钟功能等。
以下是原理图
以下是C程序
#include
#include\头文件总设置ds18b20的DQ端 #define uchar unsigned char #define uint unsigned int
/*------------------寄存器地址定义------------*/ #define WRITE_SECOND 0x80 #define WRITE_MINUTE 0x82 #define WRITE_HOUR 0x84 #define WRITE_DAY 0x86 #define WRITE_MONTH 0x88 #define WRITE_YEAR 0x8C #define WRITE_PROTECT 0x8E #define WRITE_WEEK 0x8A //#define WRITE_CURRENT 0x90 #define READ_SECOND 0x81 #define READ_MINUTE 0x83 #define READ_HOUR 0x85 #define READ_DAY 0x87 #define READ_MONTH 0x89 #define READ_WEEK 0x8B #define READ_YEAR 0x8D
sbit LCD_E=P1^3; //液晶使能端
sbit LCD_RS=P1^2; //液晶数据命令选择端
//sbit LCD_RW=P2^5; //液晶读写选择端,直接接地 ,不需要 sbit RST=P3^7; //DS1302片选 sbit DIO=P3^1; //DS1302数据信号 sbit SCLK=P3^0; //DS1302时钟信号 sbit key0=P3^2; //功能键 sbit key1=P3^3; //增大键 sbit key2=P3^4; //减小键 sbit beep=P1^0; //蜂鸣器 sbit ACC7=ACC^7;
sbit ACC0=ACC^0;
unsigned char READ_1302(unsigned char addr); char hour,minute,second,week,day,month,year,tem; unsigned char num,flag,count,wendu; unsigned char str1[]=\ - - %unsigned char str2[]=\ : :\
void delay(unsigned char z); void INITIAL_1302();
void WRITE_1302(unsigned char addr,unsigned char date); void LCD_WRITE_COM(unsigned char com);
void LCD_WRITE_DATA(unsigned char date);
void LCD_WRITE_SFM(unsigned char addr,unsigned char date); void LCD_WRITE_NYR(unsigned char addr,unsigned char date); void LCD_WRITE_WEEK(unsigned char week); void LCD_INITIAL(); void keyscan();
void INITIAL_TEMER0(); void w1602c(uchar com); void w1602d(uchar data01);
void write_temp(uchar add,uchar date);
void main() {
LCD_INITIAL(); //液晶初始化 INITIAL_1302(); //DS1302初始化 INITIAL_TEMER0(); //定时器初始化 beep=0;//蜂鸣器长响一次 delay(1000); beep=1; while(1) {
keyscan(); //按键扫描 if(flag==0) //当标志位为0,允许读取DS1302数据,将数据送入液晶显示 { second=READ_1302(0x81); LCD_WRITE_SFM(8,second); minute=READ_1302(0x83); LCD_WRITE_SFM(5,minute); hour=READ_1302(0x85); LCD_WRITE_SFM(2,hour); week=READ_1302(0x8b); LCD_WRITE_WEEK(week); day=READ_1302(0x87); LCD_WRITE_NYR(9,day); month=READ_1302(0x89); LCD_WRITE_NYR(6,month); year=READ_1302(0x8d); LCD_WRITE_NYR(3,year); wendu=ReadTemperature();//将18b2头文件运行返回的函数结果送到变量wendu中,用于显示 write_temp(11,wendu);//显示温度,从第二行第12个字符后开始显示 }