一.项目要求

**1、**在1602液晶上显示年、月、日、星期、时、分、秒,并且按秒实时更新显示。
**2、**具有闹铃设定及到时报警功能
**3、**能够使用板上的按键调节各个参数。
**4、**每次有键按下时,蜂鸣器都以短“滴”报警。

二.项目内容

(1)实验原理图
DS12C887引脚结构及其功能如下:

管脚名称

  • AD0-AD7——地址/数据复用总线
  • NC——空脚
  • MOT——总线类型选择
  • CS——片选
  • AS——ALE
  • R/W ——读/写输入端
  • DS——数据选择或读输入脚
  • RESET——芯片复位引脚
  • IRQ——中断请求输出
  • SQW——方波输出引脚


(2)连线图


(3)项目流程图

三.程序实现


#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit dula=P2^6;
sbit wela=P2^7;
sbit rs=P3^5;
sbit lcden=P3^4;
sbit s1=P3^0;//功能键
sbit s2=P3^1;//增加键
sbit s3=P3^2;//减小键
sbit s4=P3^6;//闹钟查看键
sbit rd=P3^7;
sbit beep=P2^3;//蜂鸣器
sbit dscs=P1^4;
sbit dsas=P1^5;
sbit dsrw=P1^6;
sbit dsds=P1^7;
sbit dsirq=P3^3;
bit flag1,flag_ri;//定义两个位变量
uchar count,s1num,flag,t0_num;//其它变量定义
char miao,shi,fen,year,month,day,week,amiao,afen,ashi;
uchar code table[]=" 20  -  -      ";//液晶固定显示内容
uchar code table1[]="      :  :  ";
void write_ds(uchar,uchar);//函数申明
void set_alarm(uchar,uchar,uchar);void read_alarm();
uchar read_ds(uchar);void set_time();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);}write_com(0x80+0x40);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+shi);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函数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)
{//读12C887函数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;
}
/*---首次操作12C887时给予寄存器初始化---*/
void set_time()
{//首次上电初始化时间函数write_ds(4, 0);write_ds(2, 0);/*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寄存器表示响应了中断
}

四、结果显示

五.思考题

如何使用TX-1C实验板扩展本实验?
答:DS12C887是一款纯数字式的芯片,只要它与单片机的I/O口直接相连就可以操作它了,IX XIC实验板时需要准备一小块面包电路板,一些杜邦线。
操作DS12C887时钟芯片共需要13条信号线,分别是并行数据地址复用线ADO~AD7,CS,AS,R/W,DS和RQ。然后将 RESET引脚固定接高电平,再将DS12C887芯片的Vcc和GND引脚与实验板相连即可。连接信号线时需要考虑不要和原来实验板上的其他资源造成操作冲突,DS12C887芯片的数据地址复用线可以和单片机的P0口相连。同时注意,P0口同时也连接着液晶数据口,但这样复用并不会发生冲突,因为单片机在操作液晶的时候是不会操作DS12C887的,它们各自都有片选信号,选中时操作对应的芯片就不会造成冲突。DS,AS,R/W,CS分别连接单片机的P1.4~P1.7口,当然连接其他口也可以,只要可以正常操作即可。IRQ是DS12C887的中断申请端,该引脚不能随便连接,必须与单片机的外部中断引脚相连,这样当DS12C887芯片向单片机申请中断时,单片机才不会遗漏的检测出所有的中断,这里我们将其与单片机的P3.3口相连。

