基于51单片机的DS12C887时钟芯片的程序

合集下载

基于DS12C887时钟芯片的多功能万年历设计概要

基于DS12C887时钟芯片的多功能万年历设计概要

一、系统的结构和工作原理 1.系统结构此次课程设计的万年历,以AT89S52单片机为主控核心,由LCD 显示屏、DS12C887时钟芯片、温度传感器DS18B20、蜂鸣器、功能键盘、复位电路、晶振、电源模块等组成,系统结构框图如图1所示。

AT89S52单片机温度传感器DS18B20DS12C887时钟芯片LCD 显示屏(1602)蜂鸣器复位电路功能键盘电源模块图1 系统结构框图2.工作原理主控制器每隔一段时间(小于一秒钟)读一次时钟芯片的内部寄存器的值,将读出的时间、星期、温度等值实时显示在LCD 液晶屏上。

同时,主控制器不断的扫描按键电路和温度测量电路,当有按键按下时,识别出按键的值并调整相应的时间、星期值再写入时钟芯片内部。

温度数据由测量电路获得的环境温度值送人显示电路。

二、硬件设计1.主控核心—AT89S52单片机AT89S52是一个低功耗,高性能CMOS8位单片机,具有8K 在系统可编程Flash 存储器。

采用ATMEL 公司的高密度、非易失性存储技术制造,兼容标准MCS-51指令系统及80C51引脚结构。

2.DS12C887时钟电路DS12C887与计算机常用的时钟芯片MC146818和DS12887管脚兼容,可直接替换。

采用DS12C887芯片设计的时钟电路无需任何外围电路和器件,并且有良好的微机接口。

DS12C887芯片内有微功耗,外围接口简单,精度高,工作稳定可靠等优点,广泛用于各种需要较高精度的实时时钟系统中。

DS12C887主要功能如下:(1)内含一个锂电池,断电后运行十年以上不丢失数据; (2)计秒、分、时、天、星期、日、月、年、并有闰年补偿功能;(3)二进制数码或BCD 码表示时间,日历和定闹;(4)12小时或24小时制,12小时时钟模式带有PM 和AM 指示,有夏令时功能; (5)Motorola 和Intel 总线时序选择;(6)有128个字节RAM 单元与软件接口,其中14个字节作为时钟和控制寄存器,114 字节为通用RAM ,所有RAM 单元数据都具有掉电保护功能; (7)可编程方波信号输出;(8)中断信号输出(IRQ )和总线兼容、定闹中断、周期性中断、时钟更新周期、结束 中断可分别由软件屏蔽,也可分别进行测试; DS12C887时钟芯片和单片机的硬件连接如下图2 :EA/VPP 31XTAL119XTAL218RESET 9P3.7/RD 17P3.6/WR 16P3.2/INT012P3.3/INT113P3.4/T014P3.5/T115P1.01P1.12P1.23P1.34P1.45P1.56P1.67P1.78P0.039P0.138P0.237P0.336P0.435P0.534P0.633P0.732P2.021P2.122P2.223P2.324P2.425P2.526P2.627P2.728PSEN 29ALE/PROG 30P3.1/TXD 11P3.0/RXD 10VCC 40GND 20U1AT89S52VCC+C1210u FR910KS17Y112MHzC930p FC1030p FP00P01P02P03P04P05P06P07VCCP20P21P22P23P24P25P27P26P10P11P12P04P13P14P15P16P00P17P01P32P02P30P03P31P05P33P06P34P07P35P20P35WR P37P32P34242322212019181716151413121110987654321DS12C887CSASR/WNCDSRESETIRQNCNCNCSQWVCCGND AD7AD6AD5AD4AD3AD2AD1AD0NC MOT NC 123456789RP1RESPACKVCCU3P36P37图2 DS12C887与单片机的连接3.DS18B20温度传感器采用数字式温度传感器DS18B20,其仅需一条数据线进行数据传输,易于与单片机连接,可以去除A/D 模块,降低硬件成本,简化系统电路。

基于51单片机驱动DS12CR887时钟芯片用1602液晶显示的完整程序

基于51单片机驱动DS12CR887时钟芯片用1602液晶显示的完整程序

#include<reg52.h>#include<define.h>#define uchar unsigned char#define uint unsigned intvoid delay(uint z);sbit lcdrs=P3^5;sbit lcd_e=P3^4;sbit s1=P3^0;sbit s2=P3^1;sbit s3=P1^3;sbit s4=P1^2;sbit dscs=P1^4;sbit dsas=P1^5;sbit dsrw=P1^6;sbit dsds=P1^7;sbit dsirq=P3^2;sbit beep=P2^3;void set_time();void Disp_xq();void write_ds(uchar,uchar);uchar read_ds(uchar);uchar num,i,y,xq,mon,d,h,m,s,l,*p,als,alm,alh,a,aa;//定义全局变量uchar code table1[]="2013 02 13 TUE ";uchar code table2[]=" 00:00:00 00:00";uchar code table3[]={15,12,8,5,2, 14,9,6,3};uchar code table4[]={0x08,0x0F,0x12,0x0F,0x0A,0x1F,0x02,0x02, /*年*/0x0F,0x09,0x0F,0x09,0x0F,0x09,0x13,0x00, /*月*/0x1F,0x11,0x11,0x1F,0x11,0x11,0x1F,0x00, /*日*/0x11,0x0E,0x1F,0x1F,0x1F,0x0A,0x11,0x00,};/*闹钟符号*/uchar code table5[7][3]={"Mon","Tue","Wen","Thu","Fri","Sat","Sun"}; void delay(uint z)//延时函数{uint i,j;for(i=z;i>0;i--)for(j=110;j>0;j--);}void keyscan() //键位函数{ uchar j;if(s4==0) //闹铃开关{delay(5);while(!s4);if(a==0)a=1;else a=0;}if(s1==0) //调时键{ write_ds(0x0A,0x60);delay(5);while(!s1);if(aa<5)set_XY(table3[aa],1);else set_XY(table3[aa],0);write_com(0x0f);aa++;i=1;j=aa-1;if(aa==10){ aa=0;i=0;write_ds(0x0A,0xa0);write_com(0x0c);}while(s1==i){ delay(5);if(s4==0) //退出调时{delay(5);while(!s4);i=0;aa=0;}if(s2==0) //按键每次加1{delay(5);while(!s2);switch(j){delay(5);case 0:{alm++;if(alm==60)alm=0;write_ds(3,alm);write_sfm1(14,alm);write_com(0x80+0x40+15);};break; //闹铃分case 1:{alh++;if(alh==24)alh=0;write_ds(5,alh);write_sfm1(11,alh);write_com(0x80+0x40+12);};break; //闹铃时case 2:{s++;if(s==60)s=0;write_ds(0,s);write_sfm1(7,s);write_com(0x80+0x40+8);};break; //秒case 3:{m++;if(m==60)m=0;write_ds(2,m);write_sfm1(4,m);write_com(0x80+0x40+5);};break; //分case 4:{h++;if(h==24)h=0;write_ds(4,h);write_sfm1(1,h);write_com(0x80+0x40+2);};break; //时case 5:{xq++;if(xq==8)xq=1;write_ds(6,xq);Disp_xq();};break;//星期case 6:{d++;if(d==31)d=1;write_ds(7,d);write_sfm2(8,d);write_com(0x80+9);};break; //日case 7:{mon++;if(mon==13)mon=1;write_ds(8,mon);write_sfm2(5,mon);write_com(0x80+6);};break; //月case 8:{y++;if(y==64)y=0;write_ds(9,y);write_sfm2(2,y);write_com(0x80+3);}; break; //年}}if(s3==0) //按键每次减1{delay(5);while(!s3);switch(j){ delay(5);case 0:{if(alm==0)alm=60;alm--;write_ds(3,alm);write_sfm1(14,alm);write_com(0x80+0x40+15);};break; //闹铃分case 1:{if(alh==0)alh=24;alh--;write_ds(5,alh);write_sfm1(11,alh);write_com(0x80+0x40+12);};break; //闹铃时case 2:{if(s==0)s=60;s--;write_ds(0,s);write_sfm1(7,s);write_com(0x80+0x40+8);};break; //秒case 3:{if(m==0)m=60;m--;write_ds(2,m);write_sfm1(4,m);write_com(0x80+0x40+5);};break; //分case 4:{if(h==0)h=24;h--;write_ds(4,h);write_sfm1(1,h);write_com(0x80+0x40+2);};break; //时case 5:{if(xq==1)xq=8;xq--;write_ds(6,xq);Disp_xq();};break;//星期case 6:{if(d==1)d=31;d--;write_ds(7,d);write_sfm2(8,d);write_com(0x80+9);};break; //日case7:{if(mon==1)mon=13;mon--;write_ds(8,mon);write_sfm2(5,mon);write_com(0x80+6);};break; //月case 8:{if(y==0)y=64;y--;write_ds(9,y);write_sfm2(2,y);write_com(0x80+3);}; break; //年}}}}}void write_com(uchar com)//1602命令函数{lcdrs=0;P0=com;delay(1);lcd_e=1;delay(1);lcd_e=0;}void write_data(uchar date) //1602数据函数{lcdrs=1;P0=date;delay(1);lcd_e=1;delay(1);lcd_e=0;}void set_XY(uchar X,uchar Y)//设置字符显示位置{if(Y==0)X+=0x80;else X|=0xC0;write_com(X);}void DispOneChar(uchar X,uchar Y,uchar Data){ //显示单个字符set_XY(X,Y);write_data(Data);}void DispChars(uchar X,uchar Y,uchar *p,uchar count){ //显示字符串uchar i;for(i=0;i<count;i++){set_XY(X,Y);write_data(*p);X++;p++;}}void HZ() //写入自定义字符{uchar i;write_com(0x40);for(i=0;i<32;i++)write_data(table4[i]);}void write_sfm1(uchar add,uchar date)//写入s m h{ uchar ge,shi;ge=date%10;shi=date/10;write_com(0x80+0x40+add);write_data(0x30+shi);write_data(0x30+ge);}void write_sfm2(uchar add,uchar date)//写入y mon d{ uchar ge,shi;ge=date%10;shi=date/10;write_com(0x80+add);write_data(0x30+shi);write_data(0x30+ge);}void init () //初初初初初初初初初初初初初初始化函数{ beep=0;a=0;aa=0;i=0;lcd_e=0;EA=1;EX0=1;IT0=1;write_ds(0x0B,0x26);//DS寄存器B// read_ds(0x0C); //DS寄存器C write_ds(0x0A,0x20);//DS寄存器Awrite_com(0x38); //指令6write_com(0x0c); //指令4write_com(0x01); //指令1write_com(0x80); //指令8write_com(0x06); //指令3DispChars(0,1,p=table2,16);//00:00:00DispChars(0,0,p=table1,2);//20set_time();}void write_ds(uchar add,uchar date){dscs=0;dsas=1;dsds=1;dsrw=1;P0=add;dsas=0;dsrw=0;P0=date;dsrw=1;dsas=1;dscs=1;}uchar read_ds(uchar add){uchar ds_date;dsas=1;dsds=1;dsrw=1;dscs=0;P0=add;dsas=0;dsds=0;P0=0xff;ds_date=P0;dsds=1;dsas=1;dscs=1;return ds_date;}#include<keyscan.h>void set_time()//设置时间{write_ds(9,13);//年write_ds(8,2);//月write_ds(7,18);//日write_ds(6,4);//星期write_ds(5,0);//闹铃时write_ds(4,0);//时write_ds(3,1);//闹铃分write_ds(2,0);//分write_ds(1,0);//闹铃秒}void Disp_time() //读出时间{if(i==0){ write_ds(0x0A,0xa0);write_com(0x0c);s=read_ds(0);//读秒m=read_ds(2);//读分alm=read_ds(3); //闹铃分h=read_ds(4);//读时alh=read_ds(5);//闹铃时d=read_ds(7);//读日xq=read_ds(6);//读星期mon=read_ds(8);//读月y=read_ds(9);//读年write_sfm1(7,s);//显秒write_sfm1(4,m);//显分write_sfm1(14,alm);//闹铃分write_sfm1(1,h);//显时write_sfm1(11,alh);//闹铃时write_sfm2(8,d);//显日write_sfm2(5,mon);//显月write_sfm2(2,y);//显年}}void Disp_xq() //显星期{uchar t;write_com(0x0c);xq=read_ds(6);for(t=0;t<3;t++)DispOneChar(t+12,0,table5[xq-1][t]);}void Disp_HZ() //显示自定义字符{HZ();write_com(0x0c);DispOneChar(4,0,0x00);//显示年DispOneChar(7,0,0x01);//显示月DispOneChar(10,0,0x02);//显示日if(a==0)DispOneChar(10,1,0x03);//显示闹钟符号else DispOneChar(10,1,0x20);}void main() //主函数{init();while(1){ Disp_HZ();keyscan();Disp_time();Disp_xq();}}void exter() interrupt 0{beep=1;delay(500);// write_ds(0x0C,0x00);}。

