51单片机实验04 -数码管的动态显示实验

目录

一、实验目的

二、实验内容

三、实验原理

四、实验方法

五,实验效果及代码

1,效果

2,代码

六,课后习题

1,使用定时器T0的中断函数1 从999999~0计时

 1)效果

2)代码

2,使用定时器T1的中断函数3 从999999~0计时

1)效果 

2)代码


一、实验目的


1、熟悉掌握数码管动态显示的基本方法。
2、根据已知电路和设计要求在实验板上实现数码管动态显示。
3、掌握利用定时器T0中断的使用方法。


二、实验内容

在KST-51开发板上,选择任意左右相连的4位数码管,利用定时器T0中断实现动态显示0123→1234→2345→3456→4567→5678→6789→7890→8901→9012→0123→不断反复,每隔2s切换显示内容


三、实验原理


实验要求“4位数码管上实现动态显示

0123→1234→2345→3456→4567→5678→6789→7890→8901→9012→0123→不断反复,每隔2s切换显示内容”。动态扫描可以实现该要求。

简单地说,动态扫描就是选通一位,送一位数据。原理图中的LEDS0-LEDS5是相应数码管的位选信号,即选择哪个数码管显示数字;P0.0-P0.7是段码,即要显示的数字。可以通过依次选通某一位7段数码管并通过P0端口送出显示数据。由于人眼的视觉残留原理,如果这种依次唯一选通每一位7段数码管的动作在10ms内完成,就会造成多位数码管同时点亮显示各自数字的假象。
本实验使用定时器T0中断,实现每2s更新一次数字。

定时器有关代码请看前面文章:

51单片机实验03-单片机定时/计数器实验-CSDN博客


四、实验方法


1、根据电路图,分析和掌握数码管动态显示的原理,选择4位数码管。使用定时器T0中断实现每2秒更新一次数字的设计思路。
本次实验使用Timer0中断,由于其定时时间最大为65536us,不能实现2s的长延时,那么可以使用多次中断来实现,并且在中断到来时,不断地死循环显示数字,即根据动态显示原理“选通一位,来一位数据”。设x表示千位的数字,由于最大的数字为9,则(x%10)、(x+1)%10、(x+2)%10、(x+3)%10分别是千位、百位、十位、个位上的数字。在编写代码时,设置Timer0定时时间为2ms,可以用一个参数cnt计算中断的次数;当中断的次数达到1000次时,说明已经达到了2s,此时更新数字,即将数字x自增1。
2、针对要求,画出程序流程图,根据流程图进行代码编写。
3、编译调试生成HEX文件,进行代码烧写,完成数码管动态显示功能。


五,实验效果及代码

我选择的是中间四个数码管,如果想要选择其它数码管的,可以修改这几行代码:

addr2,addr1,addr0分别控制了138译码器的输出y0~y6,因为y6已经用来控制发光二极管 ,因此,y0~y5就是用来控制数码管的。例如,y0控制最右边的数码管leds0,对应的138译码器输入:

addr2=0;addr1=0;addr0=0;

如果想要控制最左边的数码管,就需要y5输出低电平。即addr2=1;addr1=0;addr0=1;

1,效果

0123-1234等数字的循环显示

2,代码

#include<reg52.h>
sbit enled=P1^4;   // 138译码器使能  
sbit addr3=P1^3;
sbit addr2=P1^2;
sbit addr1=P1^1;
sbit addr0=P1^0;  // 使能端					  unsigned  char  code ledChar[]={	 // 晶体管0~9真值表0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90
//,0x88,0x83,0xC6,0xA1,0x86,0x8E
};unsigned char ledBuff[]={    // 晶体管全灭0xFF,0xFF,0xFF,0xFF};		 unsigned int outflow=0;  // 记录定时器溢出次数unsigned char  ind=0;  // 动态扫描的索引unsigned char flags=0;  // 2s定时标志
void  main(){unsigned long sectransistor=0;  // 记录数码管显示的秒数enled=0;addr3=1;TMOD=0x01;  // 定时器T0选择模式1(16位定时器)TH0=0xFC;   // 定时器的初始值TL0=0x67; EA=1;   //总中断打开ET0=1;  // 定时器0使能中断打开TR0=1;      // 定时器T0运行while(1){  	 // 写好定时器中断服务后再使用while循环if(flags==2){	 // flags是2s定时flags=0;   // 重新计时,直到flags再次等于1(时间再次为2s)ledBuff[0]=ledChar[(sectransistor+3)%10];	 ledBuff[1]=ledChar[(sectransistor+2)%10];ledBuff[2]=ledChar[(sectransistor+1)%10];  // 0+1对10取余为1 ,10对10取余为0ledBuff[3]=ledChar[sectransistor%10]; // 最左边的晶体管数值最小0sectransistor++;  // 秒数自增}}}void  InterruptTimer0() interrupt 1{	  // 定时器T0中断服务函数1TH0=0xFC;   // 定时器初始值TL0=0x67; outflow++;	// 溢出自增if(outflow==2000){		 //每隔2s切换显示内容outflow=0;flags=2;  // 2s到了之后,flags立起来}P0=0xFF;  // 关闭段switch(ind){   // 控制指定晶体管亮起case 0:addr2=0;addr1=0;addr0=1;ind++;P0=ledBuff[0];break;case 1:addr2=0;addr1=1;addr0=0;ind++;P0=ledBuff[1];break;case 2:addr2=0;addr1=1;addr0=1;ind++;P0=ledBuff[2];break;case 3:addr2=1;addr1=0;addr0=0;ind=0;P0=ledBuff[3];break;default: break;}}

六,课后习题

 需要知道的是,使用不同的定时器,所对应的中断函数也是不一样的,如下表中所示👇

 可以看到,定时器T0的中断函数编号是1 ,而定时器T1的中断函数3,因此在写程序的时候需要正确更改interrupt后面的编号。

1,使用定时器T0的中断函数1 从999999~0计时

 1)效果

效果同T1定时器👇:

定时器T1使用中断函数从999999~0计时

2)代码

