在此之前我们已经学习了单片机的定时器、中断、数码管。这篇文章主要讲述如何用上述的知识自己制作一个基于51单片机的数字时钟。
(1)主电路由秒信号发生器、“时、分、秒”计数器、译码器及显示器、校准电路等构成。
(2)秒信号发生器一般用石英晶体振荡器加分频器实现。
(3)译码电路将时、分、秒计数器的输出状态送七段译码器译码,经过八位LED七段共阴显示器显示出来。
(4)校时电路用来对时、分、秒显示数字进行校对。
单片机晶振部位电路,详情请参考《51单片机入门——单片机最小系统》,在此项目中我们选择 11.0592 MHz的晶振。
按键部分我们选择使用单片机的P3.0、P3.1、P3.2 三个 I/O 口 使用。
初版原理:按下开关K2“时”加一,按下开关K3“分”加一,按下开关K4“秒”加一。
终版原理:按下开关K3加一,按下开关K2控制按钮2的位移(例如:刚开始按K3无反应,按一下K2后秒加、再按分加),按下开关K4控制“时分秒”与“年月日”的切换。
在仿真软件中我们选择使用两个4位共阴极数码管(红色),实际电路中选择两个4位0.36英寸的红色共阴极数码管。
//该程序使用两个四位共阴数码管,10.0592Mhz晶振,STC89C52RC单片机,三个轻触开关
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
//单独控制某个引脚的电平不能直接写P3^0=1,必须先定义引脚
sbit key0 = P3^0 ;
sbit key1 = P3^2 ;
sbit key2 = P3^3 ;
uchar s[]={
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //共阴数码管0~9
uchar a = 0 ,hour = 0 , min = 0 , sec = 0 ;
uchar b = 0 , c = 0 , d = 0;
void time0_server_() interrupt 1 // interrupt 0表示外部中断0 , 1表示定时器中断0 , 2表示外部中断1 , 3表示定时器中断1 , 4表示串口中断
{
TH0 = 0x4c ;
TL0 = 0x00 ;
a++;
if(a == 20) //20 * 50 = 1000ms = 1s 即每隔1s“秒”加1
{
a = 0 ;
sec = sec + 1 ;
}
if(sec == 60) //sec=60时清空,“分”加1
{
min = min + 1 ;
sec = 0 ;
}
if(min == 60) //min=60时清空,“时”加1
{
hour = hour + 1 ;
min = 0 ;
}
if(hour == 24) //hour=24时清空
{
hour = 0 ;
}
}
void init_t0()
{
TMOD = 0x01 ; //采用16位定时器
TH0 = 0x4C ; //50ms (65536-50000)/256
TL0 = 0x00 ; // (65536-50000)%256
EA = 1 ; //开启定时器0的中断
ET0 = 1 ; //开启总中断
TR0 = 1 ; //启动定时器0
}
void delay(uint n) //延时函数(运行空项目以达到延迟时间的效果)
{
uint i,j;
for(i = 0 ; i < n ; i ++)
{
for(j = 0 ; j < 120 ; j ++);
}
}
void display1() //在数码管上显示
{
uchar t0 = 0 ,t1 = 0 , t2 = 0 , t3 = 0 , t4 = 0 , t5 = 0 ;
t0 = hour / 10 ; //t0表示时针的十位
t1 = hour % 10 ; //t1表示时针的个位
t2 = min / 10 ; //t2表示分针的十位
t3 = min % 10 ; //t3表示分针的个位
t4 = sec / 10 ; //t4表示秒针的十位
t5 = sec % 10 ; //t5表示秒针的个位
P2 = 0x7f ; //P2^7低电平 0111 1111 控制第一个数码管
P0 = s[t0] ; //用来显示“时”的十位
delay(1) ; //延时大约1ms
P2 = 0xbf ; //P2^6低电平 1011 1111 控制第二个数码管
P0 = s[t1] ; //用来显示“时”的个位
delay(1) ;
P2 = 0xdf ; //P2^5低电平 1101 1111 控制第三个数码管
P0 = 0x40 ; //显示“—”来分割“时”与“分”
delay(1) ;
P2 = 0xef ; //P2^4低电平 1110 1111 控制第四个数码管
P0 = s[t2] ; //用来显示“分”的十位
delay(1) ;
P2 = 0xf7 ; //P2^3低电平 1111 0111 控制第五个数码管
P0 = s[t3] ; //用来显示“分”的个位
delay(1) ;
P2 = 0xfb ; //P2^2低电平 1111 1011 控制第六个数码管
P0 = 0x40 ; //显示“—”来分割“分”与“秒”
delay(1) ;
P2 = 0xfd ; //P2^1低电平 1111 1101 控制第七个数码管
P0 = s[t4] ; //用来显示“秒”的十位
delay(1) ;
P2 = 0xfe ; //P2^0低电平 1111 1110 控制第八个数码管
P0 = s[t5] ; //用来显示“秒”的个位
delay(1) ;
}
void KEY0() //开关0控制“时”加1
{
if(key0 == 0 && c == 0)
{
c = 1 ;
}
if(key0 == 1 && c == 1)
{
c = 0 ;
hour = hour + 1 ;
}
}
void KEY1() //开关1控制“分”加1
{
if(key1 == 0 && d == 0)
{
d = 1 ;
}
if(key1 == 1 && d == 1)
{
d = 0 ;
min = min + 1 ;
}
}
void KEY2() //开关2控制“秒”加1
{
if(key2 == 0 && b == 0)
{
b = 1 ;
}
if(key2 == 1 && b == 1)
{
b = 0 ;
sec = sec + 1 ;
}
}
void main() //主函数
{
init_t0();
while(1)
{
KEY0();
KEY1();
KEY2();
display1();
}
}
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit key1 = P3^0 ;
sbit key0 = P3^1 ;
sbit key2 = P3^2 ;
sbit key3 = P3^3 ;
uchar s[]={
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //共阴数码管0~9
uchar hour = 10 , min = 10 , sec = 0 ,day = 25 , month = 1 , year = 20 ;
uchar a = 0 ,b = 0 , c = 0 , d = 0 , e = 0 ,f = 0 ;
uchar b_1 = 0 ,c_1 = 0 ;
void time0_server_() interrupt 1
{
TH0 = 0x4c ;
TL0 = 0x00 ;
a++;
e = 2000 + year ;
if(a == 20)
{
a = 0 ;
sec = sec + 1 ;
}
if(sec == 60)
{
min = min + 1 ;
sec = 0 ;
}
if(min == 60)
{
hour = hour + 1 ;
min = 0 ;
}
if(hour == 24)
{
day = day + 1 ;
hour = 0 ;
}
switch(month) //根据月份来控制天数
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:if(day == 32)
{
month = month + 1 ;
day = 1 ;
}
break ;
case 4:
case 6:
case 9:
case 11:if(day == 31)
{
month =month + 1;
day = 1 ;
}
break ;
case 2:if(e%400==0||e%4==0&&e%100!=0)
{
if(day == 30)
{
month = month + 1 ;
day = 1 ;
}
}
else if(day == 29)
{
month = month + 1 ;
day = 1 ;
}
break ;
}
if(month == 13)
{
year = year + 1 ;
month = 1 ;
}
}
void init_t0()
{
TMOD = 0x01 ;
TH0 = 0x4C ;
TL0 = 0x00 ;
EA = 1 ;
ET0 = 1 ;
TR0 = 1 ;
}
void delay(uint n) //延时函数 大约1ms
{
uint i,j;
for(i = 0 ; i < n ; i ++)
{
for(j = 0 ; j < 120 ; j ++);
}
}
void display1() //显示 “时、分、秒”
{
uchar t0 = 0 ,t1 = 0 , t2 = 0 , t3 = 0 , t4 = 0 , t5 = 0 ;
t0 = hour / 10 ;
t1 = hour % 10 ;
t2 = min / 10 ;
t3 = min % 10 ;
t4 = sec / 10 ;
t5 = sec % 10 ;
/************* 74HC138译码器 辅助控制数码管 ******/
// P2 = 0x1c ;
// P0 = s[t0] ;
// delay(2) ;
// P2 = 0x18 ;
// P0 = s[t1] ;
// delay(2) ;
// P2 = 0x14 ;
// P0 = 0x40 ;
// delay(2) ;
// P2 = 0x10 ;
// P0 = s[t2] ;
// delay(2) ;
// P2 = 0x0c ;
// P0 = s[t3] ;
// delay(2) ;
// P2 = 0x08 ;
// P0 = 0x40 ;
// delay(2) ;
// P2 = 0x04 ;
// P0 = s[t4] ;
// delay(2) ;
// P2 = 0x00 ;
// P0 = s[t5] ;
delay(2) ;
/*********** P2直接控制数码管 *********/
P2 = 0x7f ;
P0 = s[t0] ;
delay(1) ;
P2 = 0xbf ;
P0 = s[t1] ;
delay(1) ;
P2 = 0xdf ;
P0 = 0x40 ;
delay(1) ;
P2 = 0xef ;
P0 = s[t2] ;
delay(1) ;
P2 = 0xf7 ;
P0 = s[t3] ;
delay(1) ;
P2 = 0xfb ;
P0 = 0x40 ;
delay(1) ;
P2 = 0xfd ;
P0 = s[t4] ;
delay(1) ;
P2 = 0xfe ;
P0 = s[t5] ;
delay(1) ;
}
void display2() //显示 “年、月、日”
{
uchar t0 = 0 ,t1 = 0 , t2 = 0 , t3 = 0 , t4 = 0 , t5 = 0 ;
t0 = year / 10 ;
t1 = year % 10 ;
t2 = month / 10 ;
t3 = month % 10 ;
t4 = day / 10 ;
t5 = day % 10 ;
/************* 74HC138译码器 辅助控制数码管 ******/
// P2 = 0x1c ;
// P0 = s[t0] ;
// delay(2) ;
// P2 = 0x18 ;
// P0 = s[t1] ;
// delay(2) ;
// P2 = 0x14 ;
// P0 = 0x40 ;
// delay(2) ;
// P2 = 0x10 ;
// P0 = s[t2] ;
// delay(2) ;
// P2 = 0x0c ;
// P0 = s[t3] ;
// delay(5) ;
// P2 = 0x08 ;
// P0 = 0x40 ;
// delay(2) ;
// P2 = 0x04 ;
// P0 = s[t4] ;
// delay(2) ;
// P2 = 0x00 ;
// P0 = s[t5] ;
// delay(2) ;
/*********** P2直接控制数码管 *********/
P2 = 0x7f ;
P0 = s[t0] ;
delay(1) ;
P2 = 0xbf ;
P0 = s[t1] ;
delay(1) ;
P2 = 0xdf ;
P0 = 0x40 ;
delay(1) ;
P2 = 0xef ;
P0 = s[t2] ;
delay(1) ;
P2 = 0xf7 ;
P0 = s[t3] ;
delay(1) ;
P2 = 0xfb ;
P0 = 0x40 ;
delay(1) ;
P2 = 0xfd ;
P0 = s[t4] ;
delay(1) ;
P2 = 0xfe ;
P0 = s[t5] ;
delay(1) ;
}
void KEY0() //控制按钮2的位移
{
if(key0 == 0 && c == 0)
{
c = 1 ;
}
if(key0 == 1 && c == 1)
{
c = 0 ;
c_1 = c_1 + 1 ;
}
if(c_1 == 4)
{
c_1 = 0 ;
}
}
void KEY1() //控制 "秒"、“分”、“时”、“天”、“月”、“年” 的加1
{
switch(c_1)
{
case 1: if(b_1 == 0)
{
if(key1 == 0 && d == 0)
{
d = 1 ;
}
if(key1 == 1 && d == 1)
{
d = 0 ;
sec = sec + 1 ;
}
}
else if(b_1 == 1)
{
if(key1 == 0 && d == 0)
{
d = 1 ;
}
if(key1 == 1 && d == 1)
{
d = 0 ;
day = day + 1 ;
}
}
break ;
case 2: if(b_1 == 0)
{
if(key1 == 0 && d == 0)
{
d = 1 ;
}
if(key1 == 1 && d == 1)
{
d = 0 ;
min = min + 1 ;
}
}
else if(b_1 == 1)
{
if(key1 == 0 && d == 0)
{
d = 1 ;
}
if(key1 == 1 && d == 1)
{
d = 0 ;
month = month + 1 ;
}
}
break ;
case 3: if(b_1 == 0)
{
if(key1 == 0 && d == 0)
{
d = 1 ;
}
if(key1 == 1 && d == 1)
{
d = 0 ;
hour = hour + 1 ;
}
}
else if(b_1 == 1)
{
if(key1 == 0 && d == 0)
{
d = 1 ;
}
if(key1 == 1 && d == 1)
{
d = 0 ;
year = year + 1 ;
}
}
break ;
}
}
void KEY2() //控制 "秒"、“分”、“时”、“天”、“月”、“年” 的减1
{
switch(c_1)
{
case 1: if(b_1 == 0)
{
if(key2 == 0 && f == 0)
{
f = 1 ;
}
if(key2 == 1 && f == 1)
{
f = 0 ;
sec = sec - 1 ;
if(sec == 255)
{
sec = 59 ;
}
}
}
else if(b_1 == 1)
{
if(key2 == 0 && f == 0)
{
f = 1 ;
}
if(key2 == 1 && f == 1)
{
f = 0 ;
day = day - 1 ;
if(day <= 1)
{
day = 1 ;
}
}
}
break ;
case 2: if(b_1 == 0)
{
if(key2 == 0 && f == 0)
{
f = 1 ;
}
if(key2 == 1 && f == 1)
{
f = 0 ;
min = min - 1 ;
if(min == 255)
{
min = 0 ;
}
}
}
else if(b_1 == 1)
{
if(key2 == 0 && f == 0)
{
f = 1 ;
}
if(key2 == 1 && f == 1)
{
f = 0 ;
month = month - 1 ;
if(month <= 1)
{
month = 1 ;
}
}
}
break ;
case 3: if(b_1 == 0)
{
if(key2 == 0 && f == 0)
{
f = 1 ;
}
if(key2 == 1 && f == 1)
{
f = 0 ;
hour = hour - 1 ;
if(hour == 255)
{
hour = 0 ;
}
}
}
else if(b_1 == 1)
{
if(key2 == 0 && f == 0)
{
f = 1 ;
}
if(key2 == 1 && f == 1)
{
f = 0 ;
year = year - 1 ;
if(year == 255)
{
year = 0 ;
}
}
}
break ;
}
}
void KEY3() //控制“时、分、秒”与“年、月、日”的转换
{
if(key3 == 0 && b == 0)
{
b = 1 ;
}
if(key3 == 1 && b == 1)
{
b = 0 ;
b_1 = b_1 + 1;
}
if(b_1 == 2)
{
b_1 = 0 ;
}
switch(b_1)
{
case 0: display1() ;
break ;
case 1: display2() ;
break ;
}
}
void main()
{
init_t0();
while(1)
{
KEY0();
KEY1();
KEY2();
KEY3();
}
}
数码管:7SEG-MPX4-CC
单片机:AT89C52
按键:BUTTON
排阻:RESPACK-8
名称 | 封装 | 数量 |
---|---|---|
STC89C52 | PDIP-40 | 1 |
排阻 4.7K | A472J | 1 |
10K色环电阻 | AXIAL0.5 | 1 |
0.36寸共阴数码管 | CL3631AH | 2 |
轻触开关 | DIP-6x6x6 | 4 |
30pF电容 | RAD-0.2 | 2 |
10uF电解电容 | DIP-EC2.0X5X11 | 1 |
11.0592MHz晶振 | OSC HC-49S | 1 |
文章浏览阅读2.1k次。云计算离不开底层的虚拟化技术支持,目前虚拟化技术很多种,云吞铺子分享常见的虚拟化架构种类、特点及优势:虚拟化架构根据在整个系统中的位置不同,虚拟化架构分为以下几种:寄居虚拟化架构裸金属虚拟化架构操作系统虚拟化架构混合虚拟化架构寄居虚拟化架构寄居虚拟化架构指在宿主操作系统之上安装和运行虚拟化程序,依赖于宿主操作系统对设备的支持和物理资源..._虚拟化架构分为哪几种有啥特点
文章浏览阅读1.4k次。在JMeter中,可以使用BeanShell脚本来实现接口的前置和后置操作。下面是使用BeanShell脚本实现接口前置和后置操作的步骤:_beanshell后置处理器获取参数
文章浏览阅读2.3k次,点赞2次,收藏9次。作者:denniszhu ,腾讯 CDG 开发工程师面对大量代码,在开发任务繁重场景下,VSCode 绝对是一把利器。本文虽以 C++为引,但在 python、php、java 等中后台..._vs code c++大纲
文章浏览阅读8k次。CLion 也不错,不过要收费在过去的几年中,要从头开始创建应用程序,开发人员必须付出很多努力。因为要创建软件应用程序,所以从编码,编译,测试,调试,构建和部署开始将需要很多步骤。所有这些不同的阶段将需要安装不同的软件包,并且开发人员难以维护。因此,为了提高生产率并加快软件开发过程,所有对开发必不可少的软件包都集成或组合到称为IDE(集成开发环境)的单个环境中,这使现代软件开发变得更加轻松快捷。典型的IDE必须具有一些功能,例如语法突出显示,自动代码完成,自动保存代码,代码搜索,编译器,重构.._c++开发工具
文章浏览阅读136次。 最近无聊,想知道一下玩斗地主的话我能有多大的概率拿到炸弹(4张同点数牌 或 集齐大小王)。但是我概率学学得不好,于是想到用统计学来试试,随手写了一个程序模拟一下斗地主的发牌过程 面向对象Card 首先依据OOP思想,我把牌看作是一个对象,点数与花色是其属性,为了处理大小王加入了Type属性 public class Card { Suit suit; Size s...
文章浏览阅读320次。Java垃圾回收器是一种“自适应的、分代的、停止—复制、标记-清扫”式的垃圾回收器。 1、 在堆上分配对象的代价十分高昂,然而java的垃圾回收机制可以和其他语言从堆栈上分配空间的速度想媲美,但是,释放对上的存储空间也有开销; 2、 当它工作的时候,将一面回收_如何优化java垃圾回收机制 - csdn博客
文章浏览阅读671次。信息摘要是由单向散列函数加密成的固定长度的散列值不可逆的。作用:确保信息的完整性,防篡改。哈希算法生成的哈希值的长度必须是固定的,而输入数据是任意长度,效率高。MD5、SHA属于哈希算法。MD5的散列值为128位,SHA算法的散列值为160位,因此SHA的安全性高一些。
文章浏览阅读3k次,点赞2次,收藏4次。鼠标随意点在模型上射线会射在所点击处,并显示点击处的坐标。代码:using UnityEngine;using System.Collections;public class Test : MonoBehaviour{ void Update() { if (Input.GetMouseButton(0)) { ..._unity显示射线焦点坐标
文章浏览阅读546次。正如官方所说,mybatis-plus在mybatis的基础上只做增强不做改变,因此其与spring的整合亦非常简单。只需把mybatis的依赖换成mybatis-plus的依赖,再把sqlSessionFactory换成mybatis-plus的即可。_文字描述springboot整合mybatis-plus过程
文章浏览阅读2.7k次。使用 Node Exporter for Prometheus Dashboard 监控服务器CPU 内存 磁盘 IO 网络 流量 温度等指标当需要监控服务器的CPU 内存 磁盘 IO 网络 流量 温度等指标。可以使用 grafana 的 dashborad 。插件名称:Node Exporter for Prometheus Dashboard插件链接: https://grafana.c..._grafana node_exporter dashboard
文章浏览阅读978次。Linux下快速搭建ntp时间同步服务器背景:服务器多了,时间是否一致以及是否准备就显得格外重要,虽然这个问题总是被忽略,但是统一时间是很有必要的,因为时间问题导致服务出现问题也是司空见惯,本文简单介绍一下ntp的快速搭建和使用。1、安装ntpyum -y install ntp(直接yum安装即可)2、修改ntp.conf的配置1)vim /etc/ntp.conf①配置方法一:只允许192.1..._linux ntp校时
文章浏览阅读4.1k次,点赞3次,收藏6次。大家好,我是前端西瓜哥。我所在的公司的前端部门,每周都会开周会,然后其中一个环节就是做技术分享。我们是轮流每周一位前端同学做主持人,且必须做技术分享,其他人则是选择性分享。今天我们讲讲如何在团队内做技术分享。我们的形式很简单,分享者将要分享的内容放到 协同在线文档,将链接发出来,然后分享者投屏到视频会议上。有些会议软件像飞书支持投屏文档,投出来的文档和浏览器打开没有区别,可以自由选择是否追随共享人的位置,个人觉得挺方便的,不需要自己一会看发出来的链接,一会看投屏。没必要一定要用 PPT 的形式分享。因为 P_公司每周技术分享前端