DS12C887 例程

DS12C887  例程
case 4:
num1=0;
}
}
if(jian==0)//闹铃减少键
delay(9);
if(jian=);
switch(num1)
{
case 1:
shi=read(0x05);
shi--;
if(shi==-1)
shi=23;
writesfm(4,shi);
write(0x05,shi);
yue++;
if(yue==13)
yue=1;
writeryn(6,yue);
write(0x08,yue);
break;
case 3:
ri=read(0x07);
ri++;
if(ri==32)
ri=1;
writeryn(9,ri);
write(0x07,ri);
break;
case 4:
shi=read(0x04);
write(0x08,2);
write(0x09,15);
write(0x06,3);
}
void initalize()//液晶初始化函数
{
command(0x38);
command(0x0c);
command(0x04);
command(0x01);
}
void writesfm(uchar dizhi,uchar shuju)//写入液晶显示时分秒
miao=read(0x00);
miao++;
if(miao==60)
miao=0;
writesfm(10,miao);
write(0x00,miao);
break;

基于DS12CR887的多功能电子时钟设计

基于DS12CR887的多功能电子时钟设计

基于DS12CR887的多功能电子时钟设计作者:刘坤来源:《数字化用户》2013年第07期【摘要】本设计主要对51系列单片机控制的多功能实时时钟进行了研究,时钟芯片采用美国DALLAS公司生产的DS12CR887芯片,单片机采用STC89C52RC芯片,液晶屏用YM1602C型LCD。

实现了声控背光,液晶显示,时间显示,时间设置,闹钟提醒,闹钟设置等功能。

【关键词】实时时钟DS12CR887 单片机STC89C52RC 液晶屏YM1602C在日常生活中和自动控制系统中,经常遇到对时间实时监控的需求,这就给具有多种功能的时钟提供了市场。

这里给出了时钟芯片DS12CR887及液晶显示屏YM1602C与单片机的连接电路,声控背光电路,软件流程等供大家参考。

一、设计思路本设计为模块化设计,总体上可分为三个模块:(一)电源模块:系统输入12V±3V直流电压,经三端集成稳压器7805整成标准5V直流电,去耦后可为单片机及其他芯片供电。

(二)声控背光:传感器采用电容式麦克风,经两级三极管放大电路对声音信号进行放大,再经缓冲器增加其驱动能力,最后和单片机的一个控制引脚与非后接到LCD背光正极。

(三)主体电路:由单片机,实时时钟芯片,液晶屏和键盘组成。

单片机,时钟,液晶屏都挂在数据总线上进行数据交换,时钟和液晶屏通过少数地址总线和控制总线和单片机相连,以便控制。

二、电路硬件设计电路硬件接线图如图1所示:单片机P0口作为数据口连接在数据总线上[1],数据总线上还挂有液晶屏和时钟芯片,P2口中的一部分做了控制引脚,P2.4接液晶屏的使能端,P2.2接液晶屏的读写选择端,P2.0接液晶屏的命令数据选择端,P2.1经非门接时钟芯片的使能端,单片机的读写分别接时钟芯片的读写引脚,P1口的低四位和外部中断1引脚做了独立键盘输入,外部中断0接了时钟芯片的中断输出引脚,电容式麦克风经两级三极管放大电路放大[2]和P1.4引脚共同控制液晶屏背光,时钟芯片的方波输出端接蜂鸣器作为闹钟动作装置。

基于51单片机的DS12C887时钟芯片的时钟电路设计

基于51单片机的DS12C887时钟芯片的时钟电路设计

摘要:本设计开发了一款具有日期、时间、星期和气温同步显示功能的电子时钟.工作原理是主控MCU读取实时时钟芯片DS12C887,获取时间信息,由全数字单总线结构温度传感器DS18B20读取温度信息,经MCU处理,送LCD显示,关键字:DS12C887 DS18B20 电子时前言随着科学技术的不断发展, 人们对时间计量的要求越来越高。

在当今社会,电子时钟已经得到相当广泛的应用,产品多样,发展更是多元化。

本作品是以STC89C51单片机作为主控芯片,使用12MHZ的晶振,使用专用时钟日历芯片DS12C887产生时间信息,时间精确。

软件部分以C语言为主体,用1602LCD液晶屏显示输出信息,输出信息量多,更直观、人性化。

该时钟可实现人机交互,可通过提供的键盘对其进行调整。

系统具有以下功能:年、月、日、时、分、秒显示;12小时/24小时模式切换,在12小时模式中,用AM和PM区分上午和下午;秒表功能;整点闹铃和报时功能,且闹钟可设置多组。

本次设计的电子时钟系统由单片机最小系统,1602LCD液晶屏,时钟芯片,调整按键,蜂鸣器,电源五大部分组成。

1. 课题分析随着电子技术的发展,电子技术为人们的生活带来了越来越大的方便.本课题旨在借助实时时钟芯片DS12C887和温度传感器DS18B20 和51单片机设计一个多功能的电子时钟.由于DS12C887芯片内附加锂电池,在上电情况下可以通过电源充电,断电后可以利用内部锂电池供电继续工作,在掉电重新上电后,不影响时间数据,不需重新对时,方便可靠.2. 方案论证方案一、利用单片机内部定时器产生秒信号,通过软件处理得到时间信息,送LCD显示.方案二、利用通用串行实时时钟芯片DS1302产生时间信息,利用MCU读取时间信息,送LCD 显示.方案三、通过实时时钟芯片DS12887,获取时间信息,经MCU处理,送LCD显示.方案一电路结构简单,可控性强,但断电后时间数据完全消失,再次上电后需重新设定,且由于电路本身缺陷和附加干扰较多,时间误差较大.方案二电路结构简单,时间精度较高,由于使用串行数据传输,节省MCU资源,但DS1302无内置电池,掉电后,数据丢失,重新上电后需对时.方案三采用实时时钟芯片DS12C887,其内部具有内置锂电池,在掉电的情况下可以正常工作10年以上,且带有非易失性RAM,可以保证在掉电的情况下,用户的定时信息不会丢失;带有温度补偿,保证时间数据的准确.经过综合考虑,我们认为方案三满足设计需求.2.2温度部分由于只是测量气温,用数字温度传感器单总线结构DS18B20即可满足要求,该器件采用单总线结构,且数字传输,可以与CPU直接接口,电路结构简便,可靠性好.2.3主控部分选用单片微控制器AT89C52作为主控.系统方案方框图如图2.1所示.图2.1 系统方案3.方案实现3.1 器件简介(1)AT89C52AT89C52是ATMEL公司生产的通用低功耗8位CMOS微控器,具有8051内核和8KB的可编程Flash程序存储空间以及256字节RAM.有32个通用IO口线和全双工串口,两个数据指针、两个16位可编程计数器/定时器、8个2级优先级中断源,具有片内时钟电路,通过简单的外接器件即可实现时钟电路.(2)DS12C887引脚结构及其功能如图3.1.图3.1 DS12C887引脚结构AD0-AD7:地址/数据总线NC :空脚MOT :总线模式选择CS :片选信号AS :地址锁存信号R/W :写信号(intel总线模式下)DS :读信号(intel总线模式下)RESET :复位信号IRQ : 中断请求输岀VCC :+5V电源GND :电源地DS12C887是美国DALLAS半导体公司生产的实时时钟芯片.采用24 引脚双列直插式的封装形式.芯片的晶体振荡器、振荡电路、充电电路和可充电锂电池等一起封装在芯片内部,组成一个加厚的集成电路模块.电路通电时,其内部充电电路便自动对其内部电池充电.可保证时钟数据10 年内不会丢失.DS12C887内部设有方便的接口电路,接口设计简便,使其与各种微处理器的接口大大简化.使用时无需外围电路元件,通过对MOT引脚的电平控制,可以实现与不同的计算机总线连接.DS12C887 能够自动存取并更新当前的时间,CPU 可通过读取DS12C887 的内部时标寄存器得到当前的时间和日历,也可通过选择二进制码或BCD 码初始化芯片的10 个时标寄存器.其中114 字节的非易失性静态RAM 可供用户使用,可以在控制器掉电的情况下,保存一些重要的数据.DS12C887 的4 个状态寄存器用来控制和指出DS12C887 模块当前的工作状态,除数据更新周期外,程序可随时读写这4 个寄存器.其内部结构如下图3.2.图3.2 DS12C887内部结构(3)DS18B20DS18B20是美国DALLAS半导体公司生产的可组网数字式温度传感器,在其内部使用了在板(ON-B0ARD)专利技术.全部传感元件及转换电路仅集成在形如三极管的一个集成电路内.DS18B20采用单总线接口方式,与微处理器连接时仅需要一条总线即可实现微处理器与DS18B20的双向通讯;支持多点组网功能,多个DS18B20可以并联在一条总线上,即可实现多点测温;在使用中不需要任何外围元件.测温范围为-55℃~+125℃,结果以9位数字量方式串行传送.DS18B20测温原理如图3.3所示.图3.3 DS18B20内部结构图中低温度系数晶振的振荡频率受温度影响很小,用于产生固定频率的脉冲信号送给计数器1.高温度系数晶振随温度变化其振荡率明显改变,所产生的信号作为计数器2的脉冲输入.计数器1和温度寄存器被预置在-55℃所对应的一个基数值.计数器1对低温度系数晶振产生的脉冲信号进行减法计数,当计数器1的预置值减到0时,温度寄存器的值将加1 ,计数器1的预置将重新被装入,计数器1重新开始对低温度系数晶体振荡器产生的脉冲信号进行计数,如此循环直到计数器2计数到0时,停止温度寄存器值的累加,此时温度寄存器中的数值即为所测温度.其内部带有非线性修正,确保温度数据的准确性.DS18B20的测温分辨率为0.5℃以9位数据格式表示,其中最低有效位(LSB)由比较器进行0.25℃比较,当计数器1中的余值转化成温度后低于0.25℃时,清除温度寄存器的最低位(LSB),当计数器1中的余值转化成温度后高于0.25℃,置位温度寄存器的最低位(LSB),DS18B20温度数据格式如表3.1所示.表3.1 DS18B20温度数据格式DS18B20采用12位二进制数据表示温度,分成两个字节,低字节低四位为小数位,低字节高四位和高字节低四位组成温度信息的8位整数位,其中第一位为符号位,为0表示温度为正值,为1表示温度为负值.当温度为负值时,数据采用补码存放.高字节高四位无效,与符号位保持一致.温度与数据对应关系如表3.2所示.表3.2 部分温度对应数据3.2硬件电路设计本课题涉及电路原理图和PCB图均由Altium Designer Summer 09绘制.(1)电源部分图3.7 整机电源电路由于电路微控器供电电压为5V,osyno6188供电电压为3V或4.5V,osyno6188对电源电压精度要求不高,决定整机采用5V电源供电,在电源处串联一只1N4003二极管,为osyno6188供电,1N4003为硅管,正向导通压降在0.7V左右,经过二极管后,得到约4.3V 电压,为osyno6188供电.电源电路为普通稳压电源电路,由于不是本项目主要方面,不再赘述.(2)AT89C52最小系统电路图3.8 AT89C52单片机最小系统电路由震荡电路,复位电路和单片机构成最小系统.震荡电路为单片机提供工作时钟,由石英晶体和补偿电容构成.由于语音部分需要1200bps波特率,石英晶体选取11.0592MHz,保证波特率零误差,补偿电容选取30pF瓷片电容.复位电路在上电时为单片机提供复位信号,由10uF电容和10K电阻构成的RC充电电路构成,当系统复位上电瞬间,电源通过电阻R为电容充电,在电阻上得到下降的指数充电电压,由高电平经过一段时间到达低电平,提供单片机需要的高脉冲复位信号.电源部分电容为去耦电容.EA拉高,MCU 上电后,从内部程序存储器开始执行.(3)osyno6188及外围电路设计.图3.9 osyno6188及外围电路系统采用4.5V电源供电模式,电源VDD由电源电路中VCC串接二极管后获得.电源电路、复位电路以及时钟电路参考osyno6188用户手册.RXD、TXD为串行总线接口,分别连接主控MCU的TXD、RXD端.(4)DS12C887与AT89C52接口电路设计.图3.10 DS12C887接口电路DS12C887的AD0-AD7为地址\数据复用总线,与控制器地址\数据总线(P0口)直接连接,R2为上拉电阻;MOT为总线模式选择引脚,接地选择INTEL总线连接方式;R/W在INTEL 总线模式下位写使能,接控制器读信号WR(P3.6)端;DS在INTEL总线模式下为读使能信号,接控制器读信号RD(P3.6)端;AS为地址锁存,接控制器地址锁存信号ALE(30脚)端;RST接电源拉高,片选CS直接接地使能。