#include<reg52.h>
sbit enled=P1^4;   // 138译码器使能  
sbit addr3=P1^3;
sbit addr2=P1^2;
sbit addr1=P1^1;
sbit addr0=P1^0;  // 使能端					  
//	unsigned  char  code ledChar[]={	 // 晶体管真值表
//0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
//0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E
//};//倒计时	    0x8E,0x86,0xA1,0xC6,0x83,0x88,  unsigned char  code ledChar[]={	  // 从数值9开始		  0x90,0x80,0xF8,0x82,0x92,0x99,0xB0,0xA4,0xF9,0xC0};unsigned char ledBuff[]={    // 晶体管全灭0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF};		 unsigned int outflow=0;  // 记录定时器溢出次数unsigned char  ind=0;  // 动态扫描的索引unsigned char flags=0;  // 1s定时标志
void  main(){unsigned long sectransistor=0;  // 记录数码管显示的秒数
//  0~999999enled=0;addr3=1;TMOD=0x01;  // 定时器T0选择模式1TH0=0xFC;   // 定时器的初始值TL0=0x67; EA=1;   //总中断打开ET0=1;  // 定时器0使能中断打开TR0=1;      // 定时器T0运行while(1){  	 // 写好定时器中断服务后再使用while循环if(flags==1){	 // flags是1s定时flags=0;   // 重新及时,直到flags再次等于1ledBuff[0]=ledChar[sectransistor%10];	 // 开启指定晶体管	ledBuff[1]=ledChar[sectransistor/10%10];ledBuff[2]=ledChar[sectransistor/100%10];ledBuff[3]=ledChar[sectransistor/1000%10];ledBuff[4]=ledChar[sectransistor/10000%10];ledBuff[5]=ledChar[sectransistor/100000%10];sectransistor++;  // 数码管在之前的基础上+1s}}}void  InterruptTimer0() interrupt 1{	  // 定时器T0中断服务函数1TH0=0xFC;   // 定时器初始值TL0=0x67; outflow++;	// 溢出自增if(outflow==1000){		 //1soutflow=0;flags=1;  // 1s到了之后,flags立起来}P0=0xFF;  // 关闭段switch(ind){   // 控制指定晶体管亮起case 0:addr2=0;addr1=0;addr0=0;ind++;P0=ledBuff[0];break;case 1:addr2=0;addr1=0;addr0=1;ind++;P0=ledBuff[1];break;case 2:addr2=0;addr1=1;addr0=0;ind++;P0=ledBuff[2];break;case 3:addr2=0;addr1=1;addr0=1;ind++;P0=ledBuff[3];break;case 4:addr2=1;addr1=0;addr0=0;ind++;P0=ledBuff[4];break;	case 5:addr2=1;addr1=0;addr0=1;ind=0;P0=ledBuff[5];break;default: break;}}

2,使用定时器T1的中断函数3 从999999~0计时

1)效果 

定时器T1使用中断函数从999999~0计时

2)代码

