蓝桥杯单片机DS1302实时时间设计(时间暂停、启动设置)

it2025-04-23  12

蓝桥杯单片机DS1302时间设计,这也是蓝桥杯中常考的一个模块。对于DS1302的操作也是非常简单的,只需要简单记住控制写入以及读出的地址位便可,其余都是在调用官方提供的底层驱动代码,只要会调用就能够轻松编写出一个实时时钟了。

设计时钟的暂停以及暂停之后启动,使用按键S4进行控制,还有就是使用按键S5进行控制日期的显示。

# include "reg52.h" # include "ds1302.h" // 官方提供的底层驱动代码 typedef unsigned int u16; typedef unsigned char u8; // 秒 分 时 日 月 周 年(最后两位) u8 code DS1302_read[7] = {0x81,0x83,0x85,0x87,0x89,0x8b,0x8d}; // Ds1302读取数据的地址位 u8 code DS1302_write[7] = {0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; // 20-10-10-23-59-50(2020-10-10 23:59:50) u8 timer[7] = {0x50,0x59,0x23,0x10,0x10,0x06,0x20}; u8 shuma[12] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xbf}; sbit S4 = P3^3; sbit S5 = P3^2; u8 stop = 0; u8 temp; // 用于保存暂停之前的秒钟的数值,点击启动的时候重新写入到秒钟的寄存器中即可 // 实现功能:按键控制,按下按键S4,暂停时钟计算(开始);按下S5显示日期,放开继续显示时钟; // 主要考点:最后一位控制写的位数,低电位才能够写入,高电位写入保护,禁止写入内容;秒钟的第一位控制暂停的位置,高电位暂停; // 外设初始化 void init_system() { P2 = (P2 & 0x1f) | 0x80; P0 = 0xff; P2 = (P2 & 0x1f); P2 = (P2 & 0x1f) | 0xa0; P0 = 0x00; P2 = (P2 & 0x1f); P2 = (P2 & 0x1f) | 0xc0; P0 = 0x00; P2 = (P2 & 0x1f); } // 导通函数 void select(u8 local) { switch(local) { case(4): P2 = (P2 & 0x1f) | 0x80; break; case(5): P2 = (P2 & 0x1f) | 0xa0; break; case(6): P2 = (P2 & 0x1f) | 0xc0; break; case(7): P2 = (P2 & 0x1f) | 0xe0; break; } } // 简单延时函数 void delay() { u8 t; t = 200; while(t--); } // 数码管点亮函数,点亮单个数码管 void display(u8 local, u8 num) { select(6); P0 = 0x80 >> (local - 1); P2 = P2 & 0x1f; select(7); P0 = num; P2 = P2 & 0x1f; // 简单延时 delay(); // 消隐 (为了不要让最后一个数码管特别亮,其余的特别暗) select(6); P0 = 0x00; P2 = P2 & 0x1f; } // DS1302芯片的初始化,写入初始时间 void ds1302_init() { u8 i; Write_Ds1302_Byte(0x8e,0x00); // 打开写入保护位,不打开无法写入数据 for(i = 0; i < 7; i++) { Write_Ds1302_Byte(DS1302_write[i],timer[i]); // 分别写入初始化时间到对应的寄存器中 } Write_Ds1302_Byte(0x8e,0x80); // 关闭写入保护位,防止数据被恶意修改 } // DS1302芯片的时间读取 void ds1302_reader() { u8 i; for(i = 0; i < 7; i++) { timer[i] = Read_Ds1302_Byte(DS1302_read[i]); } } // 数码管显示的内容 void shuma_display(u8 i,u8 j,u8 k) { display(3,shuma[10]); display(6,shuma[10]); display(1,shuma[i%16]); display(2,shuma[i/16]); display(4,shuma[j%16]); display(5,shuma[j/16]); display(7,shuma[k%16]); display(8,shuma[k/16]); } void scan() { if(S4 == 0) { delay(); if(S4 == 0 && stop == 0) // 启动暂停的控制位 { temp = Read_Ds1302_Byte(DS1302_read[0]); Write_Ds1302_Byte( 0x8e,0x00); Write_Ds1302_Byte( DS1302_write[0],0x00); Write_Ds1302_Byte( 0x8e,0x80); stop = 1; } if(S4 == 0 && stop == 1) { Write_Ds1302_Byte( 0x8e,0x00); Write_Ds1302_Byte( DS1302_write[0],temp); Write_Ds1302_Byte( 0x8e,0x80); stop = 0; } while(!S4){shuma_display(timer[0],timer[1],timer[2]);} } if(S5 == 0) // 显示日期 { delay(); if(S5 == 0) { shuma_display(timer[3],timer[4],timer[6]); while(!S5){shuma_display(timer[3],timer[4],timer[6]);} } } } void main() { init_system(); ds1302_init(); //写入数据到芯片中 while(1) { ds1302_reader(); // 读取数据 scan(); if(stop == 0) { shuma_display(timer[0],timer[1],timer[2]); } if(stop == 1) { shuma_display(temp,timer[1],timer[2]); } // 这里的暂停之后启动还存在一定的小问题,欢迎给出建议修改 } }

具体思路:使用一个判断位来判断当前时钟是暂停状态还是启动状态,按下暂停之后保存当前的时间,同时把秒钟寄存器的最高位置为1,;在下一次启动的时候,把暂停前保存的时间重新写入到时钟寄存器中。

最新回复(0)