单片机电子时钟.docx
《单片机电子时钟.docx》由会员分享,可在线阅读,更多相关《单片机电子时钟.docx(22页珍藏版)》请在冰豆网上搜索。
单片机电子时钟
#include
#include
#defineMSB0x80//读忙位
#defineHIGH1
#defineLOW0
//*****************************************
#defineDATA_MODE0x28//LCD模式设置,0x28位四位数据线模式
#defineOPEN_SCREEN0x0C//打开LCD显示
#defineDISPLAY_ADDRESS0x80//写地址指令
#defineCLEARSCREENLCD_en_com(0x01)//清屏
//***********//LCD1602的接线//*****************************
#defineLCDIOP0//LCD1602的高四位接在P0口的高四位
sbitLCD1602_RS=P0^0;//RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。
sbitLCD1602_RW=P0^1;//RW为读写信号线,高电平时进行读操作,低电平时进行写操作。
sbitLCD1602_EN=P0^2;//E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。
//*********************************************************//
RST=P3^4;
sbitACC7=ACC^7;//累加器
sbitACC0=ACC^0;
unsignedcharL_18B20,H_18B20;//分别存放低八位高八位的数据;
unsignedcharfg=0,zhengshu,xiaoshu1,xiaoshu2;//fg为负数标志位,zhengshu是温度的整数部分,xiaoshu1是十分位,xiaoshu2是百分位
unsignedchartimes[7]={55,39,16,7,11,3,7};//存放时间
unsignedcharkey=16;//存放健值
unsignedcharalarm_clock[3]={0};//用于存放闹钟的时间:
时分和闹钟的标志位
voidReset_18B20(void);//ds18b20复位程序
voidWait_18B20();//等待程序,等待ds18b20应答
bitReadbit_18B20(void);//读取一个bit的数据
unsignedcharReadbyte_18B20(void);//读取一个字节的数据
voidWritebyte_18B20(unsignedcharb);//写一个字节(控制字)
voidConvert(void);//开始转换
voidRead_18B20(void);//读取ds18b20
voidwrite_1302_byte(unsignedchard);//向1302写入一字节数据d
unsignedcharread_1302_byte(void);//从1302读出一字节数据并返回
voidwrite_1302_reg(unsignedcharadd,unsignedchard);//向1302地址add处写入数据d
unsignedcharread_1302_reg(unsignedcharadd);//从1302地址add处读出数据并返回
voidon_off_1302(unsignedcharch);//启动/停止计时,gate=0时启动计时,gate!
=0时停止计时
voidhour_mode_1302(unsignedcharch);//时间显示方式设置,ch=0时为24小时格式,ch!
=0时为12小时格式
voidwrite_1302_time(unsignedchar*time);//设置时间
voidread_1302_time(unsignedchartime[]);//读出时间
//**********************************************************************
voidLCD_en_com(unsignedcharcommand);//写命令指令
voidLCD_en_dat(unsignedchartemp);//写数据指令
voidLCD_set_xy(unsignedcharx,unsignedchary);//设置显示地址:
X为横轴(0-15),Y为纵轴(0-1).
voidLCD_write_char(unsignedx,unsignedchary,unsignedchardat);//写一个字符
voidLCD_write_string(unsignedcharx,unsignedchary,unsignedchar*s);//写一个字符串
voidLCD_write_int(unsignedcharx,unsignedchary,unsignedintintdat);//写无字符型整形数
voidLCD_init(void);//lcd初始化
voidLCD_Read_BF(void);//LCD读忙信号
//**********************************************************************
/*
LCD1602.c
CreatedbyZhengxihui
email:
zhengxihui0506@
May2007
*/
voidLCD_Read_BF(void)
{
LCD1602_RW=HIGH;//RW1
LCD1602_RS=LOW;//RS0
LCD1602_EN=HIGH;//EN1读忙信号
LCDIO=LCDIO&0x0F|0xf0;
while(LCDIO&MSB);
LCD1602_EN=LOW;
}
voidLCD_en_write(void)//EN端产生一个高电平脉冲,写LCD
{
LCD1602_EN=HIGH;
_nop_();
LCD1602_EN=LOW;
}
//*************************************
voidLCD_en_com(unsignedcharcommand)
{
LCD_Read_BF();
LCD1602_RS=LOW;//RS0写命令
LCD1602_RW=LOW;//RW0
LCDIO&=0x0F;
LCDIO=command&0xf0|LCDIO&0x0f;//先发送高四位数据
LCD_en_write();
command=command<<4;
LCDIO&=0x0F;
LCDIO=command&0xf0|LCDIO&0x0f;//发送低四位数据
LCD_en_write();
}
//*********************************
voidLCD_en_dat(unsignedchardat)
{
LCD_Read_BF();
LCD1602_RS=HIGH;//RS1写数据
LCD1602_RW=LOW;//RW0
LCDIO&=0x0F;
LCDIO=dat&0xf0|LCDIO&0x0f;//先发送高四位数据
LCD_en_write();
dat=dat<<4;
LCDIO&=0x0F;
LCDIO=dat&0xf0|LCDIO&0x0f;//发送低四位数据
LCD_en_write();
}
//**************设置显示地址:
X为横轴(0-15),Y为纵轴(0-1)********************
voidLCD_set_xy(unsignedcharx,unsignedchary)
{
unsignedcharaddress;
x&=0x0f;
if(!
y)
address=0x80+x;
else
address=0xc0+x;
LCD_en_com(address);
}
//***************写一个字符:
X为横轴(0-15),Y为纵轴(0-1)**********
voidLCD_write_char(unsignedx,unsignedchary,unsignedchardat)
{
LCD_set_xy(x,y);
LCD_en_dat(dat);
}
//****************写一个字符串***************************************
voidLCD_write_string(unsignedcharx,unsignedchary,constunsignedchar*s)
{
LCD_set_xy(x,y);
while(*s)
{
LCD_en_dat(*s);
s++;
}
}
//****************写一个无字符整数***************************************
voidLCD_write_int(unsignedcharx,unsignedchary,unsignedintintdat)
{
unsignedchari=0,temp[5];
LCD_set_xy(x,y);
if(intdat==0)
{
LCD_en_dat(0x30);
return;
}
while(intdat/10||intdat%10)
{
temp[i]=intdat%10;
intdat/=10;
i++;
}
while(i)
{
i--;
LCD_en_dat(temp[i]+0x30);
}
}
//*****//LCD的初始化函数(刚上电的时候一定要调用一次)//*********************
voidLCD_init(void)
{
LCD_en_com(DATA_MODE);//设计四位数据线模式
LCD_en_com(OPEN_SCREEN);//打开LCD显示
LCD_en_com(DISPLAY_ADDRESS);//设计首地址
CLEARSCREEN;//清屏
}
voidReset_18B20(void)//ds18b20复位程序
{
unsignedchari;
DS18B20=0;
i=110;
while(i>0)i--;
DS18B20=1;
i=6;
while(i>0)i--;
}
voidWait_18B20()//等待程序,等待ds18b20应答
{
unsignedchari;
while(DS18B20);
while(~DS18B20);
i=6;
while(i>0)i--;
}
bitReadbit_18B20(void)//读取一个bit的数据
{
unsignedchari;
bitb;
DS18B20=0;
i++;i++;
DS18B20=1;
i++;i++;i++;i++;i++;
b=DS18B20;
i=13;
while(i>0)i--;
returnb;
}
unsignedcharReadbyte_18B20(void)//读取一个字节的数据
{
unsignedchari,j,b;
b=0;
for(i=1;i<=8;i++)
{
j=Readbit_18B20();
b=(j<<7)|(b>>1);//又玩野
}
returnb;
}
voidWritebyte_18B20(unsignedcharb)//写一个字节(控制字)
{
unsignedcharj,i;
bittemp;
for(j=1;j<=8;j++)
{
temp=b&0x01;
b=b>>1;
if(temp)//写“1”
{
DS18B20=0;
i++;i++;i++;i++;i++;
DS18B20=1;
i=13;
while(i>0)i--;
}
else//写“0”
{
DS18B20=0;
i=13;
while(i>0)i--;
DS18B20=1;
i++;i++;i++;i++;i++;
}
}
}
voidConvert(void)//开始转换
{
Reset_18B20();
Wait_18B20();//等待应答脉冲
Writebyte_18B20(0xcc);//跳过序列号脉冲
Writebyte_18B20(0x44);//转换命令
}
voidRead_18B20(void)//读取ds18b20
{
Convert();
Reset_18B20();
Wait_18B20();
Writebyte_18B20(0xcc);//跳过ROM
Writebyte_18B20(0xbe);//发送读取命令
L_18B20=Readbyte_18B20();//读取低八位数据
H_18B20=Readbyte_18B20();//读取高八位数据
if(H_18B20>0x7f)//最高位为1时温度是负
{
L_18B20=~L_18B20;//补码转换,取反加一
H_18B20=~H_18B20+1;
fg=1;//读取温度为负时fg=1
}
zhengshu=L_18B20/16+H_18B20*16;//整数部分
xiaoshu1=(L_18B20&0x0f)*10/16;//小数第一位
xiaoshu2=(L_18B20&0x0f)*100/16%10;//小数第二位
}
/*================================================================*/
/*向1302当前地址处写入1字节数据*/
/*================================================================*/
voidwrite_1302_byte(unsignedchard)
{
unsignedchari;
ACC=d;//将8位数据写入ACC
for(i=8;i>0;i--)//循环8次将ACC8位数据从低位到高位写入1302
{
IO=ACC0;//将ACC的最低位转送到IO口
SCLK=1;//上升沿写入1位数据
SCLK=0;
ACC=ACC>>1;//将ACC次低位变为最低位
}
}
/*=================================================================*/
/*=================================================================*/
/*从1302的当前地址处读出1字节数据*/
/*=================================================================*/
unsignedcharread_1302_byte(void)
{
unsignedchari;
for(i=8;i>0;i--)
{
ACC=ACC>>1;
ACC7=IO;
SCLK=1;//时钟下降沿读1位数据
SCLK=0;
}
return(ACC);
}
/*=================================================================*/
/*将数据Data写入1302寄存器add处*/
/*================================================================*/
voidwrite_1302_reg(unsignedcharadd,unsignedchard)
{
RST=0;
SCLK=0;
RST=1;
write_1302_byte(add);//将1302的指针移到add处
write_1302_byte(d);//往add处写入数据
SCLK=1;
RST=0;//停止写数据
}
/*=================================================================*/
/*读寄存器add处的值*/
/*==================================================================*/
unsignedcharread_1302_reg(unsignedcharadd)
{
unsignedchard;
RST=0;
SCLK=0;
RST=1;
write_1302_byte(add);
d=read_1302_byte();
SCLK=1;
RST=0;
return(d);
}
/*=================================================================*/
/*设置时间,time[0]-time[6]数据存放顺序为:
秒,分,时,日,月,星期,年*/
/*===================================================================*/
voidwrite_1302_time(unsignedchar*time)
{
unsignedcharadd=0x80;//地址add初值(秒),偶数地址为只写
unsignedchari;
unsignedchartimeBCD[7];//用以存放time数据的BCD码值
bdataunsignedcharl,h;//单位变量,分别存放时间数据(8421BCD码)的低4位和高4位
for(i=0;i<7;i++)//将时间数据转为BCD码放入timeBCD中
{
l=time[i]%10;
h=time[i]/10;
timeBCD[i]=h*16+l;
}
write_1302_reg(0x8e,0x00);//禁止写
for(i=0;i<7;i++)
{
write_1302_reg(add,timeBCD[i]);//将时间数据写入1302对应的寄存器
add+=2;//地址移动,确保地址为偶数
}
write_1302_reg(0x8e,0x80);//允许写
}
/*==================================================================*/
/*读取当前时间*/
/*==================================================================*/
voidread_1302_time(unsignedchartime[])
{
unsignedchari;
unsignedcharadd=0x81;//设置地址add初值(秒),奇数为只读
bdataunsignedcharl,h;//单位变量,分别存放时间数据(8421BCD码)的低4位和高4位,用以进行十进制转换
write_1302_reg(0x8e,0x00);//禁止写
for(i=0;i<7;i++)
{
time[i]=read_1302_reg(add);//将时间数据(8421BCD码)从1302对应的寄存器中读出
l=time[i]&0x0f;//l存放time的低4位,即个位
h=(time[i]>>4)&0x0f;//h存放time的高4位,即十位
time[i]=h*10+l;//时间数据以十进制形式放进time[i]中
add+=2;//地址移动,确保地址为奇数
}
}
/*======================================================================================*/
/*=====================================================================================*/
/*启动/停止计时,gate=0时启动计时,gate!
=0时停止计时*/
/*=====================================================================================*/
voidon_off_1302(unsignedcharch)
{
unsignedchartemp;
if(ch)
{
temp=read_1302_reg(0x80);//将秒当前值读入temp暂存
temp=temp|0x80;//将秒数据最高位置1
write_1302_reg(0x80,temp);//将置1后的秒数据写入秒寄存器,以定止计时
}
else
{
temp=read_1302_reg(0x80);//将秒当前值读入temp暂存
temp=temp&0x80;//将秒数据最高位置0
write_1302_reg(0x80,temp);//将最高位置0后的秒数据写入秒寄存器,以启动计时
}
}
/*=====================================================================================*/
/*=========================================================================================*/
/*时间显示方式设置,ch=0时为24小时格式,ch!
=0时为12小时格式*/
/*=========================================================================================*/
voidhour_mode_1302(unsignedcharch)
{
unsignedchartemp;
if(ch)
{
temp=read_1302_reg(0x85);//将小时当前值读入temp暂存
temp=temp|0x80;//将小时数据最高位置1
write_1302_reg(0x84,temp);//将置1后的小时数据写入小时寄存器,变为12小时格