|
- #include<reg52.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit lcden=P3^4; //液晶使能端
- sbit rs=P3^5; //液晶数据命令选择端
- sbit led=P2^5; //控制LED的锁存器
- sbit dula=P2^6; //控制LCD的段锁存器
- sbit wela=P2^7; //控制LCD的位锁存器
- sbit dsirq=P3^2; //DS12887的中断请求端
- sbit dsds=P1^7; //DS12887的读允许输入端
- sbit dsrw=P1^6; //DS12887的写允许输入端
- sbit dsas=P1^5; //DS12887的地址选通端
- sbit dscs=P1^4; //DS12887的芯片片选端
- sbit a=P3^0; //设置键盘用的
- sbit b=P3^1; //设置键盘用的
- sbit c=P3^6; //设置键盘用的
- sbit d=P3^7; //设置键盘用的
- sbit e=P3^3; //设置键盘用的
- uchar code table1[]=" 2000-00-00 ";
- uchar code table2[]=" 00:00:00 ";
- uchar flag1,flag2,temp,temp1;
- /*
- falg1标志位是用来判断是否执行从DS12C887中读取数据并送去液晶显示;
- flag2标志位是用来判断LCD上显示的年数是否是闰年;
- temp与temp1都时当月的天数值,用来判断DS12C887中的天数值是否大
- 于当月应有的天数,如大于则将天数值置1,如有需要请重新设置天数值。
- */
- char miao,fen,nian,yue,ri,xingqi;
- int shi; //小时的数值大于128,所以不能选择char型数据
- /*------------
- 延时子程序
- */
- void delayms(uchar a)
- {
- uchar x,y;
- for(x=a;x>0;x--)
- for(y=110;y>0;y--);
- }
- /*----------------
- 往液晶中写指令
- ----------------*/
- void write_com(uchar com)
- {
- rs=0; //选择写命令模式
- lcden=0; //将lcden置为零
- P0=com; //将要写的命令字送到数据总线上
- delayms(5); //稍做延时以待数据稳定
- lcden=1; //使能端给一个高脉冲
- delayms(5); //稍做延时
- lcden=0; //将使能端置0以完成高脉冲
- }
- /*----------------
- 往液晶中写数据
- ----------------*/
- void write_date(uchar date)
- {
- rs=1; //选择写数据模式
- lcden=0; //将lcden置为零
- P0=date; //将要写的数据送到数据总线上
- delayms(5); //稍做延时以待数据稳定
- lcden=1; //使能端给一个高脉冲
- delayms(5); //稍做延时
- lcden=0; //将使能端置0以完成高脉冲
- }
- /*--------------------
- 向DS12C887内写数据
- --------------------*/
- 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;
- }
- /*--------------------
- 从DS12C887中读数据
- --------------------*/
- uchar read_ds(uchar add)
- {
- uchar temp;
- dscs=0;
- dsas=1;
- dsds=1;
- dsrw=1;
- P0=add; //先写地址
- dsas=0;
- dsds=0;
- P0=0xff; //读数据之前先将P0口置一
- temp=P0; //再读数据
- dsds=1;
- dsas=1;
- dscs=1;
- return temp;
- }
- /*----------------------------------------------------------------------
- 24小时制在液晶的指定位置写入时分秒,12小时制在液晶的指定位置写入分秒
- ----------------------------------------------------------------------*/
- void write_sfm(uchar add,uchar date)
- {
- uchar shi,ge;
- shi=date/10; //分解一个2位数的十位和个位
- ge=date%10;
- write_com(0x80+0x40+add); //设置显示位置
- write_date(shi+0x30); //送去液晶显示十位
- write_date(ge+0x30); //送去液晶显示个位
- }
- /*----------------------------
- 在液晶的指定位置写入年月日
- ----------------------------*/
- void write_nyr(uchar add,uchar date)
- {
- uchar shi,ge;
- shi=date/10; //分解一个2位数的十位和个位
- ge=date%10;
- write_com(0x80+add); //设置显示位置
- write_date(shi+0x30); //送去液晶显示十位
- write_date(ge+0x30); //送去液晶显示个位
- }
- /*----------------------------
- 在液晶的指定位置写入星期
- ----------------------------*/
- void write_xq(uchar date)
- {
- uchar i;
- i=date;
- write_com(0x80+12);
- switch(i) //switch-case语句判断i的值及执行相应的操作
- {
- case 1: //当i等于1时,送去液晶显示MON(星期一)
- write_date('M');
- write_date('O');
- write_date('N');
- break;
- case 2: //当i等于2时,送去液晶显示TUE(星期二)
- write_date('T');
- write_date('U');
- write_date('E');
- break;
- case 3: //当i等于3时,送去液晶显示WED(星期三)
- write_date('W');
- write_date('E');
- write_date('D');
- break;
- case 4: //当i等于4时,送去液晶显示THU(星期四)
- write_date('T');
- write_date('H');
- write_date('U');
- break;
- case 5: //当i等于5时,送去液晶显示FRI(星期五)
- write_date('F');
- write_date('R');
- write_date('I');
- break;
- case 6: //当i等于6时,送去液晶显示SAT(星期六)
- write_date('S');
- write_date('A');
- write_date('T');
- break;
- case 7: //当i等于7时,送去液晶显示SUN(星期日)
- write_date('S');
- write_date('U');
- write_date('N');
- break;
- }
- }
- /*----------------
- 判断天数的函数
- ----------------*/
- char day_num(char nian,char yue)
- {
- char num;
- if(((nian%4==0)&&(nian%100!=0))||((nian%100==0)&&(nian%400==0))) //闰年判断
- flag2=1;
- else
- flag2=0;
- if(flag2==1) //是闰年时,将第二月的天数设为29
- {
- switch(yue)
- {
- case 1:
- num=31; //1月的天数
- break;
- case 2:
- num=29; //2月的天数
- break;
- case 3:
- num=31; //3月的天数
- break;
- case 4:
- num=30; //4月的天数
- break;
- case 5:
- num=31; //5月的天数
- break;
- case 6:
- num=30; //6月的天数
- break;
- case 7:
- num=31; //7月的天数
- break;
- case 8:
- num=31; //8月的天数
- break;
- case 9:
- num=30; //9月的天数
- break;
- case 10:
- num=31; //10月的天数
- break;
- case 11:
- num=30; //11月的天数
- break;
- case 12:
- num=31; //12月的天数
- break;
- }
- }
- if(flag2==0) //不是闰年时,将第二月的天数设为28
- {
- switch(yue)
- {
- case 1:
- num=31; //1月的天数
- break;
- case 2:
- num=28; //2月的天数
- break;
- case 3:
- num=31; //3月的天数
- break;
- case 4:
- num=30; //4月的天数
- break;
- case 5:
- num=31; //5月的天数
- break;
- case 6:
- num=30; //6月的天数
- break;
- case 7:
- num=31; //7月的天数
- break;
- case 8:
- num=31; //8月的天数
- break;
- case 9:
- num=30; //9月的天数
- break;
- case 10:
- num=31; //10月的天数
- break;
- case 11:
- num=30; //11月的天数
- break;
- case 12:
- num=31; //12月的天数
- break;
- }
- }
- return num; //函数的返回值时当月的天数
- }
- /*--------------
- 键盘扫描程序
- --------------*/
- void keyscan()
- {
- uchar num;
- a=0; //设置矩阵键盘S1低电平
- b=1; //设置矩阵键盘S2高电平
- if(c==0) //判断S3有没有被按下
- {
- delayms(5); //去抖延时
- if(c==0) //判断S3有没有被按下
- {
- while(!c); //判断按键S3有没有释放
- num++; //按下键的次数
- flag1=1; //标志位flag1置一
- if(num==1) //当num等于1时,光标在秒钟处闪烁
- {
- write_com(0x80+0x40+8);
- write_com(0x0f);
- }
- if(num==2) //当num等于2时,光标在分钟处闪烁
- {
- write_com(0x80+0x40+5);
- write_com(0x0f);
- }
- if(num==3) //当num等于3时,光标在时钟处闪烁
- {
- write_com(0x80+0x40+2);
- write_com(0x0f);
- }
- if(num==4) //当num等于4时,光标在年处闪烁
- {
- write_com(0x80+4);
- write_com(0x0f);
- }
- if(num==5) //当num等于5时,光标在月处闪烁
- {
- write_com(0x80+7);
- write_com(0x0f);
- }
- if(num==6) //当num等于6时,光标在日处闪烁
- {
- write_com(0x80+10);
- write_com(0x0f);
- }
- if(num==7) //当num等于7时,光标在星期处闪烁
- {
- write_com(0x80+14);
- write_com(0x0f);
- }
- if(num==8)
- {
- num=0; //num清0
- write_ds(0x00,miao); //将秒写入DS12C887
- write_ds(0x02,fen); //将分写入DS12C887
- write_ds(0x04,shi); //将时写入DS12C887
- write_ds(0x06,xingqi); //将星期写入DS12C887
- write_ds(0x07,ri); //将日写入DS12C887
- write_ds(0x08,yue); //将月写入DS12C887
- write_ds(0x09,nian); //将年写入DS12C887
- flag1=0; //标志位flag1清0
- }
- }
- }
- if(num!=0) //当功能键S3按下后,数值增大键S4才有用
- {
- a=0; //设置矩阵键盘第一排位低电平
- b=1; //设置矩阵键盘第二排位高电平
- if(d==0) //判断S4有没有被按下
- {
- delayms(5); //去抖延时
- if(d==0) //判断S4有没有被按下
- {
- while(!d); //判断按键S4有没有释放
- if(num==1)
- {
- miao++; //当num=1时,秒值加一
- if(miao>59) //当秒值大于59时,将秒值置0
- miao=0;
- write_sfm(7,miao); //将秒值写入液晶显示
- write_com(0x80+0x40+8); //光标在秒值的个位闪烁
- write_com(0x0f);
- }
- if(num==2)
- {
- fen++; //当num=2时,分值加一??
- if(fen>59) //当分值大于59时,将分值置0
- fen=0;
- write_sfm(4,fen); //将分值写入液晶显示
- write_com(0x80+0x40+5); //光标在分值的个位闪烁
- write_com(0x0f);
- }
- if(num==3)
- {
- shi++; //当num=3时,时钟加一?
- if(shi>23) //当时钟大于23时,将时钟置0
- shi=0;
- write_sfm(1,shi); //将时钟写入液晶显示
- write_com(0x80+0x40+2); //光标在时钟的个位闪烁
- write_com(0x0f);
- }
- if(num==4)
- {
- nian++; //当num=4时,年加一
- if(nian>99) //当年大于99时,将年置0
- nian=0;
- write_nyr(3,nian); //将年写入液晶显示
- write_com(0x80+4); //光标在年的个位闪烁
- write_com(0x0f);
- }
- if(num==5)
- {
- yue++; //当num=5时,月加一
- if(yue>12) //当月大于12时,将月置1
- yue=1;
- write_nyr(6,yue); //将月写入液晶显示
- write_com(0x80+7); //光标在月的个位闪烁
- write_com(0x0f);
- }
- if(num==6)
- {
- ri++; //当num=6时,日加一
- temp=day_num(nian,yue);
- if(ri>temp) //当日大于当月的天数时,将日置1
- ri=1;
- write_nyr(9,ri); //将日写入液晶显示
- write_com(0x80+10); //光标在月的个位闪烁
- write_com(0x0f);
- }
- if(num==7)
- {
- xingqi++; //当num=7时,星期加一
- if(xingqi>7) //当星期大于7时,将星期置1
- xingqi=1;
- write_xq(xingqi); //将星期写入液晶显示
- write_com(0x80+14); //光标在星期的个位闪烁
- write_com(0x0f);
- }
- }
- }
- }
- if(num!=0) //当功能键S3按下后,数值减小键S5才有用
- {
- a=1; //设置矩阵键盘第一排位高电平
- b=0; //设置矩阵键盘第二排位低电平
- if(e==0) //判断S5有没有被按下
- {
- delayms(5); //去抖延时
- if(e==0) //判断S5有没有被按下
- {
- while(!e); //判断按键S5有没有释放
- if(num==1)
- {
- miao--; //当num=1时,秒值减一
- if(miao<0) //当秒值小于0时,将秒值置59
- miao=59;
- write_sfm(7,miao); //将秒值写入液晶显示
- write_com(0x80+0x40+8); //光标在秒值的个位闪烁
- write_com(0x0f);
- }
- if(num==2)
- {
- fen--; //当num=2时,分值减一
- if(fen<0) //当分值小于0时,将分值置59
- fen=59;
- write_sfm(4,fen); //将分值写入液晶显示
- write_com(0x80+0x40+5); //光标在分值的个位闪烁
- write_com(0x0f);
- }
- if(num==3)
- {
- shi--; //当num=3时,时钟减一
- if(shi<0) //当时钟小于0时,将时钟置23
- shi=23;
- write_sfm(1,shi); //将时钟写入液晶显示
- write_com(0x80+0x40+2); //光标在时钟的个位闪烁
- write_com(0x0f);
- }
- if(num==4)
- {
- nian--; //当num=4时,年减一
- if(nian<0) //当年小于0时,将年置99
- nian=99;
- write_nyr(3,nian); //将年写入液晶显示
- write_com(0x80+4); //光标在年的个位闪烁
- write_com(0x0f);
- }
- if(num==5)
- {
- yue--; //当num=5时,月减一
- if(yue<1) //当月小于1时,将月置12
- yue=12;
- write_nyr(6,yue); //将月写入液晶显示
- write_com(0x80+7); //光标在月的个位闪烁
- write_com(0x0f);
- }
- if(num==6)
- {
- ri--; //当num=6时,日减一
- temp=day_num(nian,yue);
- if(ri>temp)
- ri=temp;
- if(ri<1) //当日小于1时,将日置为当月的天数
- ri=temp;
- write_nyr(9,ri); //将日写入液晶显示
- write_com(0x80+10); //光标在月的个位闪烁
- write_com(0x0f);
- }
- if(num==7)
- {
- xingqi--; //当num=7时,星期加一
- if(xingqi<1) //当星期小于1时,将星期置7
- xingqi=7;
- write_xq(xingqi); //将星期写入液晶显示
- write_com(0x80+14); //光标在星期的个位闪烁
- write_com(0x0f);
- }
- }
- }
- }
- }
- /*--------------
- ? 初始化时钟函数
- --------------*/
- void set_time()
- {
- write_ds(0,0); //初始化时钟秒钟的数值为0
- write_ds(2,0); //初始化时钟分钟的数值为0
- write_ds(4,1); //初始化时钟小时的数值为1
- write_ds(6,1); //初始化时钟星期的数值为1
- write_ds(7,1); //初始化时钟日的数值为1
- write_ds(8,1); //初始化时钟月的数值为1
- write_ds(9,0); //初始化时钟年的数值为0
- }
- /*------------
- ? 初始化程序
- ------------*/
- void init()
- {
- uchar i;
- dula=0; //关段锁存器(不让数码管显示)
- wela=0; //关位锁存器
- lcden=0;
- write_com(0x38); //设置16*2显示,5*7点阵,8位数据接口(LCD初始化设置)
- write_com(0x0c); //设置开显示,不显示光标(LCD初始化设置)
- write_com(0x06); //写一个字符后地址指针自动加一(LCD初始化设置)
- write_com(0x01); //显示清零,数据指针清零(LCD初始化设置)
- write_com(0x80); //将数据指针定位到第一行第一字处
- for(i=0;i<16;i++)
- {
- write_date(table1[i]); //将字符串1写入液晶
- }
- write_com(0x80+0x40); //将数据指针定位到第2行第1字处
- for(i=0;i<16;i++)
- {
- write_date(table2[i]); //将字符串2写入液晶
- }
- set_time(); //初始化时钟
- }
- void main()
- {
- init(); //调用初始化子程序
- while(1)
- {
- keyscan();
- if(flag1==0) //当标志位flag1等于0时,才从DS12C887中读取数据并送去液晶显示
- {
- miao=read_ds(0); //从DS12C887中读取秒的值
- write_sfm(7,miao); //将秒值送去液晶显示
- fen=read_ds(0x02); //从DS12C887中读取分的值
- write_sfm(4,fen); //将分值送去液晶显示
- shi=read_ds(0x04); //从DS12C887中读取小时的值
- write_sfm(1,shi); //将小时送去液晶显示
- nian=read_ds(0x09); //从DS12C887中读取年的值
- write_nyr(3,nian); //将年值送去液晶显示
- yue=read_ds(0x08); //从DS12C887中读取月份的值
- write_nyr(6,yue); //将月份送去液晶显示
- ri=read_ds(0x07); //从DS12C887中读取日的值
- temp1=day_num(nian,yue); //读取当月的天数值
- if(ri>temp1) //判断DS12C887中的天数值是否大于当月应有的天数,如大于则将天数值置1,如有需要请重新设置
- ri=1;
- write_nyr(9,ri); //将日值送去液晶显示
- xingqi=read_ds(0x06); //从DS12C887中读取星期的值
- write_xq(xingqi); //将星期送去液晶显示
- }
- }
- }
复制代码
|
评分
-
查看全部评分
|