基于51单片机电子时钟设计

基于51单片机电子时钟设计

基于51单片机的电子时钟设计摘要本电子时钟以STC89C52单片机作为主控芯片,采用DS12C887时钟芯片,使用1602液晶作为显示输出。

该时钟走时精确,具有闹钟设置,以及可同时显示时间、日期等多种功能。

本文将详细介绍该电子时钟涉及到的一些基本原理,从硬件和软件两方面进行分析。

【关键词】STC89C52单片机DS12C887时钟芯片1602液晶蜂鸣器目录一、绪论 (4)1.1 电子时钟功能 (4)1.2设计方案 (4)二、硬件设计 (4)2.151单片机部分设计 (4)2.2USB供电电路设计 (5)2.3 串行通信电路设计 (6)2.4DS12C887时钟芯片电路的设计 (6)2.51602LCD液晶屏显示电路设计 (7)2.6蜂鸣器电路设计 (8)2.7按键调整电路设计 (8)三、软件设计 (9)3.1系统程序流程图设计 (9)3.2程序设计 (11)四、心得体会 (22)参考文献 (23)一、绪论1.1电子时钟功能(1)在1602液晶上显示年、月、日、星期、时、分、秒,并且按秒实时更新显示。

(2)具有闹铃设定即到时报警功能,报警响起时按任意键可取消报警。

(3)能够使用实验板上的按键随时调节各个参数,四个有效键分别为功能选择键、数值增大键、数值减小键和闹钟查看键。

(4)每次有键按下时,蜂鸣器都以短“滴”声报警。

(5)利用DS12C887自身掉电可继续走时的特性,该时钟可实现断电时间不停、再次上电时时间仍准确显示在液晶上的功能。

1.2设计方案DS12C887时钟芯片+1602LCD液晶屏DS12C887时钟芯片功能丰富、价格适中,能够自动产生世纪、年、月、日、时、分、秒等时间信息,其内部含有世纪寄存器,从而利用硬件电路解决“千年”问题。

DS12C887中自带锂电池,外部掉电时,其内部时间信息还能保持10年之久。

1602LCD液晶屏可以输出2行,每行显示16个字符。

1602LCD液晶屏显示清晰且不会闪烁,由于液晶屏是数字式的,因此和单片机系统的接口简单,操作方便。

基于DS12C887的高精度时钟设计

基于DS12C887的高精度时钟设计

基于DS12C887的高精度时钟设计摘要:设计以ATM89C52单片机为核心的,采用LCD1602液晶和专门时钟芯片DS12C887的高精度时钟,该时钟具有电路结构简单合理、显示精度高和实时更新显示等特点。

介绍了DS12C887芯片和LCD1602液晶的特点、功能和实现方法,给出了ATM89C52单片机的外部接口电路和相关程序的设计方法。

关键词:单片机;时钟芯片;实时时钟;接口电路0引言随着人们生活水平的提高和智能化电子集成的发展,许多电子设备,通常要进行与时间有关的控制,并需要记录实时的时间信息。

许多重要的信息不仅需要记录其内容,还需要记录发生的准确时间。

有些设备需要长时间运行并且保证掉电数据不丢失。

通常的单片机并没有这样的实时时钟功能,单片机掉电或者时钟晶振的误差会导致时间错乱。

如果完全用程序设计时钟,又会占用单片机大量的系统资源,影响到其他功能的实现。

美国Dallas公司的DS12C887实时时钟芯片,将晶振、写保护电路、可充电锂电池等集成,可保证时钟精确、掉电时时钟数据不丢失,可靠性高,使用简单。

1系统原理本系统利用DS12C887芯片设计的高精度时钟,与52单片机相连,通过1602液晶显示,实现在1602液晶上精确显示年、月、日、时、分、秒,并且在掉电的情况下仍能记录时间数据,通电后更新实时显示,与矩阵键盘相连接,能够使用按键调节时间,设定闹钟。

2核心芯片AT89C52单片机本系统核心芯片采用ATMEL公司生产的AT89C52单片机。

AT89C52是51系列单片机的其中一种型号,是一种低电压、高性能的8位单片机。

其片内含有8K bytes的可反复擦写Flash只读程序存储器和256 bytes的随机存取数据存储器。

AT89C52有40个引脚,其中32个为外部双向输入/输出(I/O)引脚,同时内含2个外部中断口,51单片机内部共有定时器T0和定时器T1两个16位可编程定时/计数器,AT89C52单片机内部比51单片机多一个T2定时/计数器,它们可以按照常规方法进行编程,并兼容标准MCS-51指令系统。

基于ds12c887的多功能时钟设计

基于ds12c887的多功能时钟设计

中北大学大学生电子设计竞赛项目总结技术报告负责人:学号:学院、系:信息与通信工程学院专业:光电信息工程联系电话:E_m a i l: 1677882726@项目名称:基于DS12C887时钟芯片的多功能时钟设计指导教师:小组成员:赵策、高洁、黄康2013年 03 月 01 日目录一、设计背景 (3)二、主要研究内容 (3)三、总体思路与研究方案1、LCD1602模块 (4)2、DS18B20模块 (6)3、蜂鸣器 (9)4、独立键盘模块 (9)5、时钟芯片DS12C887模块 (15)四、主要研究成果 (17)五、存在问题即以后努力方向 (18)附件:设计原理图一、项目背景在本次全国大学生电子设计大赛人员选拨之际,我小组准备设计出一个多功能高精度时钟。

众所周知,电子时钟在日常生活中十分常见,本实验原利用单片机定时器中断系统来实现时钟设计,但考虑到走时不够精确,又不具有掉电保护功能,偶尔的掉电和晶振的误差都会造成时间的错乱,并且完全用程序计时也会占用大量的系统资源,影响其他系统的正常运行,与正常的时钟相比相去甚远,所以我们改用新的方案加以实现。

本方案采用时钟芯片DS12C887与单品机实验板相连,DS12C887芯片相比一些如DS1302等表贴式芯片体积较大,内部集成了可充电锂电池,同时内部还集成了32.768KHz 的标准晶振,一旦设定好时间,即使系统主电源掉电,该芯片仍然可以靠内部电源正常运行,当系统重新上电后,可继续给锂电池充电,这样可有效的保证了时间的延续性,并且精度高,运行稳定,使用方便,广泛应用于各种高精度的实时时钟系统中。

该芯片与晶振和电池集成在了一起,能自动产生世纪、年、月、日、时、分、秒等时间信息,少于31天的月份,月末日期自动调整,具有闰年补偿功能,有效期至2100年,对于一天的时间可有12小时制和24小时制两种模式,在12小时制中利用AM 和PM 来提示上午还是下午。

该时钟芯片内部有一个精密的温度补偿电路,用来监视Vcc 的状态,如果主电源有故障,会自动切换到备用电源。

基于51单片机和DS12C887时钟芯片的c语言程序

基于51单片机和DS12C887时钟芯片的c语言程序