使用DS12C887时钟芯片设计高精度时钟(单片机)相关推荐

  1. DS3231高精度时钟,LCD1602显示,QXmini151版本

    本设计的主要任务是计时和显示. 设计任务的具体要求如下: 计时:第一种是通过单片机内部的定时器/计数器来实现为软时钟.第二种是通过专用的硬件时钟芯片来实现为硬时钟. 显示:第一种是数码管显示,分为静态 ...

  2. mpc5774时钟监控寄存器_单片机如何才能不死机之内外部时钟

    1. 前言 时钟是嵌入式系统中非常重要,但又常常被忽视的地方.它的成本只占整个系统的一个零头,但由于时钟的停振,或其它异常最终导致厂商付出高昂代价的案例却并不少见.下面我们看一下在时钟设计中应该注意的 ...

  3. 单片机设计时钟程序c语言,单片机电子时钟程序设计

    共用体除非必要,否则我们不推荐使用,枚举的用法比较简单,在本书 19 章的项目实践中有很好的示例,这节课我们先来练习一下结构体的使用.下边这个程序的功能是一个带日期的电子钟,相当于一个简易万年历了,并 ...

  4. 单片机之外部时钟与内部时钟

    1.晶振 首先,单片机能正常工作的必要条件之一就是时钟电路,时钟是单片机的脉搏,是单片机的驱动源,单片机工作是在统一的时钟脉冲控制下一拍一拍进行工作的.这个脉冲由单片机控制器中的时序电路发出的.所以单 ...

  5. linux 内核定时器精度_高精度时钟工作机制简介

    1. 为什么会有高精度时钟 既然提到高精度,那么其对应的就是低精度,所以高精度时钟是为了解决低精度时钟计时精度不足的问题.举个例子帮助理解,日出而作,日落而息,古人以天为单位,安排劳作和休息.随着生产 ...

  6. 2019-12-02 调用C++高精度时钟 std::chrono::high_resolution_clock的方法

    调用C++高精度时钟 std::chrono::high_resolution_clock的方法 测试usleep()的延时误差 // high_resolution_clock example #i ...

  7. 计算机时钟的工作原理,单片机的周期与系统时钟的工作原理

    我们先来理解几个比较重要的概念:时间周期.指令周期.机器周期,以及系统时钟的工作原理. 时钟周期: 时钟周期也叫振荡周期或晶振周期,即晶振的单位时间发出的脉冲数,一般有外部的振晶产生,比如12MHZ= ...

  8. linux内核配置高精度时钟,关于linux内核中使用的时钟

    linux内核里面用了很多的时钟,其实这些时钟的用处无外乎就几种:1.作为心跳,中断cpu:2.使得用户可以获取当前时间:3.实时测量:4.定时 服务.知道了使用目的后,我们来看看到底有哪些时钟供我们 ...

  9. DIY一块DS3231的高精度时钟模块,让时钟DS3231/DS1302自动识别

    [DIY]DIY一块DS3231的高精度时钟模块,让时钟DS3231/DS1302自动识别 水晶城堡在设计之初,采用全直插设计理念,保证玩家在自行DIY的过程中,不会因为焊接贴片元器件而烦恼.所以水晶 ...

最新文章

  1. 谷歌推出 ARCore 1.7 版本,增加 AR 滤镜
  2. Python基本语法_异常处理详解
  3. 每日一皮:当我突然有一个很棒的调试想法...
  4. 曲线绕x轴旋转曲面方程_空间曲线绕空间直线旋转生成的旋转曲面方程
  5. 51 Nod 1509 加长棒(巧妙的隔板法计数)
  6. 《SaltStack技术入门与实践》—— Job管理
  7. 解决卸载时残留目标文件夹的问题
  8. cogs2840. 二叉查找树
  9. Hook Windows API调用 C++
  10. html2canvas 在qq保存失败_QQ的截图功能,没想到这么好用!
  11. Linux下把U盘格式化为fat32
  12. echarts 饼图文字图例多种颜色
  13. android记账本折线图_小熊记账本
  14. Visual C++ Redistributable for VS2005/VS2008/VS2010/VS2012/VS2013/VS2015/VS2017/VS2019 下载地址
  15. 自己做量化交易软件(31)小白量化实战5--板块股票池与基本面选股
  16. 微软一个罕为人知的无敌命令
  17. redis事件循环处理框架
  18. 计算机研究与发展投稿记录
  19. RNN-人名分类器算法
  20. Elixir-Pattern matching

热门文章

  1. 【LOD for 3D Graphics】LOD技术背景调查
  2. 离谱!全公司电脑Alt键被抠掉,就为防员工摸鱼...
  3. 如何 重构网络 SDN架构实现
  4. 适合程序员编程的笔记本电脑如何选择?
  5. python 将List中元素两两组合
  6. Android App接入支付功能
  7. javaweb_笔记1(系统架构;servlet分析,注册,生命周期;Servletconfig对象(四个方法)和Servletcontext对象;http协议,get,post)
  8. 移动电源有哪些产品?热门的移动电源推荐
  9. 聚焦应用场景,OriginOS全面焕新用户体验
  10. 系统检测到您疑似使用网页抓取工具访问本_12款最常使用的网络爬虫工具推荐...