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

news2024/10/7 20:29:53

目录

一、实验目的

二、实验内容

三、实验原理

四、实验方法

五,实验效果及代码

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取余为0
		ledBuff[3]=ledChar[sectransistor%10]; // 最左边的晶体管数值最小0
		sectransistor++;  // 秒数自增
		
		}
	
	}
	
		}

	void  InterruptTimer0() interrupt 1{	  // 定时器T0中断服务函数1
	TH0=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~999999
    enled=0;
	addr3=1;
	TMOD=0x01;  // 定时器T0选择模式1
	TH0=0xFC;   // 定时器的初始值
	TL0=0x67; 

	EA=1;   //总中断打开
	ET0=1;  // 定时器0使能中断打开

	TR0=1;      // 定时器T0运行
	while(1){  	 // 写好定时器中断服务后再使用while循环
		if(flags==1){	 // flags是1s定时
		 flags=0;   // 重新及时,直到flags再次等于1
		ledBuff[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中断服务函数1
	TH0=0xFC;   // 定时器初始值
	TL0=0x67; 
	outflow++;	// 溢出自增
	if(outflow==1000){		 //1s
	   outflow=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~999999
    enled=0;
	addr3=1;
	TMOD=0x10;  // 定时器T1选择模式1
	TH1=0xFC;   // 定时器初始值
	TL1=0x67; 

	EA=1;   //总中断打开
	ET1=1;  // 定时器1使能中断打开

	TR1=1;      // 定时器运行
	while(1){  	 // 写好定时器中断服务后再使用while循环
		if(flags==1){	 // flags是1s定时
		 flags=0;   // 重新及时,直到flags再次等于1
		ledBuff[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){		 //1s
	   outflow=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.coloradmin.cn/o/1607172.html

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

相关文章

OpenHarmony开发实例:【仿桌面应用】

介绍 本示例实现了一个简单桌面应用&#xff0c;实现了以下几点功能&#xff1a; 1.展示了系统安装的应用&#xff0c;实现点击启动、应用上滑弹出卡片、卡片添加到桌面、卡片移除功能。 2.实现桌面数据持久化存储&#xff0c;应用支持卸载、监听应用卸载和安装并显示。 3.…

Arcgis Pro2.5安装教程(内含安装文件)

​最近处理的数据量大&#xff0c;发现arcmap这种老产品属实是不行了&#xff0c;相比于下一代的Arcgis Pro,不但运行速度慢&#xff0c;也容易遇到突然关闭的问题&#xff0c;之前基于团队的选择也没办法&#xff0c;最近实在是被数据搞得无语了&#xff0c;一鼓作气装上了Arc…

武汉星起航:亚马逊上的中国智慧,创新与差异化策略赢得全球赞誉

在全球电商的浪潮中&#xff0c;亚马逊作为行业的佼佼者&#xff0c;为众多商家提供了一个展示自我、实现价值的舞台。在这其中&#xff0c;中国商家以其独特的创新和差异化策略&#xff0c;逐渐在亚马逊平台上崭露头角&#xff0c;赢得了全球消费者的青睐。 中国商家在亚马逊…

新手入门:大语言模型训练指南

在这个信息爆炸的时代&#xff0c;人工智能技术正以前所未有的速度渗透到我们生活的方方面面。从智能手机上的语音助手到自动驾驶汽车&#xff0c;AI的应用无处不在。而在这些令人惊叹的技术背后&#xff0c;大语言模型&#xff08;LLM&#xff09;扮演着至关重要的角色。它们不…

(六)Pandas文本数据 学习简要笔记 #Python #CDA学习打卡

一. 文本数据简介 1&#xff09;定义 指不能参与算术运算的任何字符&#xff0c;也称为字符型数据。如英文字母、汉字、不作为数值使用的数字(以单引号开头)和其他可输入的字符。 文本数据虽不能参加算术运算&#xff0c;但其具有纬度高、量大且语义复杂等特点&#xff0c;因…

企业微信扫码登录遇到的bug及解决办法

企业微信自建应用扫码登录 1.基本配置 1.登录企业微信管理系统&#xff0c;新建一个自建应用 2.点击你新建的应用&#xff0c;拿到AgentId 3.在我的企业页面拿到appid 4.配置可信域名 5.配置授权回调域 写到这&#xff0c;基本配置已完成&#xff0c;可以开始写前端代码 …

【高级RAG技巧】在大模型知识库问答中增强文档分割与表格提取

前言 文档分割是一项具有挑战性的任务&#xff0c;它是任何知识库问答系统的基础。高质量的文档分割结果对于显著提升问答效果至关重要&#xff0c;但是目前大多数开源库的处理能力有限。 这些开源的库或者方法缺点大致可以罗列如下&#xff1a; 只能处理文本&#xff0c;无法…

MySql8快速迁移版的制作过程

首先说明&#xff0c;mysql 8的安装不同与mysql5.x。 做程序的朋友都知道&#xff0c;程序好做&#xff0c;客户难伺候&#xff0c;因为限于用户的情况&#xff0c;如何能让用户把程序运行起来很关键&#xff0c;比如日前我在做 山东高中信息技术 学考 考前练习 系统时&#x…

解决 vue install 引发的 failed Error: not found: python2 问题

发生 install 异常时&#xff0c;提示信息如下所示&#xff1a; npm ERR! code 1 npm ERR! path U:\cnblogs\fanfengping-dtops\fanfengping-dtops-front\node_modules\node-sass npm ERR! command failed npm ERR! command U:\Windows\system32\cmd.exe /d /s /c node scripts…

苍穹外卖学习笔记(5.微信登录,商品浏览)

目录 一、微信登录1、封装HttpClient工具类2、导入小程序代码3、微信登录流程4、需求分析设计5、代码开发6、功能测试 二、商品浏览1、需求分析设计2、代码开发1.查询分类2.根据分类id查询套餐3.根据分类id查询套餐&#xff0c;根据套餐id查询包含菜品 3、测试 四、相关知识1、…

Django模型的字段类型

Django模型中最重要并且也是唯一必须执行的就是字段定义。字段在类中进行定义&#xff0c;对应于实体数据库的字段。另外&#xff0c;定义模型字段名时为了避免冲突&#xff0c;不建议使用模型API中已经定义的关键字。 字段类型用以指定数据库的数据类型&#xff0c;例如Integ…

python入门之简洁安装VS保姆版安装(含虚拟环境)

11、保姆版安装 Anoconda安装&#xff08;python的一个发行版本&#xff09; 优点&#xff1a;集成了许多关于python科学计算的第三方库&#xff0c;保姆级别 下载&#xff1a;www.anaconda.com/download/ 版本默认64位&#xff0c;py37 √&#xff1a;add anaconda to my…

代码随想录算法训练营第三十八天|509. 斐波那契数,70.爬楼梯,746. 使用最小花费爬楼梯

动态规划(DP) 如果某一问题有很多重叠子问题&#xff0c;使用动态规划是最有效的。 所以动态规划中每一个状态一定是由上一个状态推导出来的 一、动态规划包含哪些问题&#xff1f; 1、基础问题&#xff0c;如斐波那契数 2、背包问题&#xff0c;很经典的问题 3、打家劫舍 4、…

操作系统命令(贪吃蛇项目)

&#x1f3dd;1.获得句柄 GetStdHandle是⼀个Windows API函数。它用于从⼀个特定的标准设备&#xff08;标准输入、标准输出或标 准错误&#xff09;中取得⼀个句柄&#xff08;用来标识不同设备的数值&#xff09;&#xff0c;使用这个句柄可以操作设备。 ⛳️函数原型&…

Git使用总结(不断更新中)

branch 本地分支操作 删除本地分支 git branch -d <local-branch-name>远端分支操作 从远端分支创建本地分支 git checkout -b <local-branch-name> origin/<remote-branch-name>git ignore 如果工程的代码文件中有不希望上传到远端的文件&#xff0c;…

【Linux学习】Linux权限管理(一)

文章标题 &#x1f680;Linux用户分类&#x1f680;Linux权限管理&#x1f680;文件访问者的分类&#xff08;人&#xff09;&#x1f680;文件类型和访问权限&#xff08;事物属性&#xff09;&#x1f680;怎么修改权限 &#x1f680;Linux用户分类 Linux下有两种用户&#…

使用Hugo、Github Pages搭建自己的博客

文章目录 搭建博客框架及对比使用Hugo搭建博客使用Github Pages部署博客 搭建博客框架及对比 在众多的博客框架中&#xff0c;Hugo、Jekyll和Hexo因其出色的性能和易用性而备受推崇。 特点HugoJekyllHexo速度极高中等较高易用性高中等高&#xff08;熟悉JavaScript者&#xf…

力扣112,路径总和

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径&#xff0c;这条路径上所有节点值相加等于目标和 targetSum 。如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 叶子节点 是指没有子节点…

怎样实现opc采集数据后传给web后端

现在很多老工厂要进行数字化改造&#xff0c;现场生产的各种数据需要传到web后端&#xff0c;很多工厂现场原有的自动监控系统已经采集了现场的各种数据&#xff0c;只是没有形成联网。如果前端自动化系统全部废除&#xff0c;重新做数字化控制系统&#xff0c;成本投入太大&am…

GIS地理信息平台+智慧巡检技术解决方案(Word原件)

1.系统概述 1.1.需求描述 1.2.需求分析 1.3.重难点分析 1.4.重难点解决措施 2.系统架构设计 2.1.系统架构图 2.2.关键技术 3.系统功能设计 3.1.功能清单列表软件全套精华资料包清单部分文件列表&#xff1a; 工作安排任务书&#xff0c;可行性分析报告&#xff0c;立项…