基于51单片机和DS12C887时钟芯片的c语言程序代码1:#include<reg52.h>#include<define.h>void delay(uint z)//延时函数{uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void di() //蜂鸣器报警声音{beep=0;delay(100);beep=1;}void write_com(uchar com){//写液晶命令函数rs=0;lcden=0;P0=com;delay(3);lcden=1;delay(3);lcden=0;}void write_date(uchar date){//写液晶数据函数rs=1;lcden=0;P0=date;delay(3);lcden=1;delay(3);lcden=0;}void init(){//初始化函数uchar num;EA=1;//打开总中断EX1=1;//开外部中断1IT1=1;//设置负跳变沿触发中断flag1=0;//变量初始化t0_num=0;s1num=0;week=1;dula=0;//关闭数码管显示wela=0;lcden=0;rd=0;/*以下几行在首次设置DS12C887时使用,以后不必再写入write_ds(0x0A,0x20);//打开振荡器write_ds(0x0B,0x26);//设置24小时模式,数据二进制格式//开启闹铃中断set_time();//设置上电默认时间-----------------------------------------------------*/write_com(0x38);//1602液晶初始化write_com(0x0c);write_com(0x06);write_com(0x01);write_com(0x80);for(num=0;num<15;num++)//写入液晶固定部分显示{write_date(table[num]);delay(1);}for(num=0;num<11;num++){write_date(table1[num]);delay(1);}}void write_sfm(uchar add,char date){//1602液晶刷新时分秒函数4为时,7为分,10为秒char shi,ge;shi=date/10;ge=date%10;write_com(0x80+0x40+add);write_date(0x30+shi);write_date(0x30+ge);}void write_nyr(uchar add,char date){//1602液晶刷新年月日函数3为年,6为分,9为秒char shi,ge;shi=date/10;ge=date%10;write_com(0x80+add);write_date(0x30+ge);}void write_week(char we){//写液晶星期显示函数write_com(0x80+12);switch(we){case 1: write_date('M');delay(5);write_date('O');delay(5);write_date('N');break;case 2: write_date('T');delay(5);write_date('U');delay(5);write_date('E');break;case 3: write_date('W');delay(5);write_date('E');delay(5);write_date('D');break;case 4: write_date('T');delay(5);write_date('H');delay(5);write_date('U');break;case 5: write_date('F');delay(5);write_date('R');delay(5);write_date('I');break;case 6: write_date('S');delay(5);write_date('A');delay(5);write_date('T');break;case 7: write_date('S');delay(5);write_date('U');delay(5);write_date('N');break;}}void keyscan(){if(flag_ri==1){//这里用来取消闹钟报警,任一键取消报警if((s1==0)||(s2==0)||(s3==0)||(s4==0)){delay(5);if((s1==0)||(s2==0)||(s3==0)||(s4==0)){while(!(s1&&s2&&s3&&s4));di();flag_ri=0;//清除报警标志}}}if(s1==0)//检测S1{delay(5);if(s1==0){s1num++;//记录按下次数if(flag1==1)if(s1num==4)s1num=1;flag=1;while(!s1);di();switch(s1num){//光标闪烁点定位case 1: write_com(0x80+0x40+10);write_com(0x0f);break;case 2: write_com(0x80+0x40+7);break;case 3: write_com(0x80+0x40+4);break;case 4: write_com(0x80+12);break;case 5: write_com(0x80+9);break;case 6: write_com(0x80+6);break;case 7: write_com(0x80+3);break;case 8: s1num=0;write_com(0x0c);flag=0;write_ds(0,miao);write_ds(2,fen);write_ds(4,shi);write_ds(6,week);write_ds(7,day);write_ds(8,month);write_ds(9,year);break;}}}if(s1num!=0)//只有当S1按下后,才检测S2和S3 {if(s2==0){delay(1);if(s2==0){while(!s2);di();switch(s1num){//根据功能键次数调节相应数值case 1: miao++;if(miao==60)miao=0;write_sfm(10,miao);write_com(0x80+0x40+10);break;case 2: fen++;if(fen==60)fen=0;write_sfm(7,fen);write_com(0x80+0x40+7);break;case 3: shi++;if(shi==24)shi=0;write_sfm(4,shi);write_com(0x80+0x40+4);break;case 4: week++;if(week==8)week=1;write_week(week);write_com(0x80+12);break;case 5: day++;if(day==32)day=1;write_nyr(9,day);write_com(0x80+9);break;case 6: month++;if(month==13)month=1;write_nyr(6,month);write_com(0x80+6);break;case 7: year++;if(year==100)year=0;write_nyr(3,year);write_com(0x80+3);break;}}}if(s3==0){delay(1);if(s3==0){while(!s3);di();switch(s1num){//根据功能键次数调节相应数值case 1: miao--;if(miao==-1)miao=59;write_sfm(10,miao);write_com(0x80+0x40+10);break;case 2: fen--;if(fen==-1)fen=59;write_sfm(7,fen);write_com(0x80+0x40+7);break;case 3: shi--;if(shi==-1)shi=23;write_sfm(4,shi);write_com(0x80+0x40+4);break;case 4: week--;if(week==0)week=7;write_week(week);write_com(0x80+12);break;case 5: day--;if(day==0)day=31;write_nyr(9,day);write_com(0x80+9);break;case 6: month--;if(month==0)month=12;write_nyr(6,month);write_com(0x80+6);break;case 7: year--;if(year==-1)year=99;write_nyr(3,year);write_com(0x80+3);break;}}}}if(s4==0)//检测S4{delay(5);if(s4==0){flag1=~flag1;while(!s4);di();if(flag1==0){//退出闹钟设置时保存数值flag=0;write_com(0x80+0x40);write_date(' ');write_date(' ');write_com(0x0c);write_ds(1,miao);write_ds(3,fen);write_ds(5,shi);}else{//进入闹钟设置read_alarm();//读取原始数据miao=amiao;//重新赋值用以按键调节fen=afen;shi=ashi;write_com(0x80+0x40);write_date('R');//显示标志write_date('i');write_com(0x80+0x40+3);write_sfm(4,ashi);//送液晶显示闹钟时间write_sfm(7,afen);write_sfm(10,amiao);}}}}void write_ds(uchar add,uchar date){//写12C887函数dsas=1;dsds=1;dsrw=1;P0=add;//先写地址dsas=0;dsrw=0;P0=date;//再写数据dsrw=1;dsas=1;dscs=1;}uchar read_ds(uchar add) {//读12C887函数uchar ds_date;dsas=1;dsds=1;dsrw=1;dscs=0;P0=add;//先写地址dsas=0;P0=0xff;ds_date=P0;//再读数据dsds=1;dsas=1;dscs=1;return ds_date;}/*---首次操作12C887时给予寄存器初始化--- void set_time(){//首次上电初始化时间函数write_ds(0,0);write_ds(1,0);write_ds(2,0);write_ds(3,0);write_ds(4,0);write_ds(5,0);write_ds(6,0);write_ds(7,0);write_ds(8,0);write_ds(9,0);}----------------------------------------*/void read_alarm(){//读取12C887闹钟值amiao=read_ds(1);afen=read_ds(3);ashi=read_ds(5);}void main()//主函数{init();//调用初始化函数while(1){keyscan();//按键扫描if(flag_ri==1)//当闹钟中断时进入这里{di();delay(100);di();delay(500);}if(flag==0&&flag1==0)//正常工作时进入这里{keyscan();//按键扫描year=read_ds(9);//读取12C887数据month=read_ds(8);day=read_ds(7);week=read_ds(6);shi=read_ds(4);fen=read_ds(2);miao=read_ds(0);write_sfm(10,miao);//送液晶显示write_sfm(7,fen);write_sfm(4,shi);write_week(week);write_nyr(3,year);write_nyr(6,month);write_nyr(9,day);}}}void exter() interrupt 2//外部中断1服务程序{ uchar c; //进入中断表示闹钟时间到,flag_ri=1; //设置标志位,用以大程序中报警提示c=read_ds(0x0c);//读取12C887的C寄存器表示响应了中断}代码2:#include<reg52.h>#include"shijian.h"/**********************模式选择*******************/ void keyscan1(){if(s4==0);{delay(5);if(s4==0){s4num++;while(!s4);switch(s4num){case 1:flag1=~flag1;if(flag1==1) //打铃时间间隔设置标志位(防止在设置时显示时间){ //把闹铃的寄存器作为打铃的寄存器使用read_alarm(); //先读取闹铃时间miao=amiao; //在把闹铃值赋给时间值用以调节fen=afen;shi=ashi;write_com(0x80+0x40);write_date('R'); //显示标志write_date('i');write_com(0x80+0x40+3);display(0x40+4,ashi); //显示间隔时间display(0x40+7,afen);display(0x40+10,amiao);}break;/************************************/case 2:flag1=~flag1;if(flag1==0) //清除标志位{flag=0;write_com(0x80+0x40);write_date(' '); //清除打铃时间间隔标志位write_date(' ');write_com(0xc0);write_ds(1,miao); //储存间隔时间write_ds(3,fen);write_ds(5,shi);}/***********************/flag_paobiao=~flag_paobiao;miao_pb=0; //先把跑表值都赋为0 fen_pb=0;tt=0;while(!s2);if(flag_paobiao==1){init_paobiao();}/************************************/break;case 3:flag_paobiao=~flag_paobiao;if(flag_paobiao==0){write_com(0x80+0x40);write_date(' ');write_date(' ');}/************************************/flag2=~flag2;if(flag2==1){miao=miaonz1; //把闹铃值赋给时间值用来调整闹铃fen=fennz1;shi=shinz1;write_com(0x80+0x40);write_date('N');write_date('Z');write_date('1');write_com(0x80+0x40+3);display(0x40+4,shinz1);display(0x40+7,fennz1);display(0x40+10,miaonz1);}break;/************************************/case 4:flag2=~flag2;if(flag2==0){miaonz1=miao; //把调整好的时间值赋回给闹铃值(保存闹铃值)fennz1=fen;shinz1=shi;flag=0;write_com(0x80+0x40);write_date(' ');write_date(' ');write_date(' ');}/***********************************/ flag21=~flag21;if(flag21==1){miao=miaonz2;fen=fennz2;shi=shinz2;write_com(0x80+0x40);write_date('N');write_date('Z');write_date('2');write_com(0x80+0x40+3);display(0x40+4,shinz2);display(0x40+7,fennz2);display(0x40+10,miaonz2);delay(5);}break;/************************************/ case 5:flag21=~flag21;if(flag21==0){miaonz2=miao;fennz2=fen;shinz2=shi;flag=0;write_com(0x80+0x40);write_date(' ');write_date(' ');write_date(' ');}/***********温湿度*************/flag22=~flag22;if(flag22==1){write_com(0x80);write_date('W');write_date(':');write_date(' ');write_date(' ');write_date('.');write_date(' ');write_date(' ');write_date(' ');write_date('S');write_date(':');write_date(' ');write_date(' ');write_date('.');tempval=measure_T();humival=measure_H();if(error==0){delayms(500);dis_tempval=c_T(tempval);disply_T(dis_tempval);dis_humival=c_H(dis_tempval,humival);disply_H(dis_humival);}}break;/******************************************/ case 6:flag22=~flag22;if(flag22==0){write_com(0x80);write_date(' ');write_date('2');write_date('0');write_date(' ');write_date(' ');write_date('-');write_date(' ');write_date(' ');write_date('-');write_date(' ');write_date(' ');write_date(' ');write_date(' ');write_date(' ');write_date(' ');}flag23=~flag23;if(flag23==1){write_com(0x80);write_date('U');write_date(':');write_date(' ');write_date('.');write_date(' ');write_date(' ');write_date('V');write_date(' ');write_date('I');write_date(':');write_date(' ');write_date('.');write_date(' ');write_date('A');write_date(' ');adval=ReadADC() ; //读取AD值disply_Y(adval); //电压值显示delay(30); //AD_val=255-adval; //disply_L(AD_val); //电压值显示delay(30);}break;case 7:flag23=~flag23;if(flag23==0){write_com(0x80);write_date(' ');write_date('2');write_date('0');write_date(' ');write_date(' ');write_date('-');write_date(' ');write_date(' ');write_date('-');write_date(' ');write_date(' ');write_date(' ');write_date(' ');write_date(' ');write_date(' ');write_date(' ');}break;case 8:s4num=0;break;}}}/************************************/if(flag_paobiao==1){if(s2==0){delay(5);if(s2==0)while(!s2);{TR0=~TR0;}}display_paobiao();}}void shijian(){uchar miaoy;year=read_ds(9);month=read_ds(8);day=read_ds(7);week=read_ds(6);shi=read_ds(4);fen=read_ds(2);miaoy=miao; //把当前秒赋给miaoy用以判断秒是否变化miao=read_ds(0);if(flag3==0){a=read_ds(1);b=read_ds(3);c=read_ds(5);flag3=1;}if(a!=0||b!=0||c!=0){if(miaoy!=miao) //判断秒是否进位如果进位把时间间隔{a--;if(a<=0){b--;a=60;if(b<=0){c--;if(c<=0)flag_naozhong=1;flag3=0;}}}}if(shi==shinz1&&fen==fennz1&&miao==miaonz1) {flag_nz1=1;}if(shi==shinz2&&fen==fennz2&&miao==miaonz2) {flag_nz2=1;}display(0x40+10,miao);display(0x40+7,fen);display(0x40+4,shi);displayweek(week);display(3,year);display(6,month);display(9,day);}void main(){init();while(1){keyscan();keyscan1();if(flag_naozhong==1){di_1();flag_naozhong=0;}if(flag_nz1==1){ls=0;}if(flag_nz2==1){beep=0;}if(key==0){ls=1;beep=1;flag_nz1=0;flag_nz2=0;}read_alarm();if(ashi!=0||afen!=0||amiao!=0) {write_com(0x80+0x40+15);write_date('#');}else{write_com(0x80+0x40+15);write_date(' ');}if(shinz1!=0||fennz1!=0||miaonz1!=0||miaonz2!=0||fennz2!=0||s hinz2!=0){write_com(0x80+0x40+14);write_date('*');}else{write_com(0x80+0x40+14);write_date(' ');}if(flag==0&&flag1==0&&flag_paobiao==0&&flag2==0&&flag21==0&&flag22==0&&flag23==0) {shijian();baoshi();}}}。

单片机综合时钟设计

单片机综合时钟设计

单片机综合时钟设计单片机综合时钟设计内容(1)我运用一款DS12C887芯片加上一个51单片机设计了一个综合时钟,此时钟的优点是具有单片机掉电情况下也能走,因为DS12C887芯片内置锂电池,可以自己走时间10年之久,单片机的作用只是读取DS12C887芯片里的寄存器内容。

(2)我又通过编程设计了一个单片机闹钟,并且还具有响铃功能,可以放出音乐。

(3)最后我又编了一个秒表,充分运用了单片机,做到功能最大化,但由于时间仓促秒表性能上做的不是很好。

硬件芯片介绍时钟DS12C887芯片其引脚分布如下MOT:接低电平,选择INTEL总线时序。

AD0~AD7:地址/地址数据复用总线脚。

DS:数据选择或读输入引脚。

该引脚有两种工作模式,选用Intel工作模式时,该引脚是读使能输入引脚,即Read Enable。

R/W:读/写输入引脚。

该引脚也有两种工作模式,选用Intel模式时,该引脚可作为写使能输入,即Write Enable。

IRQ:中断申请输出脚,低电平有效。

芯片有128字节寄存器,地址0x00~0x09共十个寄存器,分别存放秒,秒闹钟,分,分闹钟,时,时闹钟,星期,日,月,年。

