AT89C51单片机万年历仿真图+代码

article/2025/9/18 1:51:21

首先申明,这篇博客是用作记录本人实训内容的,代码我个人一字一字码的,就上网查了下数字温度传感器DS18B20的处理方法,基本都是个人完成的。
在这里吐槽下,本人辛辛苦苦码的代码,最后实训分数还没那些抄的人高,吐槽下老师- -,好了接下来说正事。
注意:可能有些人复制代码后会报错,可能是环境问题,也可能其他问题,反正自己简单调试下就行了,不过大部分肯定没问题。

:在评论有附本人交通灯的图噢,不过我还是建议各位先自己画。噢还要注意图里芯片,双击.hex的路径,可能链接是带本人的,大家要自己编译换成自己的.hex文件路径
在这里插入图片描述

万年历

  • 一、实验内容
  • 二、电路仿真图
  • 三、代码
  • 四、效果图
    • 1.开始
    • 2.日期
    • 3.温度
  • 五、最后

一、实验内容

设计定时器每50ms中断一次,在中断服务程序中,对中断次数进行计数,50ms计数20次,就是1秒,然后再对秒计数得到分的值,对分计数得到小时的值,分别将各值送到相应的段地址端口和位地址端口,通过数码管显示结果,达到电子时钟的计数效果。在计数的基础上,程序增加了按键程序,对电子时钟进行可调(对秒/分/时进行加1,此功能的增加使电子时钟功能更强、更实用,同理对日期也可以日/月/年进行加1。
a. 用AT89S51单片机的定时/计数器T0产生一秒的定时时间,作为秒计数时间。
b. 当一秒产生时,秒计数加1。
c. 开机时,显示00-00-00,并开始连续计时。计时满23-59-59时,返回00-00-00重新开始计时。
在以上设计基础上,在单片机的P1.0-P1.3口分别接入4个按键:
d. P1.0控制“秒”的调整,每按一次加1秒
e. P1.1控制“分”的调整,每按一次加1分
f. P1.2控制“时”的调整,每按一次加1时
g. P1.3用作功能选择键,在程序运行过程中如果按下功能选择键,则在年月日、时分秒和显示温度之间进行功能切换。

用AT89C52控制DS18B20,读取数据,并对DS18B20转换后的数据进行处理,最后在数码管上显示DS18B20测出的温度。
a.使用6位数码管显示测得的温度
b.最高位为符号位,如果温度值为正,不显示,如果温度为负,则显示负号
c.第2—4位显示温度值的整数部分,并在第4位数据上显示小数点
d.第5位显示小数部分
e.6,7位显示摄氏度符号“C”。

二、电路仿真图

这里我用的是ISIS Professional仿真,写代码用到是keil4
在这里插入图片描述
https://download.csdn.net/download/kushe123/19392394?spm=1001.2014.3001.5503,为方便懒人们这里加个我的仿真图原图,里面已经装载好了keil4的编译文件,但可能我电脑的路径跟你们不一样,所以需要自己编译替换。
在这里插入图片描述
这是图中所用到的元器件

三、代码

#include <reg51.h> //头文件unsigned char bitcode[] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f};  //选择LED位码
unsigned char code
pcode[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f}; //无小数点0~9
ncode[] = {0xbf, 0x86, 0xdb, 0xcf, 0xe6, 0xed, 0xfd, 0x87, 0xff, 0xef}; //有小数点0~9
unsigned char riqi[] = {2, 0, 2, 1, 0, 2, 0, 8};//在这里改日期
unsigned int key1=1,key2=1,key3=1,key4=1,year=0,month=0,day=0,d;
unsigned int bitcnt;
unsigned int flag = 0;
unsigned int s = 0,m = 0,h = 0;
unsigned int n = 0;
unsigned int bitcnt;
unsigned char Tools[] = {0x63, 0x39,0x40};sbit p10 = P1 ^ 0;
sbit p11 = P1 ^ 1;
sbit p12 = P1 ^ 2;
sbit p13 = P1 ^ 3;
sbit DQ = P2 ^ 4;void DATE();   //声明函数
void changed();
void runnian();
void delay();
void delay2(int z);
void time_init();
void button();
void jishu();
void delay3(unsigned int j);
void Init_DS18B20(void);
char ReadOneChar(void);
void WriteOneChar(unsigned char dat);
int ReadTemperature(void);
void display_tempmain(unsigned int i);void delay()
{int i, j;for (i = 0; i <= 10; i++)for (j = 0; j <= 20; j++);}void DATE() //日期
{for (bitcnt = 0; bitcnt < 8; bitcnt++){P3 = bitcode[bitcnt];if (bitcnt == 3 || bitcnt == 5)P0 = ncode[riqi[bitcnt]];elseP0 = pcode[riqi[bitcnt]];delay();runnian(); if(p10==0)        //判断天数按键是否按下key1=0;if (p10==1&&key1==0){riqi[7]+=1;key1=1;if (riqi[7]==10){riqi[7]=0;riqi[6]+=1;}if(day==d){riqi[6]=0;riqi[7]=1;riqi[5]+=1;}if(month==12&&day==31){riqi[5]=1;riqi[4]=0;riqi[3]+=1;}}if(p11==0)         //判断月份按键是否按下key2=0;if(p11==1&&key2==0){riqi[5]+=1;key3=1;if(riqi[5]==10){riqi[4]+=1;riqi[5]=0;}if(month==12){riqi[5]=1;riqi[4]=0;riqi[3]+=1;}key2=1;}if(p12==0)        //判断年份按键是否按下key3=0;if(p12==1&&key3==0){riqi[3]+=1;key3=1;if(riqi[3]==10){riqi[3]=0;riqi[2]+=1;}}}}void runnian(void) //判断是否为闰年
{year=riqi[0]*1000+riqi[1]*100+riqi[2]*10+riqi[3];month=riqi[4]*10+riqi[5];day=riqi[6]*10+riqi[7];if ((year%4==0)&&(year%100!=0)||(year%400==0)){if((month==1)||(month==3)||(month==5)||(month==7)||(month==8)||(month==10)||(month==10)||(month==12)){d=31;}if((month==4)||(month==6)||(month==9)||(month==11)){d=30;}if(month==2){d=28;}}else{if((month==1)||(month==3)||(month==5)||(month==7)||(month==8)||(month==10)||(month==10)||(month==12)){d=31;}if((month==4)||(month==6)||(month==9)||(month==11)){d=30;}if(month==2){d=29;}}
}
void delay2(int z)
{int x, y;for (x = z; x > 0; x--)for (y = 50; y > 0; y--);
}void time_init()      //定时器初始化
{TMOD = 0x01;TH0 = (65536 - 50000) / 256;TL0 = (65536 - 50000) % 256;EA = 1;TR0 = 1;ET0 = 1;
}void button()
{if (p10==0) //判断s按键是否按下key1=0;if (p10==1&&key1==0)     {s++;key1=1;} if (p11==0) //判断m按键是否按下key2=0;if (p11==1&&key2==0)     {m++;key2=1;} if (p12==0) //判断h按键是否按下key3=0;if (p12==1&&key3==0)     {h++;key3=1;}
}void jishu()
{for (bitcnt = 0; bitcnt < 8; bitcnt++){P3 = bitcode[bitcnt];button();if(P3==0xfe)P0=pcode[h/10];     //取小时的十位else if(P3==0xfd)P0=pcode[h%10];     //取小时的个位else if(P3==0xfb)P0=0x40;        //取段码显示为-else if(P3==0xf7)  //取分的十位P0=pcode[m/10];else if(P3==0xef)    //取分的个位P0=pcode[m%10];else if(P3==0xdf)P0=0x40;        //取段码显示为-else if(P3==0xbf)  //取秒的十位P0=pcode[s/10] ;else if(P3==0x7f)    //取秒的个位P0=pcode[s%10];delay();}
}void delay3(unsigned int j)
{while (j--);
}void Init_DS18B20(void)
{unsigned char x = 0;DQ = 1;delay3(8);DQ = 0;delay3(80);DQ = 1;delay3(14);x = DQ;delay3(20);
}char ReadOneChar(void)
{unsigned char i = 0;unsigned char dat = 0;for (i = 8; i > 0; i--){DQ = 0;dat >>= 1;DQ = 1;if (DQ)dat |= 0x80;delay3(4);}return (dat);
}void WriteOneChar(unsigned char dat)
{unsigned char i = 0;for (i = 8; i > 0; i--){DQ = 0;DQ = dat & 0x01;delay3(5);DQ = 1;dat >>= 1;}delay3(4);
}int ReadTemperature(void)    //读取温度
{unsigned char a = 0;unsigned char b = 0;unsigned int t = 0;Init_DS18B20();WriteOneChar(0xCC);WriteOneChar(0x44);Init_DS18B20();WriteOneChar(0xCC);WriteOneChar(0xBE);a = ReadOneChar();b = ReadOneChar();t = b << 8;t = t | a;return (t);
}void display_tempmain(unsigned int i) //显示温度
{float temp;unsigned char xiaoshu;unsigned int zhengshu;if ((0xf000 & i) == 0xf000){i = ~i + 1;P0 = 0x00;if((zhengshu % 100 / 10)==0){P0 = Tools[2];P3 = 0xfb;}else{P0 = Tools[2];P3 = 0xfd;}delay3(500);}temp = (0x000f & i) * 10.0 * 0.0625;xiaoshu = temp;zhengshu = i >> 4;P0 = 0x00;if((zhengshu / 100)==0)      //温度百位{delay3(500);P3 = 0xff;}else{P0 = pcode[zhengshu / 100];P3 = 0xfd;}if((zhengshu / 100)==0&&(zhengshu % 100 / 10)==0)   //温度十位{delay3(500);P3 = 0xff;}else{P0 = pcode[zhengshu % 100 / 10];    P3 = 0xfb;} delay3(500);P0 = 0x00;P0 = pcode[zhengshu % 100 % 10] | ~0x7f;   //温度个位P3 = 0xf7;delay3(500);P0 = 0x00;P0 = pcode[xiaoshu];  //小数P3 = 0xef;delay3(500);P0 = 0x00;P0 = Tools[0];     //度P3 = 0xdf;delay3(500);P0 = 0x00;P0 = Tools[1];    //摄氏度CP3 = 0xbf;delay3(500);P3 = 0xff;
}void changed()     //判断按键是否按下
{if (flag == 0){while (flag == 0){jishu();if (p13 == 0)    //判断转换键是否按下            key4=0;if (p13==1&&key4==0){                      flag++;key4=1;}}}else if (flag == 1)while (flag == 1){DATE();if (p13 == 0)    //判断转换键是否按下            key4=0;if (p13==1&&key4==0){                      flag++;key4=1;}}else if (flag == 2){unsigned int temp;while (flag == 2) //涓诲惊鐜?{temp = ReadTemperature();display_tempmain(temp);if (p13 == 0)    //判断转换键是否按下            key4=0;if (p13==1&&key4==0){                      flag=0;key4=1;}}}}
void main(void)
{time_init();while (1){changed();}
}void timer() interrupt 1  //1s中断
{TH0 = (65536 - 50000) / 256;TL0 = (65536 - 50000) % 256;n++;if (n == 20)  {n = 0;s++;if (s == 60)//{s = 0;m++;}if (m == 60){m = 0;h++;}if (h == 24){h = 0;}}
}

四、效果图

如果你图画对,代码没问题,hex文件也没问题,程序运行应该如下图所示:

1.开始

从00-00-00开始计时,充当计时器
在这里插入图片描述
在这里插入图片描述
这是按键的功能,比如在刚开始的计时器状态,第一个(从上到下)就+1s,第二个+1m,第三个+1h,第四个就是切换led显示状态,按下就切换到日期,再按下就切换到温度,在按下就又切换到显示计时器的状态。简单的说就是(计时-日期-温度)循环.
注意:按下切换功能按键后计时不会停止,而是在后台继续计时。

2.日期

在这里插入图片描述
注意:这里日期是代码里改的固定的,不会随系统日期的,同样按左边的按键可以实现+天,+月,+年

3.温度

在这里插入图片描述
注意:温度是读取DS18B20的数据来显示的,也就是改变DS18B20的温度,就可以改变显示的温度,所以左边的按键对这个是无效的,只有第四个切换功能的按键有用,按一下就切换到计时的去了

如下图改成4摄氏度(按那两个红色按钮调温度):
在这里插入图片描述

五、最后

希望能对你有用!!

当然还有最重要的事,麻烦各位大佬给个三连,毕竟码字不容易。
如果三连不行就点个赞吧(卑微)。
在这里插入图片描述


http://chatgpt.dhexx.cn/article/qgI2MnGt.shtml

相关文章

基于AT89C51单片机的电子万年历系统

点击链接获取Keil源码与Project Backups仿真图&#xff1a; https://download.csdn.net/download/qq_64505944/87708258 源码获取 主要内容&#xff1a; 电子万年历系统以实时时钟芯片DS1302和AT89C52单片机为主要研究对象&#xff0c;着重进行51单片机控制系统的设计研究和如…

c51单片机时钟c语言程序设计,AT89C51单片机为核心的时钟电路的程序设计

当前位置:电工之家 > 电工知识 > 单片机 > 正文 AT89C51单片机为核心的时钟电路的程序设计 时间:2018-06-05 08:38 来源:电工之家 AT89C51单片机为核心的时钟电路的程序设计 1.主程序设计及系统主流程图 设计中采用定时器T0中断完成,其余状态循环调用显示子程序。系…

AT89C51单片机

目录 一、AT89S51单片机的I/O端口二、AT89S51单片机的中断系统  1、中断处理过程  2、AT89S51单片机的中断源&#xff08;2&#xff09;AT89S51单片机的中断控制&#xff08;3&#xff09;AT89S51单片机的中断优先级&#xff08;4&#xff09;AT89S51单片机中断系统的结构&…

89c51c语言程序,AT89C51单片机流水灯c语言程序及详解

许多朋友不知道怎么用C语言编程实现AT89C51单片机流水灯&#xff0c;这里给大家讲解一下。 首先将单片机的头函数导入。 #include"reg51.h" 定义单片机P1口的8个管脚&#xff0c;使其分别代表流水灯的8个led。 sbit p0P1^0; sbit p1P1^1; sbit p2P1^2; sbit p3P1^3; …

keil ISIS AT89C51单片机

突然想起大学时候学习的知识&#xff0c;最近空余时间较多&#xff0c;想回顾一下&#xff0c;然后发现连最简单的编辑器的名字都快忘记了&#xff0c;于是赶紧抓紧时间复习一遍&#xff0c;在此记录一下这个过程遇到的问题。 首先是对于keil的安装&#xff0c;我是直接从网上…

AT89C51单片机性能介绍

AT89C51是一种带4K字节闪烁可编程可擦除只读存储器&#xff08;FPEROM—Falsh Programmable and Erasable Read Only Memory&#xff09;的低电压&#xff0c;高性能CMOS8位微处理器&#xff0c;俗称单片机。该器件采用ATMEL高密度非易失存储器制造技术制造&#xff0c;与工业标…

微机基础与89C51单片机部分知识

1&#xff0c;微机基础知识 微机: 具有完整运算及控制能力的计算机。包括微处理器&#xff0c;储存器&#xff0c;接口适配器&#xff0c;输入输出设备。 微处理器&#xff1a; 控制器&#xff1a;由程序计数器&#xff0c;指令寄存器&#xff0c;指令译码器&#xff0c;时序发…

基于AT89C51单片机的计算器设计

点击链接获取Keil源码与Project Backups仿真图: https://download.csdn.net/download/qq_64505944/87772564 源码获取 主要内容: 本设计是基于51系列的单片机进行的设计,可以完成计算器的键盘输入,进行加、减、3位无符号数字的简单运算,并在LED上相应的显示结果。设计过…

基于 AT89C51 单片机的数字时钟设计

目录 1.设计目的、作用 2.设计要求 3.设计的具体实现 3.1 设计原理 3.2 硬件系统设计 3.2.1 AT89C51 单片机原理 3.2.2 晶振电路设计 3.2.3 复位电路设计 3.2.4 LED 数码管显示 3.3 系统实现 3.3.1 系统仿真与调试 3.3.2 演示结果 4.总结 附录 附录 1 附录 2 1.…

89C51单片机之寄存器

文章目录 片内RAM中的寄存器内容介绍 低128字节片内RAM4组工作寄存器 高128字节片内RAM&#xff08;SFR区&#xff09;部分特殊功能寄存器累加器 ACC寄存器 B程序状态寄存器 PSW栈指针 SP数据指针 DPTRI/O端口 P0~P3 中断系统中的特殊寄存器定时器控制寄存器 TCON 之中断定时器…

【89c51汇编语言】51单片机结构及其原理

单片机结构及其原理 51单片机的内部结构单片机CPU控制器控制器&#xff1a;程序计数器&#xff1a;PC 控制器&#xff1a;数据指针寄存器&#xff1a;DPTR运算器累加器APSW程序状态字CY&#xff08;PSW.7&#xff09;进位标志AC&#xff08;PSW.6&#xff09;辅助进位标志RS1和…

89c51单片机

89c51是一款很大众化的入门级单片机&#xff0c;ATMEL、NXP、STC、和SST等公司生产的与80c51兼容低功耗、高性能8位89c51/s51单片机具有比80c31更丰富的外设资源。 89c51/s51单片机芯片内包括&#xff1a; ①一个8位的80c51微处理器&#xff08;CPU&#xff09; ②片内256字…

关于会话(session),你应该了解这些

一、什么是会话 会话Session代表的是客户端与服务器的一次交互过程&#xff0c;这个过程可以是连续也可以是时断时续的。在Servlet中&#xff08;jsp&#xff09;&#xff0c;一旦用户与服务端交互&#xff0c;服务器tomcat就会为用户创建一个session&#xff0c;同时前端会有…

ZooKeeper客户端源码(一)——向服务端建立连接+会话建立+心跳保持长连接

首发CSDN&#xff1a;徐同学呀&#xff0c;原创不易&#xff0c;转载请注明源链接。我是徐同学&#xff0c;用心输出高质量文章&#xff0c;希望对你有所帮助。 一、从ZooKeeper实例初始化开始 ZooKeeper 提供了原生的客户端库&#xff0c;虽然不好用&#xff0c;但是能够更好…

会话劫持安全攻击

什么是会话劫持&#xff1f; TCP 会话劫持是对受保护网络上的用户会话的安全攻击。会话劫持最常见的方法称为 IP 欺骗&#xff0c;攻击者使用源路由 IP 数据包将命令插入网络上两个节点之间的活动通信中&#xff0c;并将自己伪装成经过身份验证的用户之一。这种类型的攻击是可能…

HTML sessionStorage会话存储

sessionStorage会话存储 sessionStorage 是HTML5新增的一个会话存储对象&#xff0c;用于临时保存同一窗口(或标签页)的数据&#xff0c;在关闭窗口或标签页之后将会删除这些数据。本篇主要介绍 sessionStorage(会话存储)的使用方式。包括添加、修改、删除等操作。 目录 1. 介…

【windows】会话(Session)、窗口站(WindowsStation)、桌面、窗口

序 一个系统可以同时登录多个用户(包括远程用户登录)&#xff08;多用户系统&#xff09;。 一个用户拥有一个会话&#xff08;远程用户被称为远程会话&#xff09;。 一个会话拥有多个工作站和窗口。只能拥有一个交互式工作站(Winsta0)。&#xff08;Window Station 0…

WindTerm导出会话

WindTerm的session配置并无法被适用于其他软件中&#xff0c;所有的session保存在WindTerm安装路径下的profiles文件夹内&#xff0c;如果需要更新版本或回退&#xff0c;将所安装的版本覆盖即可&#xff0c;或是将profiles复制于新路径下。 图标闪烁设置、会话保存-导入导出 …

Spring Security中的会话【Session】管理与防御以及会话的并发控制

众所周知&#xff0c;HTTP本身是没有任何关于当前用户状态的内容&#xff0c;也就是两个HTTP请求之间是没有任何的关联可言&#xff0c;用户在和服务器交互的过程中&#xff0c;站点无法确定是哪个用户访问&#xff0c;也因此不能对其提供相应的个性化服务。Session的诞生就是为…

web基础:会话

一、会话概述 HttpSession对象可以保存跨同一个客户多个请求的会话状态。即与一个特定客户的整个会话期间&#xff0c;HttpSession会持久存储。对于会话期间客户做的所有请求&#xff0c;从中得到的所有信息&#xff0c;都可以使用HttpSession对象保存。 会话的工作方式&#…