标题: 比较好的电子时钟 [打印本页]
作者: 瀚海没有水 时间: 2018-1-11 21:21
标题: 比较好的电子时钟
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
/////////////////
sbit rw = P2^6;//
sbit rs = P2^5;// 1602 IO口位定义
sbit en = P2^7;//
/////////////////
///////////////////
sbit rst = P3^5; //
sbit sclk = P3^6;// 1302 IO口位定义
sbit io = P3^4; //
///////////////////
///////////////////
sbit key1 = P1^0;//
sbit key2 = P1^1;// 独立按键位定义
sbit key3 = P1^2;//
sbit key4 = P1^3;//
///////////////////
///////////////////
sbit DQ = P2^2;////
///////////////////
uchar tempL=0; //临时变量低位
uchar tempH=0; //临时变量高位
uint temperature;
uint hour, minute, second, year, month, day;
uint key = 0;
uchar tab_num[] = {0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x2d}; //对应字符为: { 0 1 2 3 4 5 6 7 8 9 : - }
uchar tab_time[] = {1,2,10,3,4,10,5,6};
uchar tab_date[] = {2,0,1,0,11,0,9,11,2,7};
// 延时函数,延时z毫秒 ******
void delay(uint z)
{
uint x, y;
for(x=0;x<z;x++)
for(y=0;y<110;y++);
}
//***************************
/****************************************************************************
函数功能:延时子程序
入口参数:k
出口参数:
****************************************************************************/
void delay18b20(unsigned int k)
{
unsigned int n;
n=0;
while(n < k)
{n++;}
return;
}
/****************************************************************************
函数功能:DS18B20初始化子程序
入口参数:
出口参数:
****************************************************************************/
Init_DS18B20(void)
{
unsigned char x=0;
DQ=1; //DQ先置高
delay18b20(8); //延时
DQ=0; //发送复位脉冲
delay18b20(85); //延时(>480ms)
DQ=1; //拉高数据线
delay18b20(14); //等待(15~60ms)
}
/****************************************************************************
函数功能:向DS18B20读一字节数据
入口参数:
出口参数:dat
****************************************************************************/
ReadOneChar(void)
{
unsigned char i=0;
unsigned char dat=0;
for (i=8;i>0;i--)
{
DQ=1;
delay18b20(1);
DQ=0;
dat>>=1;
DQ=1;
if(DQ)
dat|=0x80;
delay18b20(4);
}
return(dat);
}
/****************************************************************************
函数功能:向DS18B20写一字节数据
入口参数:dat
出口参数:
****************************************************************************/
WriteOneChar(unsigned char dat)
{
unsigned char i=0;
for(i=8;i>0;i--)
{
DQ=0;
DQ=dat&0x01;
delay18b20(5);
DQ=1;
dat>>=1;
}
delay18b20(4);
}
/****************************************************************************
函数功能:向DS18B20读温度值
入口参数:
出口参数:temperature
****************************************************************************/
uint ReadTemperature(void)
{
Init_DS18B20(); //初始化
WriteOneChar(0xcc); //跳过读序列号的操作
WriteOneChar(0x44); //启动温度转换
delay18b20(125); //转换需要一点时间,延时
Init_DS18B20(); //初始化
WriteOneChar(0xcc); //跳过读序列号的操作
WriteOneChar(0xbe); //读温度寄存器(头两个值分别为温度的低位和高位)
tempL=ReadOneChar(); //读出温度的低位LSB
tempH=ReadOneChar(); //读出温度的高位MSB
//温度转换,把高低位做相应的运算转化为实际温度
temperature=((tempH*256)+tempL)*5/8;
delay18b20(200);
return(temperature);
}
//========1302写一个字节=========
void write_byte(uchar dat)
{
uchar i, dat_w;
dat_w = dat;
for(i=0;i<8;i++)
{
io = 0;
if(dat_w & 0x01)
io = 1;
else
io = 0;
dat_w = dat_w >> 1;
sclk = 0;
sclk = 1;
}
sclk = 0;
}
//===============================
//========1302读一个字节=========
uchar read_byte()
{
uchar i, k;
k = 0;
for(i=0;i<8;i++)
{
k = k >> 1;
if(io)
k = k|0x80;
sclk = 1;
sclk = 0;
}
sclk = 0;
return (k);
}
//===============================
//========1302把数据写入地址=====
void write_add(uchar add, uchar dat)
{
rst = 0;
sclk = 0;
rst = 1;
write_byte(add);
write_byte((dat / 10 << 4) | (dat % 10));
sclk = 0;
rst = 0;
}
//===============================
//========1302从地址读出数据=====
uchar read_add(uchar add)
{
uchar temp, dat1, dat2;
rst = 0;
sclk = 0;
rst = 1;
write_byte(add);
temp = read_byte();
sclk = 0;
rst = 0;
dat1 = temp / 16;
dat2 = temp % 16;
temp = dat1 * 10 + dat2;
return (temp);
}
//===============================
//=========1302时间初始化========
void ds1302_init()
{
write_add(0x8e,0x00); //打开写保护,写入时间;
write_add(0x80,50); //初始化--秒 50;
write_add(0x82,59); //初始化--分 59;
write_add(0x84,23); //初始化--时 23;
write_add(0x86,31); //初始化--日 31;
write_add(0x88,12); //初始化--月 12;
write_add(0x8c,10); //初始化--年 2010;
write_add(0x8e,0x80); //关闭写保护,禁止写入。
}
//===============================
//=========1302读出时间==========
void ds1302()
{
write_add(0x8e,0x00); //打开写保护,读出时间;
second = read_add(0x81); //从1302读出时间--秒;
minute = read_add(0x83); //从1302读出时间--分;
hour = read_add(0x85); //从1302读出时间--时;
day = read_add(0x87); //从1302读出时间--日;
month = read_add(0x89); //从1302读出时间--月;
year = read_add(0x8d); //从1302读出时间--年;
write_add(0x8e,0x80); //关闭写保护,禁止读出;
}
//===============================
//写命令函数 ****************
void write_com(uchar com)
{
rs = 0;
rw = 0;
en = 0;
delay(5);
P0 = com;
delay(5);
en = 1;
delay(5);
en = 0;
}
//***************************
//写数据函数*****************
void write_data(uchar date)
{
rs = 1;
rw = 0;
en = 0;
delay(5);
P0 = date;
delay(5);
en = 1;
delay(5);
en = 0;
}
//***************************
//1602显示一个字符===========
void DisplayOne(uchar *p)
{
write_data(*p);
}
//===========================
//======时间重新赋值=========
void time()
{
tab_time[0] = hour / 10;
tab_time[1] = hour % 10;
tab_time[3] = minute /10;
tab_time[4] = minute % 10;
tab_time[6] = second / 10;
tab_time[7] = second % 10;
tab_date[2] = year / 10;
tab_date[3] = year % 10;
tab_date[5] = month / 10;
tab_date[6] = month % 10;
tab_date[8] = day / 10;
tab_date[9] = day % 10;
}
//===========================
//======1602初始化===========
void init()
{
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
}
//===========================
//=====时间显示函数==========
void DisplayTime()
{
uint n;
ds1302();
time();
write_com(0x80 + 6);
for(n=0;n<10;n++)
{
DisplayOne(tab_num + tab_date[n]); //显示日期
}
write_com(0x80 + 0x40 + 6);
for(n=0;n<8;n++)
{
DisplayOne(tab_num + tab_time[n]); //显示时间
}
}
//===========================
//=========时钟停止==========
void stop()
{
write_add(0x8e, 00); //打开写保护
write_add(0x80,80); //时钟停止
write_add(0x8e, 80); //禁止写保护
write_com(0x80+0x40+12); //===================
write_data(tab_num[second/10]); // 显示秒
write_data(tab_num[second%10]); //===================
}
//===========================
//==========时钟开始=========
void start()
{
write_add(0x8e, 00); //打开写保护
write_add(0x80,second); //读入秒
write_add(0x8e, 80); //禁止写保护
}
//=====矩阵键盘扫描函数======
void KeyScan()
{
P1 = 0xff;
if(key1 == 0) //即独立键盘中的k1
{
delay(10);
if(key1 == 0)
{
key = 1;
while(!key1);
}
}
if(key2 == 0) //即独立键盘中的k2
{
delay(10);
if(key2 == 0)
{
key = 2;
while(!key2);
}
}
if(key3 == 0) //即独立键盘中的k3
{
delay(10);
if(key3 == 0)
{
key = 3;
while(!key3);
}
}
if(key4 == 0) //即独立键盘中的k6
{
delay(10);
if(key4 == 0)
{
key = 4;
while(!key4);
}
}
}
//============================
//======按键操作函数==========
void KeyDo()
{
uint m = 15; //用以修改日期(第一行)时,移动闪烁光标。
uint n = 13; //用以修改时间(第二行)时,移动闪烁光标。
if(key == 1)
{
key = 0;
stop();
write_com(0x80 + 0x40 + n);
write_com(0x0f);
while(1)
{
KeyScan();
if(key == 3)
{
n = n + 3;
if(n > 13)
n = 7;
write_com(0x80 + 0x40 + n);
write_com(0x0f);
key = 0;
}
switch(n)
{
case 13 :
if(key == 2)
{
second++;
if(second == 60)
second = 0;
time();
write_add(0x8e,0x00);
write_add(0x80,second);
write_add(0x8e,0x80);
write_com(0x80 + 0x40 + 12);
DisplayOne(tab_num + tab_time[6]);
DisplayOne(tab_num + tab_time[7]);
write_com(0x80 + 0x40 + 13);
write_com(0x0f);
key = 0;
}
if(key == 4)
{
second--;
if(second == -1)
second = 59;
time();
write_add(0x8e,0x00);
write_add(0x80,second);
write_add(0x8e,0x80);
write_com(0x80 + 0x40 + 12);
DisplayOne(tab_num + tab_time[6]);
DisplayOne(tab_num + tab_time[7]);
write_com(0x80 + 0x40 + 13);
write_com(0x0f);
key = 0;
}
case 10 :
if(key == 2)
{
minute++;
if(minute == 60)
minute = 0;
time();
write_add(0x8e,0x00);
write_add(0x82,minute);
write_add(0x8e,0x80);
write_com(0x80 + 0x40 + 9);
DisplayOne(tab_num + tab_time[3]);
DisplayOne(tab_num + tab_time[4]);
write_com(0x80 + 0x40 + 10);
write_com(0x0f);
key = 0;
}
if(key == 4)
{
minute--;
if(minute == -1)
minute = 59;
time();
write_add(0x8e,0x00);
write_add(0x82,minute);
write_add(0x8e,0x80);
write_com(0x80 + 0x40 + 9);
DisplayOne(tab_num + tab_time[3]);
DisplayOne(tab_num + tab_time[4]);
write_com(0x80 + 0x40 + 10);
write_com(0x0f);
key = 0;
}
case 7 :
if(key == 2)
{
hour++;
if(hour == 24)
hour = 0;
time();
write_add(0x8e,0x00);
write_add(0x84,hour);
write_add(0x8e,0x80);
write_com(0x80 + 0x40 + 6);
DisplayOne(tab_num + tab_time[0]);
DisplayOne(tab_num + tab_time[1]);
write_com(0x80 + 0x40 + 7);
write_com(0x0f);
key = 0;
}
if(key == 4)
{
hour--;
if(hour == -1)
hour = 23;
time();
write_add(0x8e,0x00);
write_add(0x84,hour);
write_add(0x8e,0x80);
write_com(0x80 + 0x40 + 6);
DisplayOne(tab_num + tab_time[0]);
DisplayOne(tab_num + tab_time[1]);
write_com(0x80 + 0x40 + 7);
write_com(0x0f);
key = 0;
}
}
if(key == 1)
{
start();
key = 0;
write_com(0x0c);
break;
}
}
}
if(key == 3)
{
stop();
write_com(0x80 + m);
write_com(0x0f);
while(1)
{
KeyScan();
if(key == 3)
{
m = m + 3;
if(m > 15)
m = 9;
write_com(0x80 + m);
write_com(0x0f);
key = 0;
}
switch(m)
{
case 15 :
if(key == 2)
{
day++;
if(day == 32)
day = 1;
time();
write_add(0x8e,0x00);
write_add(0x86,day);
write_add(0x8e,0x80);
write_com(0x80 + 14);
DisplayOne(tab_num + tab_date[8]);
DisplayOne(tab_num + tab_date[9]);
write_com(0x80 + 15);
write_com(0x0f);
key = 0;
}
if(key == 4)
{
day--;
if(day == 0)
day = 31;
time();
write_add(0x8e,0x00);
write_add(0x86,day);
write_add(0x8e,0x80);
write_com(0x80 + 14);
DisplayOne(tab_num + tab_date[8]);
DisplayOne(tab_num + tab_date[9]);
write_com(0x80 + 15);
write_com(0x0f);
key = 0;
}
case 12 :
if(key == 2)
{
month++;
if(month == 13)
month = 1;
time();
write_add(0x8e,0x00);
write_add(0x88,month);
write_add(0x8e,0x80);
write_com(0x80 + 11);
DisplayOne(tab_num + tab_date[5]);
DisplayOne(tab_num + tab_date[6]);
write_com(0x80 + 12);
write_com(0x0f);
key = 0;
}
if(key == 4)
{
month--;
if(month == -1)
month = 12;
time();
write_add(0x8e,0x00);
write_add(0x88,month);
write_add(0x8e,0x80);
write_com(0x80 + 11);
DisplayOne(tab_num + tab_date[5]);
DisplayOne(tab_num + tab_date[6]);
write_com(0x80 + 12);
write_com(0x0f);
key = 0;
}
case 9 :
if(key == 2)
{
year++;
if(year == 100)
year = 0;
time();
write_add(0x8e,0x00);
write_add(0x8c,year);
write_add(0x8e,0x80);
write_com(0x80 + 8);
DisplayOne(tab_num + tab_date[2]);
DisplayOne(tab_num + tab_date[3]);
write_com(0x80 + 9);
write_com(0x0f);
key = 0;
}
if(key == 4)
{
year--;
if(year == -1)
year = 23;
time();
write_add(0x8e,0x00);
write_add(0x8c,year);
write_add(0x8e,0x80);
write_com(0x80 + 8);
DisplayOne(tab_num + tab_date[2]);
DisplayOne(tab_num + tab_date[3]);
write_com(0x80 + 9);
write_com(0x0f);
key = 0;
}
}
if(key == 1)
{
key = 0;
start();
write_com(0x0c);
break;
}
}
}
}
void Display_18b20()
{
uint t1,t2,t3;
t1 = ReadTemperature()/100%10;
t2 = ReadTemperature()/10%10;
t3 = ReadTemperature()%10;
write_com(0x80);
write_data(tab_num[t1]);
write_data(tab_num[t2]);
DisplayOne(".");
write_data(tab_num[t3]);
}
//============================
void main()
{
init();
ds1302_init();
while(1)
{
Display_18b20();
KeyScan();
KeyDo();
DisplayTime();
}
}
作者: 瀚海没有水 时间: 2018-1-11 21:26
大家来看看 提点建议
作者: wxyyxr 时间: 2018-1-11 22:32
看起来不错,感谢分享!
欢迎光临 (http://www.51hei.com/bbs/) |
Powered by Discuz! X3.1 |