LCD双行显示屏RW:显示的设置RS:光标设置EE:清屏设置高电平有效程序流程图主程序按键程序PROTUES电路图程序展示主函数:#include <reg51.h>#include <intrins.h>#include "char_lcd.h"#include "lcd_display.h"#include "key.h"uchar xdata *ds_addr=0x0000; void main(void){*(ds_addr+10)=0x20;*(ds_addr+11)=0x22;lcd_init();date_init();while(1){data_pro();data_hl();key();naozhong();naozhongon();watchon();}}LCD设置函数:#include <reg51.h>#include <intrins.h>#include "char_lcd.h"void lcd_init(){lcd_wcmd(0x38);delay(1);lcd_wcmd(0x0c);delay(1);lcd_wcmd(0x06);delay(1);lcd_wcmd(0x01);}{bit busy;rs=0;rw=1;ep=1;_nop_();_nop_();_nop_();_nop_();busy=(bit)(P1&0x80);ep=0;return busy;}void lcd_wcmd(unsigned char cmd) {while(lcd_bz());rs=0;rw=0;ep=0;_nop_();_nop_();P1=cmd;_nop_();_nop_();_nop_();_nop_();ep=1;_nop_();_nop_();_nop_();_nop_();ep=0;}// void lcd_pos(unsigned char pos) void lcd_pos(unsigned char pos) {lcd_wcmd(pos|0x80);}void lcd_wdat(unsigned char dat) {rs=1;rw=0;ep=0;_nop_();_nop_();ep=1;_nop_();_nop_();ep=0;_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}void delay(uchar ms){uchar i;while(ms--){for(i=0; i<250; i++){_nop_();_nop_();_nop_();_nop_();}}}LCD设置函数头文件:#ifndef __char_lcd_h__#define __char_lcd_h__#define uchar unsigned char#define uint unsigned intsbit rs=P2^2;sbit rw=P2^1;sbit ep=P2^0;extern void lcd_init(void);extern bit lcd_bz(void);extern void lcd_wcmd(uchar cmd); extern void lcd_wdat(uchar dat); extern void lcd_pos(uchar pos); extern void delay(uchar ms);#endifLCD显示函数:#include <reg51.h>#include "lcd_display.h"#include "char_lcd.h"uchar code dis4[] = {"0123456789"};uchar code initdisp[] = {"Date:2000-00-00 Time:00:00:00"}; uchar code DT_lcdplace[] = {0x07,0x0a,0x0d,0x45,0x48,0x4b}; uchar code DTdata_addr[] = {9,8,7,4,2,0};uchar DTdata_tab[] = {0,0,0,0,0,0};uchar code chars[8][6] = {{"set "},{" "},{" year "},{" month"},{" day "},{" hour "},{"minute"},{"second"}}; uchar data_h,data_l;void data_wr(){uchar i;for(i=5; i>=0; i--){*(ds_addr+(DTdata_addr[i]))=DTdata_tab[i];}}void data_pro(){uchar i;for(i=0; i<6; i++){DTdata_tab[i]=*(ds_addr+DTdata_addr[i]);}data_hl();}void data_hl(){uchar i;for(i=0; i<6; i++){if(i==3){if((DTdata_tab[i]&0x80)!=0){DTdata_tab[i]=(DTdata_tab[i]&0x7f)&0x7f;if((DTdata_tab[i]&0x08)!=0)DTdata_tab[i]=DTdata_tab[i]+0x18;elseDTdata_tab[i]=DTdata_tab[i]+0x12;}}data_h=DTdata_tab[i]/16;data_l=DTdata_tab[i]%16;lcd_pos(DT_lcdplace[i]);lcd_wdat(data_h+48); //'0'=48lcd_wdat(data_l+48); //'0'=48}}void date_init(void) //diaplay date:{uchar i;lcd_pos(0x00);for(i=0; i<15; i++){lcd_wdat(initdisp[i]);}lcd_pos(0x40);for(i=16; i<29; i++){lcd_wdat(initdisp[i]);}}LCD显示函数头文件:#ifndef _lcd_display_h#define _lcd_display_h#define uchar unsigned char#define uint unsigned intextern uchar code dis4[];extern uchar code initdisp[];extern uchar code DT_place[];extern uchar code DT_lcdplace[];extern uchar code DTdata_addr[];extern uchar DTdata_tab[];extern uchar code chars[8][6];extern uchar data_h,data_l;extern uchar xdata *ds_addr;按键函数:#include <reg51.h>#include <intrins.h>#include "key.h"#include "char_lcd.h"#include "lcd_display.h"void key(void){uchar keyval=0;bit keyflag=0;if(keyset==0){delay(10);if(keyset==0){while(keyset==0);lcd_wcmd(0x0e);while(keyval!=6){lcd_pos(DT_lcdplace[keyval]);if(keyset==0){delay(10);if(keyset==0){keyval++;while(keyset==0);}}if(keyadd==0){delay(10);if(keyadd==0){keyflag=1;DTdata_tab[keyval]++;if((DTdata_tab[keyval]&0x0f)==0x0a){DTdata_tab[keyval]=DTdata_tab[keyval]+6;}while(keyadd==0);}}if(keysub==0){delay(10);if(keysub==0){keyflag=1;DTdata_tab[keyval]--;if((DTdata_tab[keyval]&0x0f)==0x0f){DTdata_tab[keyval]=DTdata_tab[keyval]-6;}while(keysub==0);}}if(keyflag==1){keyflag=0;datapro();*(ds_addr+0)=DTdata_tab[5]; //write modified data*(ds_addr+2)=DTdata_tab[4];*(ds_addr+4)=DTdata_tab[3];*(ds_addr+7)=DTdata_tab[2];*(ds_addr+8)=DTdata_tab[1];*(ds_addr+9)=DTdata_tab[0];data_hl();}}lcd_wcmd(0x0c);}}}void datapro(void) //modify year¡¢month¡¢day¡¢hour¡¢minute¡¢second data {if(DTdata_tab[5]==0x60) //modify second data{DTdata_tab[5]=0x00;}if(DTdata_tab[5]==0xf9){DTdata_tab[5]=0x59;}if(DTdata_tab[4]==0x60) //modify minute data{DTdata_tab[4]=0x00;}if(DTdata_tab[4]==0xf9){DTdata_tab[4]=0x59;}if(DTdata_tab[3]==0x12) //modify hour data{DTdata_tab[3]=0x80;}if(DTdata_tab[3]==0xf9){DTdata_tab[3]=0x91;}if(DTdata_tab[3]==0x24) //modify hour data{DTdata_tab[3]=0x00;}if(DTdata_tab[3]==0x23) //modify hour data{DTdata_tab[3]=0x91;}if(DTdata_tab[3]==0x22) //modify hour data {DTdata_tab[3]=0x90;}if(DTdata_tab[3]==0x21) //modify hour data {DTdata_tab[3]=0x89;}if(DTdata_tab[3]==0x20) //modify hour data {DTdata_tab[3]=0x88;}if(DTdata_tab[3]==0x19) //modify hour data {DTdata_tab[3]=0x87;}if(DTdata_tab[3]==0x18) //modify hour data {DTdata_tab[3]=0x86;}if(DTdata_tab[3]==0x17) //modify hour data {DTdata_tab[3]=0x85;}if(DTdata_tab[3]==0x16) //modify hour data {DTdata_tab[3]=0x84;}if(DTdata_tab[3]==0x15) //modify hour data {DTdata_tab[3]=0x83;}if(DTdata_tab[3]==0x14) //modify hour data {DTdata_tab[3]=0x82;}if(DTdata_tab[3]==0x13) //modify hour data {DTdata_tab[3]=0x81;}if(DTdata_tab[2]==0x32) //modify day data{DTdata_tab[2]=0x01;}if(DTdata_tab[2]==0x00){DTdata_tab[2]=0x31;}if(DTdata_tab[1]==0x13) //modify month data {DTdata_tab[1]=0x01;}if(DTdata_tab[1]==0x00){DTdata_tab[1]=0x12;}if(DTdata_tab[0]==0xa0) //modify year data{DTdata_tab[0]=0x00;}if(DTdata_tab[0]==0xf9){DTdata_tab[0]=0x99;}}void naozhong(void){uchar keyval=3;bit keyflag=0;if(keyalarm==0){delay(10);if(keyalarm==0){while(keyalarm==0);lcd_wcmd(0x0e);while(keyval!=6){lcd_pos(DT_lcdplace[keyval]);if(keyalarm==0){delay(10);if(keyalarm==0){keyval++;while(keyalarm==0);}}if(keyadd==0){delay(10);if(keyadd==0){keyflag=1;DTdata_tab[keyval]++;if((DTdata_tab[keyval]&0x0f)==0x0a){DTdata_tab[keyval]=DTdata_tab[keyval]+6;}while(keyadd==0);}}if(keysub==0){delay(10);if(keysub==0){keyflag=1;DTdata_tab[keyval]--;if((DTdata_tab[keyval]&0x0f)==0x0f){DTdata_tab[keyval]=DTdata_tab[keyval]-6;}while(keysub==0);}}if(keyflag==1){keyflag=0;datapro();*(ds_addr+1)=DTdata_tab[5]; //write modified data*(ds_addr+3)=DTdata_tab[4];*(ds_addr+5)=DTdata_tab[3];data_hl();}}lcd_wcmd(0x0c);}}}void naozhongon(void){if(keyon==1){delay(10);if(keyon==1){stop();}}if(keyon==0){delay(10);if(keyon==0){music();}}}unsigned int number;#define l_dao 262#define l_re 286#define l_mi 311#define l_fa 349#define l_sao 392#define l_la 440#define l_xi 494#define dao 523#define re 587#define mi 659#define fa 698#define sao 784#define la 880#define xi 987#define h_dao 1046#define h_re 1174#define h_mi 1318#define h_fa 1396#define h_sao 1567#define h_la 1760#define h_xi 1975void delay1(void){unsigned char i,j;for(i = 0;i < 250;i++){for(j = 0;j < 250;j++);}}//void music(void){unsigned char i,j;unsigned int code music[]={re,mi,re,dao,l_la,dao,l_la,l_sao,l_mi,l_sao,l_la,dao,l_la,dao,sao,la,mi,sao,re,mi,re,mi,sao,mi,l_sao,l_mi,l_sao,l_la,dao,l_la,l_la,dao,l_la,l_sao,l_re,l_mi, l_sao,re,re,sao,la,sao,fa,mi,sao,mi,la,sao,mi,re,mi,l_la,dao,re,mi,re,mi,sao,mi,l_sao,l_mi,l_sao,l_la,dao,l_la,dao,re,l_la,dao,re,mi,re,l_la,dao,re,l_la,dao,re,mi,re,0xff};unsigned char code musicJP[ ]={4,1,1,4,1,1,2,2,2,2,2,8,4,2,3,1,2,2,10,4,2,2,4,4,2,2,2,2,4,2,2,2,2,2,2,2, 10,4,4,4,2,2,4,2,4,4,4,2,2,2,2,2,2,10,4,2,2,4,4,2,2,2,2,6,4,2,2,4,1,1,4,10,4,2,2,4,1,1,4,10};EA = 1;ET0 = 1;TMOD = 0x00;i = 0;while(music[i]!=0xff){number = 460830 / music[i];TH0 = (8192-number) / 32;TL0 = (8192-number) % 32;TR0 = 1;for(j = 0;j < musicJP[i];j++)delay1();TR0 = 0;i++;if(keyoff==0){delay(10);if(keyoff==0){*(ds_addr+12)=0x00;break;while(keyoff==0);}}data_pro();data_hl();}}void Time0(void ) interrupt 1 using 1{sound=!sound;TH0=(8192-number)/32;TL0=(8192-number)%32;}void stop(void){sound=0;}按键函数头文件:#ifndef __key_h__#define __key_h__#define uchar unsigned char#define uint unsigned intsbit keyset=P3^2;sbit keyadd=P3^1;sbit keysub=P3^0;sbit keyalarm=P3^3;sbit keyoff=P3^5;sbit keyon=P2^6;sbit sound=P3^4;extern uchar code dis4[];extern uchar code initdisp[];extern uchar code DT_place[];extern uchar code DT_lcdplace[];extern uchar code DTdata_addr[];extern uchar DTdata_tab[];extern uchar xdata *ds_addr;extern void datapro(void);extern void key(void);extern void naozhong(void);extern void naozhongon(void);extern void music(void);extern void stop(void);extern void watch(void) ;extern void settime(void) ;extern void watchon(void);#endif秒表程序:#include <reg51.h>#include <intrins.h>#include "char_lcd.h"#include "lcd_display.h"#include "watch.h"uchar code table0[]={0x07,0x0a,0x0d,0x45,0x48,0x4b};uchar code table1[]={0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99}; unsigned int second10,second1,second2;bit bdata flag;void watchon(void){if(sta_star==0){delay(10);if(sta_star==0){watch();}}}void delay2(){unsigned char i,j;for(i=45;i>0;i--)for(j=200;j>0;j--);}void settime(){second10++;if(second10==10){second10=0;second1++;if(second1==10){second1=0;second2++;if(second2==6)second2=0;}}}void dispact(){uchar data_h,data_l,data_s,data_0;data_0=0x00/16;data_s=table1[second10]/16;data_h=table1[second2]%16;data_l=table1[second1]/16;lcd_pos(table0[4]);lcd_wdat(data_h+48);delay2();lcd_wdat(data_l+48);lcd_pos(table0[5]);delay2();lcd_wdat(data_s+48);lcd_wdat(data_0+48);lcd_pos(table0[3]);lcd_wdat(data_0+48);lcd_wdat(data_0+48);}Time1 () interrupt 3{TH1=(65535-53172)/256;TL1=(65535-53172)%256;if(flag)settime();dispact();}void watch(void){TH1=(65535-53172)/256; TL1=(65535-53172)%256; flag=0;EA=1;TR1=1;ET1=1;do{if(!sta_end){if(flag==0)flag=1;else flag=0;}if(!reset){flag=0;second10=0;second1=0;second2=0;EA=0;TR1=0;ET1=0;break;}}while(1);}秒表程序头文件:#ifndef __watch_h__#define __watch_h__#define uchar unsigned char #define uint unsigned int sbit sta_end=P2^4;sbit reset=P2^5;sbit sta_star=P2^3;extern uchar code table0[];extern void watch(void) ; #endif。