#include<reg52.h>
sbit enled=P1^4;   // 138译码器使能  
sbit addr3=P1^3;
sbit addr2=P1^2;
sbit addr1=P1^1;
sbit addr0=P1^0;  // 使能端					  
//	unsigned  char  code ledChar[]={	 // 晶体管真值表
//0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
//0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E
//};//倒计时	    0x8E,0x86,0xA1,0xC6,0x83,0x88,unsigned char  code ledChar[]={0x90,0x80,0xF8,0x82,0x92,0x99,0xB0,0xA4,0xF9,0xC0};unsigned char ledBuff[]={    // 晶体管全灭0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF};		 unsigned int outflow=0;  // 记录定时器溢出次数unsigned char  ind=0;  // 动态扫描的索引unsigned char flags=0;  // 1s定时标志
void  main(){unsigned long sectransistor=0;  // 记录数码管显示的秒数
//  0~999999enled=0;addr3=1;TMOD=0x10;  // 定时器T1选择模式1TH1=0xFC;   // 定时器初始值TL1=0x67; EA=1;   //总中断打开ET1=1;  // 定时器1使能中断打开TR1=1;      // 定时器运行while(1){  	 // 写好定时器中断服务后再使用while循环if(flags==1){	 // flags是1s定时flags=0;   // 重新及时,直到flags再次等于1ledBuff[0]=ledChar[sectransistor%10];	 // 开启指定晶体管	ledBuff[1]=ledChar[sectransistor/10%10];ledBuff[2]=ledChar[sectransistor/100%10];ledBuff[3]=ledChar[sectransistor/1000%10];ledBuff[4]=ledChar[sectransistor/10000%10];ledBuff[5]=ledChar[sectransistor/100000%10];sectransistor++;  // 数码管在之前的基础上+1s}}}void  InterruptTimer1() interrupt 3{	  // 定时器0中断服务函数TH1=0xFC;   // 定时器初始值TL1=0x67; outflow++;	// 溢出自增if(outflow==1000){		 //1soutflow=0;flags=1;  // 1s到了之后,flags立起来}P0=0xFF;  // 关闭段switch(ind){   // 控制指定晶体管亮起case 0:addr2=0;addr1=0;addr0=0;ind++;P0=ledBuff[0];break;case 1:addr2=0;addr1=0;addr0=1;ind++;P0=ledBuff[1];break;case 2:addr2=0;addr1=1;addr0=0;ind++;P0=ledBuff[2];break;case 3:addr2=0;addr1=1;addr0=1;ind++;P0=ledBuff[3];break;case 4:addr2=1;addr1=0;addr0=0;ind++;P0=ledBuff[4];break;	case 5:addr2=1;addr1=0;addr0=1;ind=0;P0=ledBuff[5];break;default: break;}}

有问题请在评论区留言,一天8h在线。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/819484.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

配置linux的oracle 21c启停服务

一、配置启停 1、使用root用户登陆 su - root 2、修改oratab文件 修改oratab文件&#xff0c;将红框里面的N改为“Y”&#xff0c;使启停脚本能够生效 vi /etc/oratab 3、验证 配置好后就能够使用 dbshut 停止服务 和 dbstart 启动服务 了 2.1启动服务 su - oracle dbstart…

什么是线程?线程和进程谁更弔?

第一个参数是所创建进程的pid。 第二个是线程的属性。 第三个参数是返回值为void*&#xff0c;参数也为void*的函数指针。 第四个参数是给第三个参数的参数&#xff0c;也就是给给函数传参。 #include<iostream> #include<pthread.h> #include<unistd.h>…

折叠面板组件(vue)

代码 <template><div class"collapse-info"><div class"collapse-title"><div class"title-left">{{ title }}</div><div click"changeHide"> <Button size"small" v-if"sho…

生产计划和排单管理怎么做

阅读本文&#xff0c;你将了解到&#xff1a;1、企业是如何制定生产计划和进行排单管理&#xff1f; 2.企业在执行生产计划和进行排单管理过程中会遇到那些问题&#xff1f; 3.企业如何高效利用工具去解决问题&#xff1f; 一、生产计划和排单管理是什么 1.生产计划和排单管理…

【uniapp】【uview2.0】【u-sticky】Sticky 吸顶

把pages.json文件中的 “navigationStyle"设置为"custom”, 出现的问题是&#xff0c;莫名奇妙多了个 一个高度 解决方法 /* 使用CSS的sticky定位 */ .sticky {/* #ifdef H5 */ position: -webkit-sticky;position: sticky;top: 0; /* 设置距顶部的距离 */z-ind…

[Python开发问题] Selenium ERROR: Unable to find a matching set of capabilities

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

在Spring Boot实战中碰到的拦截器与过滤器是什么?

在Spring Boot实战中&#xff0c;拦截器&#xff08;Interceptors&#xff09;和过滤器&#xff08;Filters&#xff09;是两个常用的概念&#xff0c;它们用于在应用程序中实现一些通用的逻辑&#xff0c;如日志记录、权限验证、请求参数处理等。虽然它们都可以用于对请求进行…

最大子树和(遇到的题)

题目是给出一个树&#xff0c;求其中最大的权值块 题解&#xff1a; #include <bits/stdc.h> using namespace std; const int N1e59; int dp[N]; //dp[i]表示第i结点为根最大权值 int w[N]; //记录每个结点的权值 int n; //点的数量 int t; //样例个数 …

Ubuntu安装VMVare Workstation pro 17.5.1

由于需要装Kali&#xff0c;我电脑是Ubuntu单系统&#xff0c;所以只能使用linux版本的虚拟机&#xff0c;通过这种方式来安装虚拟机和Kali镜像。 参考CSDN博客资料&#xff1a;https://blog.csdn.net/xiaochong0302/article/details/127420124 github代码资料&#xff1a;vm…

程序运行在 STM32H750 的外扩 FLASH 上两小时后死机

1. 问题现象 客户使用 STM32H750VBT6&#xff0c;通过 QSPI 外扩了一个 4M 的 NOR FLASH&#xff0c;采用memory map 模式。当程序跳转运行到外设 FLASH 后&#xff0c;大约两个小时后程序死机。 客户使用的 IDE 是 KEIL&#xff0c;此问题可以固定重现。 在 KEIL 调试模式下…

百货商场用户画像描绘and价值分析(下)

目录 内容概述数据说明技术点主要内容4 会员用户画像和特征字段创造4.1 构建会员用户基本特征标签4.2 会员用户词云分析 5 会员用户细分和营销方案制定5.1 会员用户的聚类分析及可视化5.2 对会员用户进行精细划分并分析不同群体带来的价值差异 内容概述 本项目内容主要是基于P…

Springboot+Vue项目-基于Java+MySQL的免税商品优选购物商城系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

【Qt】常用控件(LCD Number/进度条/日历)

需要云服务器等云产品来学习Linux可以移步/-->腾讯云<--/官网&#xff0c;轻量型云服务器低至112元/年&#xff0c;新用户首次下单享超低折扣。 目录 一、LCD Number(LCD显示器) 一个倒计时程序 二、ProgressBar(进度条) 1、创建一个进度条&#xff0c;100ms进度增加…

✌粤嵌—2024/3/14—判断子序列

代码实现&#xff1a; 方法一&#xff1a;一次遍历 bool isSubsequence(char *s, char *t) {if (strlen(s) 0) {return true;}int i 0;for (int j 0; j < strlen(t); j) {if (s[i] t[j]) {i;}if (i strlen(s)) {return true;}}return false; } 方法二&#xff1a;动态规…

5.2 mybatis之autoMappingBehavior作用

文章目录 1. NONE关闭自动映射2. PARTIAL非嵌套结果映射3. FULL全自动映射 众所周知mybatis中标签< resultMap >是用来处理数据库库字段与java对象属性映射的。通常java对象属性&#xff08;驼峰格式&#xff09;与数据库表字段&#xff08;下划线形式&#xff09;是一 一…

基于SSM项目个人健康信息管理系统

采用技术 基于SSM项目个人健康信息管理系统的设计与实现~ 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringMVCMyBatis 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 页面展示效果 用户端 用户首页 健康知识 用户注册 医院推荐信息 系统概要…

【LeetCode热题100】【矩阵】螺旋矩阵

题目链接&#xff1a;54. 螺旋矩阵 - 力扣&#xff08;LeetCode&#xff09; 先走外面的圈再走里面的圈&#xff0c;可以用递归来解决&#xff0c;对于要走的一个圈&#xff0c;由四个角决定&#xff0c;其实是三个数&#xff0c;&#xff08;0&#xff0c;0&#xff09;&…

Vue.js前端开发零基础教学(五)

目录 4.1 动态组件 4.1.1 定义动态组件 4.1.2 利用KeepAlive组件实现组件缓存 4.1.3 组件缓存相关的生命周期函数 4.1.4 KeepAlive组件的常用属性 4.2 插槽 4.2.1 什么是插槽 ​编辑 4.2.2 具名插槽 4.2.3 作用域插槽 4.3 自定义指令 4.3.1 什么是自定义指令…

使用美化方法设计嵌入的子窗体(三)

使用美化方法设计嵌入的子窗体 分析效果图的实现 效果图&#xff1a; 新建 Windows 窗体 新窗体命名&#xff1a;FrmAddProduct.cs修改窗体的 Text 属性&#xff1a;新增商品修改窗体的位置&#xff1a;StartPosition&#xff1a;CenterScreen窗体的无边框设计&#xff1a…

MySQL 8.0.19安装教程(windows 64位)

在c盘目录下的Program Files目录下创建MySQL目录&#xff0c;将下载好的mysql解压到里面 解压完是这个样子 配置初始化的my.ini文件的文件 [mysqld] # 设置3306端口 port3306 # 设置mysql的安装目录 basedirC:\Program Files\MySQL # 设置mysql数据库的数据的存放目录 datad…