基于52单片机和DS12C887的高精度多功能电子钟

基于52单片机和DS12C887的高精度多功能电子钟

基于52单片机和DS12C887的高精度多功能电子钟设计基于DS12C887高精度时钟的意义DS12C887时钟芯片能够自动显示年、月、日、时、分、秒等时间信息,同时还具有校时,报时,闹钟等功能。

DS12C887也可以很方便的由软件编程进行功能的调整或增加。

所以设计基于DS12C877时钟芯片的高精度时钟的设计具有十分重要的现实意义和实用价值。

设计方案在传统的基于单片机的数字时钟设计的基础上经过一些改进,引入DS12C887时间芯片,本次设计可分为两部分:硬件部分包括:体积小功能丰富的STC89C52单片机、具有掉电保护的DS12C887时钟芯片电路简单易于实现的1602LCD液晶显示器,键盘输入电路等。

具体说来,系统智能控制部分由单片机及其相关的外围电路组成,外围电路包括解决死机等问题的复位电路、波形稳定的晶振电路、键盘设计、闹铃电路以及合适的直流电源电路。

利用单片机将复位电路、能够降低功耗和减少显示器外部引线的显示电路、电源电路等正确的连接在一起,并通过单片机的编程来实现本次设计任务中的要求。

软件部分主要包括了主程序模块,DS12C887模块,LCD1602模块,键盘控制模块。

DS12C887芯片具有掉电保护功能,内部自带锂电池,能够在断电的情况下保持时间信息,等到外部电路恢复供电之后能够不必调整时间,为时钟的校时操作节省了很多时间,而且这种设计更节能,在需要观察时间的时候比如白天就可以给主电路通电。

而在夜晚不需要观察时钟的时候就可以给主电路断电,这样可以节约大量电能。

时间芯片DS12C887采用了内部集成晶振的电路,并且具有内部温漂补偿电路设计。

能够准确计时,提供精确的时间,这样就简化了电路的器件选择,另外也使程序的设计更加简洁。

在硬件设计方面,由于只增加了一个DS12C887时间芯片,因此并不是特别复杂,而且这种独立计时的设计使得产品排故更加方便。

设计过程详解一、系统组成1、系统原理与硬件设计本次的设计题目是电子万年历设计,要求实现年、月、日、时、分、秒的正常显示,需要硬件和软件的结合来实现。

时钟芯片ds12c887的程序

时钟芯片ds12c887的程序

日历时钟DS12887或146818的C语言源程序#include <reg52.h>#include <stdio.h>#include <absacc.h>#include <math.h>#include <string.h>#include <ctype.h>#include <stdlib.h>#define uchar unsigned char#define uint unsigned int#define P128870 XBYTE[0xa000]#define P128871 XBYTE[0xa001]#define P128872 XBYTE[0xa002]#define P128873 XBYTE[0xa003]#define P128874 XBYTE[0xa004]#define P128875 XBYTE[0xa005]#define P128876 XBYTE[0xa006]#define P128877 XBYTE[0xa007]#define P128878 XBYTE[0xa008]#define P128879 XBYTE[0xa009]#define P12887a XBYTE[0xa00a]#define P12887b XBYTE[0xa00b]#define P12887c XBYTE[0xa00c]#define P12887d XBYTE[0xa00d]#define P12887e XBYTE[0xa00e]#define P12887f XBYTE[0xa00f]void setup12887(uchar *p);void read12887(uchar *p);void start12887(void);void setup12887(uchar *p) //设置系统时间{uchar i;i=P12887d;P12887a=0x70; P12887b=0xa2; P128870=*p++; P128871=0xff; P128872=*p++; P128873=0xff; P128874=*p++; P128875=0xff; P128876=*p++; P128877=*p++; P128878=*p++; P128879=*p++; P12887b=0x22; P12887a=0x20;i=P12887c;}void read12887(uchar *p) //读取系统时间{uchar a;do{ a=P12887a; } while((a&0x80)==0x80);*p++=P128870; *p++=P128872; *p++=P128874; *p++=P128876;*p++=P128877; *p++=P128878; *p++=P128879;}void start12887(void) //启动时钟{uchar i;i=P12887d;P12887a=0x70; P12887b=0xa2; P128871=0xff; P128873=0xff; P128875=0xff; P12887b=0x22; P12887a=0x20;i=P12887c;}/*************************************************************文件名称:ds12c887.c适用范围:时钟芯片ds12c887的驱动程序*************************************************************/#include <absacc.h>/* 命令常量定义 */#define CMD_START_DS12C887 0x20 /* 开启时钟芯片*/#define CMD_START_OSCILLATOR 0x70 /* 开启振荡器,处于抑制状态 */#define CMD_CLOSE_DS12C887 0x30 /* 关掉时钟芯片*//* 所有的置位使用或操作,清除使用与操作 */#define MASK_SETB_SET 0x80 /* 禁止刷新 */#define MASK_CLR_SET 0x7f /* 使能刷新 */#define MASK_SETB_DM 0x04 /* 使用HEX格式*/#define MASK_CLR_DM 0xfb /* 使用BCD码格式 */#define MASK_SETB_2412 0x02 /* 使用24小时模式 */#define MASK_CLR_2412 0xfd /* 使用12小时模式 */#define MASK_SETB_DSE 0x01 /* 使用夏令时 */#define MASK_CLR_DSE 0xfe /* 不使用夏令时*//* 寄存器地址通道定义 */xdata char chSecondsChannel _at_ 0xdf00;xdata char chMinutesChannel _at_ 0xdf02;xdata char chHoursChannel _at_ 0xdf04;xdata char chDofWChannel _at_ 0xdf06;xdata char chDateChannel _at_ 0xdf07;xdata char chMonthChannel _at_ 0xdf08;xdata char chYearChannel _at_ 0xdf09;xdata char chCenturyChannel _at_ 0xdf32;xdata char chRegA _at_ 0xdf0a;xdata char chRegB _at_ 0xdf0b;xdata char chRegC _at_ 0xdf0c;xdata char chRegD _at_ 0xdf0d;/* 函数声明部分 */void StartDs12c887(void);void CloseDs12c887(void);void InitDs12c887(void);unsigned char GetSeconds(void);unsigned char GetMinutes(void);unsigned char GetHours(void);unsigned char GetDate(void);unsigned char GetMonth(void);unsigned char GetYear(void);unsigned char GetCentury(void);void SetTime(unsigned char chSeconds,unsigned char chMinutes,unsigned char chHours);void SetDate(unsigned char chDate,unsigned char chMonth,unsigned char chYear);/*************************************************************函数功能:该函数用来启动时钟芯片工作应用范围:仅在时钟芯片首次使用时用到一次入口参数:出口参数:*************************************************************/void StartDs12c887(void){chRegA = CMD_START_DS12C887;}/*************************************************************函数功能:该函数用来关闭时钟芯片应用范围:一般用不到入口参数:出口参数:*************************************************************/void CloseDs12c887(void){chRegA = CMD_CLOSE_DS12C887;}void InitDs12c887(){StartDs12c887();chRegB = chRegB | MASK_SETB_SET; /* 禁止刷新 */chRegB = chRegB & MASK_CLR_DM | MASK_SETB_2412 \& MASK_CLR_DSE;/* 使用BCD码格式、24小时模式、不使用夏令时 */chCenturyChannel = 0x21; /* 设置为21世纪 */chRegB = chRegB & MASK_CLR_SET; /* 使能刷新 */}/************************************************************* 函数功能:该函数用来从时钟芯片读取秒字节应用范围:入口参数:出口参数:*************************************************************/ unsigned char GetSeconds(void){return(chSecondsChannel);}/************************************************************* 函数功能:该函数用来从时钟芯片读取分字节应用范围:入口参数:出口参数:*************************************************************/ unsigned char GetMinutes(void){return(chMinutesChannel);}/************************************************************* 函数功能:该函数用来从时钟芯片读取小时字节应用范围:出口参数:*************************************************************/ unsigned char GetHours(void){return(chHoursChannel);}/************************************************************* 函数功能:该函数用来从时钟芯片读取日字节应用范围:入口参数:出口参数:*************************************************************/ unsigned char GetDate(void){return(chDateChannel);}/************************************************************* 函数功能:该函数用来从时钟芯片读取月字节应用范围:入口参数:出口参数:*************************************************************/ unsigned char GetMonth(void){return(chMonthChannel);}/************************************************************* 函数功能:该函数用来从时钟芯片读取年字节应用范围:入口参数:出口参数:*************************************************************/ unsigned char GetYear(void){return(chYearChannel);}/************************************************************* 函数功能:该函数用来从时钟芯片读取世纪字节应用范围:入口参数:*************************************************************/unsigned char GetCentury(void){return(chCenturyChannel);}/*************************************************************函数功能:该函数用来设置时钟芯片的时间应用范围:入口参数:chSeconds、chMinutes、chHours是设定时间的压缩BCD码出口参数:*************************************************************/void SetTime(unsigned char chSeconds,unsigned char chMinutes,unsigned char chHours){chRegB = chRegB | MASK_SETB_SET; /* 禁止刷新 */chSecondsChannel = chSeconds;chMinutesChannel = chMinutes;chHoursChannel = chHours;chRegB = chRegB & MASK_CLR_SET; /* 使能刷新 */}/*************************************************************函数功能:该函数用来设置时钟芯片的日期应用范围:入口参数:chDate、chMonth、chYear是设定日期的压缩BCD码出口参数:*************************************************************/void SetDate(unsigned char chDate,unsigned char chMonth,unsigned char chYear) {chRegB = chRegB | MASK_SETB_SET; /* 禁止刷新 */chDateChannel = chDate;chMonthChannel = chMonth;chYearChannel = chYear;chRegB = chRegB & MASK_CLR_SET; /* 使能刷新 */}。

基于DS12C887的单片机实时时钟设计

基于DS12C887的单片机实时时钟设计
17 DS/RD:数据选择或读输入脚,该引脚有两种工作模式,当MOT接VCC 时,选用Motorola工作模式,在这种工作模式中,每个总线周期的后一部分的DS为高电平,被称为数据选通,在读操作中,DS的上升沿使DS12C887将内部数据送往总线AD0~AD7上,以供外部读取,在写操作中,DS的下降沿将使总线AD0~AD7上的数据锁 存在DS12C887中;当MOT接GND时,选用Intel工作模式,在该模式中,该引脚是读允许输入脚,即Read Enable。
13 C——S—— :片选输入,低电平有效。
19 I——R——Q——:中断请求输入,低电平有效,该脚有效对DS12C887内的时钟、日历和RAM中的内容没有任何影响,仅对内部的控制寄存器有影响,在典型的应用中,RESET可以直接接VCC,这样可以保证DS12C887在掉电时,其内部控制寄存器不受影响。
18 RESET(复位输出):当该脚保持低电平时间大于200ms,保证DS12887有效复位。
4.实时时钟设计
本系统由硬件和软件两部分组成:
(1)硬件电路
图4-1硬件连接图
本系统采用的单片机是AT89S52单片机,它是一种带8K字节内嵌可编程闪存的低功耗高性能的八位微控制器,具有看门狗定时器、双数据指针、3个16位定时计数器、6个两级中断源结构以及掉电模式下的自动保存功能,而且价格便宜。显示模块用1602LCD,通过它实时显示DS12C887内部时间,DS12C887与单片机的典型连接如图2所示,DS12887的ADO~AD7引脚分别与AT89S52单片机的AD0~AD7相连, DS12887采用地址总线与数据总线复用方式,LCD1602接AT89S52单片机的DB0~DB7;MOT引脚接地,即DS12887选择INTEL时序。DS12887的片选引脚CS单片机AT89S52的12脚,DS1288的I——R——Q—— 引脚连于AT89S52的外部中断INT0即33引脚上,所以我们可通过编程利用中断源向CPU申请中断,每当符合中源中断条件时,I——R——Q—— 输出低电平,引起AT89S52的INTO中断。如果我们设置好内部闹钟寄存器的初值,则当当前时间与我们设置的闹铃时间匹配时,中断申请标志位IRQF置为1,由I——R——Q——向AT89S52提出中断,系统响应中断,以达到闹钟定时的目的。

单片机DS12C887时钟设计

单片机DS12C887时钟设计

目录摘要 (2)1 系统总体设计 (2)1.1 系统设计的主要内容和具体要求 (2)1.1.1主要内容: (2)1.1.2 具体技术要求: (2)1.2 方案论证 (2)2 系统硬件电路设计 (3)2.1单片机控制系统包括STC89C52单片机以及它的外围电路(晶振电路和复位电路)。

(3)2.1.1晶振电路 (4)2.1.2 复位电路 (4)2.2 DS12C887时钟电路 (5)2.2.1 器件介绍 (5)2.2.2 DS12C887与单片机的连接 (6)2.3 1602液晶显示屏 (6)2.4 USB供电电路 (7)2.5 键盘电路 (8)2.6闹铃电路 (9)3 系统软件程序设计 (9)3.1 主程序运行说明及流程图 (9)3.2 DS12C887使用说明及流程图 (11)3.3 1602操作说明及流程图 (11)3.4 键盘控制说明及流程图 (12)4 系统调试 (13)5 结论 (14)6 谢辞 (14)7 参考文献 (15)8 附录A:实时日历电子钟设计电路原理图 (15)9 附录B:实时日历电子钟设计程序代码 (15)摘要在日新月异的21世纪里,家用电子产品得到了迅速发展。

许多家电设备都趋于人性化、智能化,这些电器设备大部分都含有CPU控制器或者是单片机。

单片机以其高可靠性、高性价比、低电压、低功耗等一系列优点,近几年得到迅猛发展和大范围推广,广泛应用于工业控制系统、通讯设备、日常消费类产品和玩具等。

本文设计的电子万年历属于小型智能家用电子产品。

利用单片机进行控制,实时时钟芯片DS12C887时钟芯片进行记时及掉电存储,外加键盘电路和显示电路,可实现时间的调整和显示。

电子万年历既可广泛应用于家庭,也可应用于银行、邮电、宾馆、医院、学校、企业、商店等相关行业的大厅,以及单位会议室、门卫等场所。

因而,此设计具有相当重要的现实意义和实用价值。

关键词:单片机;DS12C887;智能1 系统总体设计1.1 系统设计的主要内容和具体要求1.1.1主要内容:本次设计的题目是基于ds12c887的高精度时钟的设计,可以正常的显示年、月、日、星期、时、分、秒。

(51单片机)DS12CR887液晶时钟

(51单片机)DS12CR887液晶时钟

//将DS12CR887的时间读入液晶显示屏;键盘调控时间;闹钟功能(按任意键退出);#include <reg52.h>#include <define.h>//见下void init(){TMOD=1;TH0=0x7f;TL0=0xff;EA=1;ET0=1; //init timerwrite_ds(0x0a,0x20);write_ds(0x0b,0x26); //init DS12CR887write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x80+0x01);write_data('2');write_data('0');write_com(0x14);write_com(0x14);write_data('/');write_com(0x14);write_com(0x14);write_data('/');write_com(0x80+0x46);write_data(':');write_com(0x14);write_com(0x14);write_data(':'); //init LCD }void display(){uchar i;write_com(0x80+0x03);write_data(year/10+48);write_data(year%10+48);write_com(0x14);write_data(month/10+48);write_data(month%10+48);write_com(0x14);write_data(day/10+48);write_data(day%10+48);write_com(0x14);for(i=0;i<4;i++)write_data(week[w][i]);write_com(0x80+0x44);write_data(h/10+48);write_data(h%10+48);write_com(0x14);write_data(min/10+48);write_data(min%10+48);write_com(0x14);write_data(sec/10+48);write_data(sec%10+48);}void keyscan(){static char p=0;uchar t=0x3c&P3;if(t!=0x3c){delay(10);t=0x3c&P3;if(t!=0x3c){if(flag){didi=1;TR0=0;flag=0;}else{if(p==0&&t==0x1c) //S1进入设置{write_com(0x80+address[p]);write_com(0x0f);p++;while((0x3c&P3)!=0x3c);delay(10);while((0x3c&P3)!=0x3c);}else if(p!=0){switch(t){case 0x1c: //S1退出设置&切换调节内容switch(p){case 7:write_com(0x0c);while((0x3c&P3)!=0x3c);delay(10);while((0x3c&P3)!=0x3c);time_set();break;default:write_com(0x80+address[p]);while((0x3c&P3)!=0x3c);delay(10);while((0x3c&P3)!=0x3c);break;}if(p==7)p=0;elsep++;break;case 0x2c: //S2增大switch(p-1){case 0:year_up(); break;case 1:month_up(); break;case 2:day_up(); break;case 3:week_up();break;case 4:h_up();break;case 5:min_up(); break;case 6:sec_up();break;}display();write_com(0x80+address[p-1]);while((0x3c&P3)!=0x3c);delay(10);while((0x3c&P3)!=0x3c);break;case 0x34: //S3减小switch(p-1){case 0:year_down(); break;case 1:month_down(); break;case 2:day_down(); break;case 3:week_down();break;case 4:h_down();break;case 5:min_down(); break;case 6:sec_down();break;}display();write_com(0x80+address[p-1]);while((0x3c&P3)!=0x3c);delay(10);while((0x3c&P3)!=0x3c);break;}}}}}else if(t==0x3c&&p==0){sec=read_ds(0);min=read_ds(2);h=read_ds(4);w=read_ds(6)-1;day=read_ds(7);month=read_ds(8);year=read_ds(9);display();}}void alarm(uchar nian,uchar yue,uchar ri,uchar shi,uchar fen){if(nian==year&&yue==month&&ri==day&&shi==h&&fen==min&&sec==0) {TR0=1;flag=1;}}void main(){init();// time_set();// display();while(1){keyscan();alarm(16,8,12,19,31);}}void timer0() interrupt 1{TH0=0x7f;TL0=0xff;didi=~didi;}头文件<define.h>typedef unsigned char uchar; typedef unsigned int uint;char w=0;sbit didi=P3^6;sbit E=P0^5;sbit RW1=P0^6;sbit RS=P0^7;sbit CS=P2^0;sbit AS=P2^1;sbit RW2=P2^2;sbit DS=P2^3;//sbit BEEP=P3^6;//sbit IRQ=ucharweek[7][4]={"Sun.","Mon.","Tue.","Wed.","Thu.","Fri.","Sat."},address[]={0x04, 0x07,0x0a,0x0f,0x45,0x48,0x4b};uchar year,month,day,h,min,sec;char flag;void delay(uint time){uint x,y;for(x=time;x>0;x--)for(y=114;y>0;y--);}void write_com(uchar com){RS=0;RW1=0;P2=com;E=0;delay(5);E=1;delay(5);E=0;}void write_data(uchar dat){RS=1;RW1=0;P2=dat;E=0;delay(5);E=1;delay(5);E=0;}void write_ds(uchar add,uchar dat) {AS=1;DS=1;RW2=1;CS=0;P1=add;AS=0;RW2=0;P1=dat;RW2=1;CS=1;AS=1;}uchar read_ds(uchar add) {uchar dat;AS=1;DS=1;RW2=1;CS=0;P1=add;AS=0;DS=0;P1=0xff;dat=P1;DS=1;CS=1;AS=1;return dat;}void time_set(){write_ds(0,sec);write_ds(2,min);write_ds(4,h);write_ds(6,w+1);write_ds(7,day);write_ds(8,month);write_ds(9,year);}char year_judge(){if(year%400==0||(year%100!=0&&year%4==0))return 1;elsereturn 0;}char daymax(){switch(month){case 1: case 3: case 5: case 7: case 8: case 10: case 12:return 31;break;case 4: case 6: case 9: case 11:return 30;break;default:if(year_judge()) return 29;else return 28;}}void year_up(){year++;}void year_down(){year--;}void month_up(){month++;if(month==13)month=1; }void month_down(){month--;if(month==0)month=12; }void day_up(){day++;if(day==daymax()+1)day=1;}void day_down(){day--;if(day==0)day=daymax();}void week_up(){w++;if(w==7) w=0;}void week_down(){w--;if(w==-1) w=6;}void h_up(){h++;if(h==24)h=0;}void h_down(){h--;if(h==-1)h=23; }void min_up(){min++;if(min==60)min=0; }void min_down(){min--;if(min==-1)min=59; }void sec_up(){sec++;if(sec==60)sec=0; }void sec_down(){sec--;if(sec==-1)sec=59; }。

基于单片机的DS12C887的日历时钟显示系统设计论文

基于单片机的DS12C887的日历时钟显示系统设计论文

摘要在51单片机应用系统中,常常需要记录实时的时间信息并长期保存。

比如,在数据采集时,对某些重要的信息不仅需要记录其内容,还需要记录下该事件发生的准确时间;在银行营业大厅中使用的利率或汇率显示屏,上面除了需要显示利率或汇率等数据以外,还需要显示实时的时间信息,如年、月、日、星期、时间等。

本文用51单片机以及DS12C887日历时钟芯片实现日历时钟的设计。

论文研究了DS12C887日历时钟芯片的相关功能,两片MAX7219分别与单片机连接实现13位数码管显示以及整个实时日历时钟显示系统的硬件,软件设计。

设计结果表明本文设计的基于DS12C887的实时日历时钟显示系统完全能够满足设计要求。

关键词:DS12C887;51单片机;MAX7219;数码管显示Abstract51 SCM application systems, often need to record real-time information and long-term preservation. For example, when data collection for some important information not only need to record the content, but also record the exact time of the incident; the banking hall in the use of interest rate or exchange rate display, shown above in addition to the interest rate or exchange rate such data, it also needs to show real-time information, such as year, month, date, day and time. In this paper, 51 MCU and the calendar clock chip DS12C887 calendar clock design.Thesis of the calendar clock chip DS12C887-related functions, MAX7219 connected respectively to achieve 13-bit single chip digital display and the real time calendar clock display system hardware and software design.Design results show that the DS12C887-based design of real-time calendar clock display system can completely meet the design requirements.Key Words:DS12C887;51 Microcontroller;MAX7219;Digital display1 绪论本次设计的功能是在51单片机系统中设置、获取、记录实时的日历时钟信息并通过数码管显示,要求能够进行长时间的记录,并且存储的时间信息在掉电情况下至少保存10年以上。

实时时钟DS12C887_C实例程序

实时时钟DS12C887_C实例程序

DS12C887实例程序#include<intrins.h>#define uchar unsigned char#define uint unsigned intuchar nian,yue,ri,day,shi,fen,miao,ashi,afen,sshi,sfen;uchar s1num,flag,flag1,flag2,flag3,flag4,settime,setalarm;/********************************************************************引脚配置定义 GND VCC VL RS R/W E D0 D1 D2 D3 D4 D5 D6 D7 BLA BLK*********************************************************************/#define LCDIO P1sbit LCD1602_RS=P3^5;sbit LCD1602_RW=P3^4;sbit LCD1602_EN=P3^3;sbit s1=P2^1;sbit s2=P2^2;sbit s3=P2^0;sbit s4=P2^3;/********************************************************************/ void LCD_delay(void);void delay_ms(unsigned int n);uchar change_bcd(uchar a);void LCD_en_command(unsigned char command);void LCD_en_dat(unsigned char temp);void LCD_set_xy( unsigned char x, unsigned char y );void LCD_write_string(unsigned char X,unsigned char Y,unsigned char *s); void LCD_init(void);void write_sfm(uchar,uchar);void setup_time();void setup_alarm();/******************** LCD PART *************************************/void LCD_delay(void){_nop_();_nop_();_nop_();}void delay_ms(uint z){uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}/********************************* *********************************/ uchar change_bcd(uchar a) //D0~D7转换程序{char temp,i;for(i=0;i<8;i++){temp<<=1;temp|=(a&0x01);a>>=1;}return(temp);}/********************************* *********************************/ void LCD_en_command(unsigned char command){command=change_bcd(command);command=_crol_(command,4);LCD1602_RS=0;LCD1602_EN=0;LCDIO&=0X0f;LCDIO|=(command & 0xf0);LCD1602_EN=1;LCD_delay();LCD1602_EN=0;LCDIO&=0X0f;LCDIO|=(command << 4) & 0xf0;LCD1602_EN=1;LCD_delay();LCD1602_EN=0;delay_ms(1);}void LCD_en_dat(unsigned char dat){dat=change_bcd(dat);dat=_crol_(dat,4);LCD1602_RS=1;LCD1602_EN=0;LCDIO&=0X0f;LCDIO|=(dat & 0xf0);LCD1602_EN=1;LCD_delay();LCD1602_EN=0;LCDIO&=0X0f;LCDIO|=(dat << 4) & 0xf0;LCD1602_EN=1;LCD_delay();LCD1602_EN=0;delay_ms(1);}/********************************************************************/ void LCD_set_xy( unsigned char x, unsigned char y ){unsigned char address;if (y ==0)address = 0x80 + x;elseaddress = 0xC0 + x;LCD_en_command(address);}/********************************************************************/ void LCD_write_string(unsigned char X,unsigned char Y,unsigned char *s) {LCD_set_xy( X, Y ); //set addresswhile (*s) // write character{LCD_en_dat(*s);s ++;}}/********************************************************************/ void LCD_init(void){LCD1602_RW=0;LCD_en_command(0x01);delay_ms(5);LCD_en_command(0x01);delay_ms(5);LCD_en_command(0x28);delay_ms(5);LCD_en_command(0x28);delay_ms(5);LCD_en_command(0x28);delay_ms(5);LCD_en_command(0x0C);delay_ms(5);LCD_en_command(0x80);delay_ms(5);LCD_en_command(0x01);delay_ms(5);}/********************************************************************/void write_sfm(uchar add,uchar date){uchar shi,ge;shi=date/10;ge=date%10;LCD_en_command(add);LCD_en_dat(shi+'0');LCD_en_dat(ge+'0');}/*****************************SET DAY & TIME***************************************/ void setup_time(){if(s1==0){delay_ms(5);if(s1==0){s1num++;TR0=0; //关定时器flag=1;flag1=1;flag3=1;flag4=1; //停止扫描DS12C887_read_time,setup_alarmwhile(!s1);if(s1num==1){LCD_en_command(0x82);LCD_en_command(0x0f);}}if(s1num==2){LCD_en_command(0x85);}if(s1num==3){LCD_en_command(0x88);}if(s1num==4){LCD_en_command(0x8b);}if(s1num==5){LCD_en_command(0xc0);}if(s1num==6){LCD_en_command(0xc3);}if(s1num==7){LCD_en_command(0xc6);}if(s1num==8){s1num=0;TR0=1; //开定时器flag1=0;flag3=0;flag4=0; //执行扫描setup_alarmsettime=1; //执行settimeLCD_en_command(0x0c);}}if(s1num!=0){/********************************************************************/ if(s2==0){delay_ms(2);if(s2==0){while(!s2);if(s1num==1){nian++;if(nian==100)miao=0;write_sfm(0x82,nian);LCD_en_command(0x82);}if(s1num==2){yue++;if(yue==13)yue=0;write_sfm(0x85,yue);LCD_en_command(0x85);}if(s1num==3){ri++;if(ri==32)ri=0;write_sfm(0x88,ri);LCD_en_command(0x88);}if(s1num==4){day++;if(day==8)day=1;write_sfm(0x8b,day);LCD_en_command(0x8b);}if(s1num==5){shi++;if(shi==24)shi=0;write_sfm(0xc0,shi);LCD_en_command(0xc0);}if(s1num==6){fen++;if(fen==60)fen=0;write_sfm(0xc3,fen);LCD_en_command(0xc3);}if(s1num==7){miao++;if(miao==60)miao=0;write_sfm(0xc6,miao);LCD_en_command(0xc6);}}}/********************************************************************/ if(s3==0){delay_ms(2);if(s3==0){while(!s3);if(s1num==1){nian--;if(nian==-1)nian=99;write_sfm(0x82,nian);LCD_en_command(0x82);}if(s1num==2){yue--;if(yue==0)yue=12;write_sfm(0x85,yue);LCD_en_command(0x85);}if(s1num==3){ri--;if(ri==0)ri=31;write_sfm(0x88,ri);LCD_en_command(0x88);}if(s1num==4){day--;if(day==0)day=7;write_sfm(0x8b,day);LCD_en_command(0x8b);}if(s1num==5){shi--;if(shi==-1)shi=23;write_sfm(0xc0,shi);LCD_en_command(0xc0);}if(s1num==6){fen--;if(fen==-1)fen=59;write_sfm(0xc3,fen);LCD_en_command(0xc3);}if(s1num==7){miao--;if(miao==-1)miao=59;write_sfm(0xc6,miao);LCD_en_command(0xc6);}}}/********************************************************************/ }}/********************************************************************//********************************************************************/void setup_alarm(){if(s4==0){delay_ms(5);if(s4==0){s1num++;TR0=0; //关定时器flag=1;flag2=1;flag3=1;flag4=1; //停止扫描DS12C887_read_time,setup_timewhile(!s4);if(s1num==1){LCD_en_command(0x01);LCD_write_string(0,0,"Start alarm at");write_sfm(0xcb,ashi);write_sfm(0xce,afen);LCD_write_string(0x0d,1,":");LCD_en_command(0xcb);LCD_en_command(0x0f);}}if(s1num==2){LCD_en_command(0xce);}if(s1num==3){LCD_en_command(0x01);LCD_write_string(0,0,"Stop alarm at");write_sfm(0xcb,sshi);write_sfm(0xce,sfen);LCD_write_string(0x0d,1,":");LCD_en_command(0xcb);LCD_en_command(0x0f);}if(s1num==4){LCD_en_command(0xce);}if(s1num==5){s1num=0;TR0=1; //开定时器flag2=0;flag3=0;flag4=0; //执行扫描setup_timesetalarm=1; //执行setalarmLCD_en_command(0x01); //清LCD屏幕LCD_write_string(0,0,"20 - -");LCD_write_string(2,1,": :");LCD_en_command(0x0c);}}if(s1num!=0){/********************************************************************/ if(s2==0){delay_ms(5);if(s2==0){while(!s2);if(s1num==1){ashi++;if(ashi==24)ashi=0;write_sfm(0xcb,ashi);LCD_en_command(0xcb);}if(s1num==2){afen++;if(afen==60)afen=0;write_sfm(0xce,afen);LCD_en_command(0xce);}if(s1num==3){sshi++;if(sshi==24)sshi=0;write_sfm(0xcb,sshi);LCD_en_command(0xcb);}if(s1num==4){sfen++;if(sfen==60)sfen=0;write_sfm(0xce,sfen);LCD_en_command(0xce);}}}/********************************************************************/ if(s3==0){delay_ms(5);if(s3==0){while(!s3);if(s1num==1){ashi--;if(ashi==-1)ashi=23;write_sfm(0xcb,ashi);LCD_en_command(0xcb);}if(s1num==2){afen--;if(afen==-1)afen=59;write_sfm(0xce,afen);LCD_en_command(0xce);}if(s1num==3){sshi--;if(sshi==-1)sshi=23;write_sfm(0xcb,sshi);LCD_en_command(0xcb);}if(s1num==4){sfen--;if(sfen==-1)sfen=59;write_sfm(0xce,sfen);LCD_en_command(0xce);}}}/********************************************************************/ }}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

#include<reg52.h>#define uchar unsigned char#define uint unsigned intuchar code table[]=" 2011-10-03 MON"; uchar code table1[]=" 00:00:00"; sbit lcden=P2^7;sbit lcdrs=P2^6;sbit lcdrw=P2^5;sbit dscs=P1^0;sbit dsas=P1^1;sbit dsrw=P1^2;sbit dsds=P1^3;sbit dsirq=P3^3;sbit s1=P3^0;sbit s2=P3^1;sbit s3=P3^2;sbit rd=P3^7;uchar num,nian,yue,ri,zhou,s1num,flag; char miao,fen,shi;void delay(uint z){uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void write_com(uchar com){lcdrs=0;P0=com;delay(5);lcden=1;delay(5);lcden=0;}void write_date(uchar date){lcdrs=1;P0=date;delay(5);lcden=1;delay(5);lcden=0;}void write_ds(uchar add,uchar date) {dscs=0;dsas=1;dsds=1;dsrw=1;P0=add;dsas=0;dsrw=0;P0=date;dsrw=1;dsas=1;dscs=1;}uchar read_ds(uchar add){uchar ds_date;dsas=1;dsds=1;dsrw=1;dscs=0;P0=add;dsas=0;dsds=0;P0=0xff;ds_date=P0;dsds=1;dsas=1;dscs=1;return ds_date;}void write_sfm(uchar add,uchar date) {uchar shi,ge;shi=date/10;ge=date%10;write_com(0x80+0x40+add);write_date(0x30+shi);write_date(0x30+ge);}void write_nyr(uchar add,uchar date) {uchar shi,ge;shi=date/10;ge=date%10;write_com(0x80+add);write_date(0x30+shi);write_date(0x30+ge);}/*void set_time(){write_ds(0,0);write_ds(1,0);write_ds(2,0);write_ds(3,0);write_ds(4,0);write_ds(5,0);write_ds(6,0);write_ds(7,0);write_ds(8,0);write_ds(9,0);} */void write_week(char date){write_com(0x80+13);switch(date){case 1: write_date('M');delay(5);write_date('O');delay(5);write_date('N');break;case 2: write_date('T');delay(5);write_date('U');delay(5);write_date('S');break;case 3: write_date('W');delay(5);write_date('E');delay(5);write_date('D');break;case 4: write_date('T');delay(5);write_date('H');delay(5);write_date('U');break;case 5: write_date('F');delay(5);write_date('R');delay(5);write_date('I');break;case 6: write_date('S');delay(5);write_date('A');delay(5);write_date('T');break;case 7: write_date('S');delay(5);write_date('U');delay(5);write_date('N');break;}}void set_time(){//write_ds(2,30);//write_ds(4,12);//write_ds(9,11);write_ds(8,10);write_ds(7,4);write_ds(6,2);}void keyscan(){rd=0;//s1=0;if(s1==0){delay(5);if(s1==0);{flag=1;s1num++;while(!s1);if(s1num==1){write_com(0x80+0x40+10);write_com(0x0f);} //delay(1000);}if(s1num==2){write_com(0x80+0x40+7);write_com(0x0f);//delay(1000);}if(s1num==3){write_com(0x80+0x40+4);write_com(0x0f);//delay(1000);}if(s1num==4){ flag=0;s1num=0;write_com(0x0c);}}if(s1num!=0){if(s2==0){delay(5);if(s2==0){while(!s2);if(s1num==1){miao++;if(miao==60)miao=0;write_sfm(10,miao);write_com(0x80+0x40+10);write_ds(0,miao);}if(s1num==2){fen++;if(fen==60)fen=0;write_sfm(7,fen);write_com(0x80+0x40+7);write_ds(2,fen);}{shi++;if(shi==24)shi=0;write_sfm(4,shi);write_com(0x80+0x40+4);write_ds(4,shi);}}}if(s3==0){delay(5);if(s3==0){while(!s3);if(s1num==1){/* if(miao==0){miao=59;write_sfm(10,miao);write_com(0x80+0x40+10);}*/miao--;if(miao==-1)miao=59;write_sfm(10,miao);write_com(0x80+0x40+10);write_ds(0,miao);}if(s1num==2){fen--;if(fen==-1)fen=59;write_sfm(7,fen);write_com(0x80+0x40+7);write_ds(2,fen);}if(s1num==3){shi--;shi=23;write_sfm(4,shi);write_com(0x80+0x40+4);write_ds(4,shi);}}}}}void init(){lcdrw=0;lcden=0;// write_ds(0x0A,0x20); //// write_ds(0x0B,0x26); //// set_time(); //这三句话为初始化DS12C887,首次使用时调用这三句话,此后不必调用set_time();write_com(0x38);write_com(0x0e);write_com(0x06);write_com(0x01);write_com(0x80);for(num=0;num<15;num++){write_date(table[num]);delay(5);}write_com(0x80+0x40);for(num=0;num<12;num++){write_date(table1[num]);delay(5);}// EA=1;// EX0=1;// IT0=1;}void main(){init();while(1){keyscan();if(flag==0){miao=read_ds(0);fen=read_ds(2);shi=read_ds(4);nian=read_ds(9);yue=read_ds(8);ri=read_ds(7);zhou=read_ds(6);write_sfm(10,miao);write_sfm(7,fen);write_sfm(4,shi);write_nyr(4,nian);write_nyr(7,yue);write_nyr(10,ri);write_week(zhou);}}}。

相关文档
最新文档