51单片机实验:数码管动态显示00-99

文章详细描述了使用STC89C52RC单片机开发板实现2位数码管循环显示00-99的过程,涉及位选、个位/十位显示函数、延时函数以及计数控制,解决了数码管显示不同数值和同步问题,最终通过调整延时和计数频率优化显示效果。
摘要由CSDN通过智能技术生成

1、实验要求

        利用STC89C52RC单片机开发板实现:使用2位数码管循环显示00-99,每次间隔1s,并且当计数到20时,则蜂鸣器鸣响1次。

2、实验分析

程序实现分析:        

        1、定义数码管位选引脚(P2.4、P2.5、P2.6、P2.7)

        2、定义个位、十位显示函数(用来未选第1、2位显示个位、十位上的数字)

        3、定义延时函数(使用for循环嵌套实现空语句执行,从而达到延时的效果)

        4、定义计数变量,分别计算出个位、十位的数,将其传入到个位、十位显示的函数

        5、结合延时函数,实现数字的显示

        6、判断计数变量大于99,则重新赋值为0

3、代码实现

(1)导入头文件及引脚定义

#include <reg52.h>

sbit pos1 = P2^4;   // 第1为数码管位选控制位
sbit pos2 = P2^5;   // 第2为数码管位选控制位
sbit pos3 = P2^6;   // 第3为数码管位选控制位
sbit pos4 = P2^7;   // 第4为数码管位选控制位
sbit fmq = P2^3;    // 蜂鸣器控制位

(2)定义个位、十位显示函数

// 分别对应:0/1/2/3/4/5/6/7/8/9
int code_sz[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};

// 宏定义:简写 unsigned int
#define uint unsigned int

// 函数声明
void show_ge(uint x);
void show_shi(uint y);


// 显示个位数字:左起第2位数码管
void show_ge(uint x)   // x:计算的个位数的值,对应数组中的索引,从而取到对应的值
{
	P0 = 0x00;     // P0(段选位)复位
	pos1 = 0;
	pos2 = 1;      // 选择第2位数码管
	pos3 = 0;
	pos4 = 0;
	P0 = code_sz[x];   // 数组索引取到对应的数字值赋值给P0
}

void show_shi(uint y)  // y:计算的十位数的值,对应数组中的索引,从而取到对应的值
{
	P0 = 0x00;     // P0(段选位)复位
	pos1 = 1;      // 选择第1位数码管
	pos2 = 0;
	pos3 = 0;
	pos4 = 0;
	P0 = code_sz[y];    // 数组索引取到对应的数字值赋值给P0
}

(3)定义延时函数

void delay(uint ms);   // 延时函数声明

void delay(uint ms)   // 延时指定的毫秒(错略延时)
{
	uint i, j;
	for(i=ms; i>0; i--)
	{
		for(j=112; j>0; j--);
	}
}

(4)编写主函数逻辑

uint val = 0;
uint ge, shi;

void main()
{
	while (1)
	{
		ge = val % 10;     // 计算个位的值
		shi = val / 10;    // 计算十位的值
		show_shi(shi);     // 调用显示十位的函数
		delay(100);        // 延时100ms,让十位数显示保持
		show_ge(ge);       // 调用显示个位的函数
		delay(900);        // 延时900ms,让十位数显示保持
		fmq = 1;           // 关闭蜂鸣器鸣叫
		pos1 = 0;          // 位选复位(避免出现位选错乱,产生乱码)
		pos2 = 0;
		pos3 = 0;
		pos4 = 0;
		val++;             // 计数值增加1
        if (val > 99) val =0;    // 如果计数值大于99,则重新从0开始
		if (val == 20) fmq=0;    // 如果计数值等于20,则蜂鸣器鸣叫
	}
}

【单片机显示问题】数码管显示不同的值需要考虑2个问题:

(1)十位、个位显示不同值:由于P0段选共用,则需要实现位选调整才能实现。

(2)要保证个位、十位的数同时显示。

【单片机显示现象】十位数字很暗,基本无法显示,个位可以正常,但会出现闪烁情况,无法看到00--99的数字。

【单片机显示分析】十位(第1位数码管)显示由于延时时间过短(100ms),造成还未显示,程序就执行到了显示个位的代码,从而位选就切换至第2位数(个位)码管,则P0对应的取值则会显示到第1位数码管,此时添加的900ms延时,也只能显示个位上的数字。

【单片机显示调整】

A、个位、十位显示的时间间隔不能过大这样(10s),由于代码执行较快(us),这样就能因为视觉停留现象则就会感觉数字是一直显示,同时也不会出现闪烁情况。

B、个位、十位数值变化时间要保证1s:则计数变量则1s内需要计数50次再增加1(1000 / (10 + 10) = 50), 这样就能让个位十位数码管1s内更新50次后显示下一个数。


uint times = 0;

void main()
{
	while (1)
	{
        times++;
		if(times == 50)    // 每50次,计数增加1
		{ 
			times = 0;     // 次数50次后复位
			val++;                   // 计数值增加1
			if (val > 99) val =0;    // 如果计数值大于99,则重新从0开始
		}

		ge = val % 10;     // 计算个位的值
		shi = val / 10;    // 计算十位的值
		show_shi(shi);     // 调用显示十位的函数
		delay(10);         // 延时10ms,让十位数显示保持
		show_ge(ge);       // 调用显示个位的函数
		delay(10);         // 延时10ms,让十位数显示保持
		fmq = 1;           // 关闭蜂鸣器鸣叫
		pos1 = 0;          // 位选复位(避免出现位选错乱,产生乱码)
		pos2 = 0;
		pos3 = 0;
		pos4 = 0;

		if (val == 20) fmq=0;    // 如果计数值等于20,则蜂鸣器鸣叫
	}
}

4、完整代码

#include <reg52.h>

// 宏定义:简写 unsigned int
#define uint unsigned int

sbit pos1 = P2^4;   // 第1为数码管位选控制位
sbit pos2 = P2^5;   // 第2为数码管位选控制位
sbit pos3 = P2^6;   // 第3为数码管位选控制位
sbit pos4 = P2^7;   // 第4为数码管位选控制位
sbit fmq = P2^3;    // 蜂鸣器控制位

// 分别对应:0/1/2/3/4/5/6/7/8/9
int code_sz[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};

// 函数声明
void show_ge(uint x);
void show_shi(uint y);
void delay(uint xms);   

uint times = 0;
uint val = 0;
uint ge, shi;

void main()
{
	while (1)
	{
        times++;
		if(times == 50)    // 每50次,计数增加1
		{ 
			times = 0;     // 次数50次后复位
			val++;                   // 计数值增加1
			if (val > 99) val =0;    // 如果计数值大于99,则重新从0开始
		}

		ge = val % 10;     // 计算个位的值
		shi = val / 10;    // 计算十位的值
		show_shi(shi);     // 调用显示十位的函数
		delay(10);         // 延时10ms,让十位数显示保持
		show_ge(ge);       // 调用显示个位的函数
		delay(10);         // 延时10ms,让十位数显示保持
		fmq = 1;           // 关闭蜂鸣器鸣叫
		pos1 = 0;          // 位选复位(避免出现位选错乱,产生乱码)
		pos2 = 0;
		pos3 = 0;
		pos4 = 0;

		if (val == 20) fmq=0;    // 如果计数值等于20,则蜂鸣器鸣叫
	}
}


// 显示个位数字:左起第2位数码管
void show_ge(uint x)   // x:计算的个位数的值,对应数组中的索引,从而取到对应的值
{
	P0 = 0x00;     // P0(段选位)复位
	pos1 = 0;
	pos2 = 1;      // 选择第2位数码管
	pos3 = 0;
	pos4 = 0;
	P0 = code_sz[x];   // 数组索引取到对应的数字值赋值给P0
}

void show_shi(uint y)  // y:计算的十位数的值,对应数组中的索引,从而取到对应的值
{
	P0 = 0x00;     // P0(段选位)复位
	pos1 = 1;      // 选择第1位数码管
	pos2 = 0;
	pos3 = 0;
	pos4 = 0;
	P0 = code_sz[y];    // 数组索引取到对应的数字值赋值给P0
}

void delay(uint ms)   // 延时指定的毫秒(错略延时)
{
	uint i, j;
	for(i=ms; i>0; i--)
	{
		for(j=112; j>0; j--);
	}
}

5、实验总结

        要明确数码管的显示要解决的问题(显示不同的值的数据保持、不同位的数据同时显示),着重问题的本身出发,设计对应的程序:通过多次判断实现对计数的修改,同时要明确程序执行的速度较快,人有视觉暂停现象, 结合这些因素实现对应逻辑分步操作。


结语以上整个程序的实现逻辑,还存在很多不全面的地方,欢迎各位大佬指点;如果觉得笔者不易,欢迎关注和点赞,给予我记录更多文章的动力!!

数码管显示0-99, CESASSCS /*************************************************************************** 标题: 数码管的显示 效果: 显示00-99,动态显示+变化显示 作者: 启程电子 ******************************************************************************/ ;脚功能定义 SMG_q EQU P3.4 ;定义数码管阳级控制脚,千位 SMG_b EQU P3.5 ;定义数码管阳级控制脚,百位 SMG_s EQU P3.7 ;定义数码管阳级控制脚,十位 SMG_g EQU P3.6 ;定义数码管阳级控制脚,个位 ;定义数据RAM空间 LDB EQU 36H ;定义一个变量存放显示值 ;数据存放 ORG 0100 TABLE: DB 0C0h,0F9H,0A4H,0b0H,99H,92H,82H,0F8H,80H,90H ;表:共阳数码管 0-9 ORG 0000H LJMP MAIN ORG 0200H MAIN: MOV DPTR,#TABLE M0: MOV LDB,#0 ;变量复值0 M1: MOV R7,#50 ;两级R7与R6组成12800次刷新,约1秒,如果要精确时间,可以用到定时器,请看例13 M2: MOV R6,#255 M3: CLR SMG_s ;选择十位数码管 MOV A,LDB ;将变量值除以10,商为十位值,余为个位 MOV B,#10 ; DIV AB ;相除后获得十位和个位的值存放A和B中 MOVC A,@A+DPTR ;查表输出定义好的数码管段值到P0口,显示相应的内容 MOV P0,A LCALL DELAY ;延时,停留一会,让人眼感触到它的亮度 MOV P0,#0FFH ;清除数码管显示,因是共阳型,所以不是0 SETB SMG_s ;关闭十位数码管 CLR SMG_g ;选择个位数码管 MOV A,B ;个位显示 MOVC A,@A+DPTR ;查表输出定义好的数码管段值到P0口,显示相应的内容 MOV P0,A LCALL DELAY ;延时,停留一会 MOV P0,#0FFH ;清除数码管显示 SETB SMG_g ;关闭个位数码管 M4: DJNZ R6,M3 DJNZ R7,M2 ;12800次刷新,约1秒 MOV A,LDB CJNE A,#99,M5 ;如果LDB变量值等于99就回到0开始,因为只有两位数码管,不能显示更多位 LJMP M0 M5: INC LDB LJMP M1 ; DELAY: MOV R5,#10 ;此次延时子程序不用很长时间 DJNZ R5,$ RET END
可以使用以下的代码实现单片机按键控制数码管的显示00-99: ```c #include <reg52.h> // 引入头文件 sbit LSA=P2^2; sbit LSB=P2^3; sbit LSC=P2^4; unsigned char code table[]={ 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90 // 数码管显示0-9的编码表 }; void delay(unsigned int i) // 延时函数 { while(i--); } void main() { unsigned int i=0, j=0; // 定义两个变量用于存储数值 P0=0; LSA=0;LSB=0;LSC=0; // 数码管显示0 while(1) { if(P3!=0xff) // 当按键被按下时 { delay(1000); // 延时,避免按键抖动 if(P3!=0xff) // 再次检测按键是否被按下 { if(P3==0xfe) // 如果按下K1键 { i++; // 数值加1 if(i>99) i=0; // 如果数值大于99,重新从0开始 } if(P3==0xfd) // 如果按下K2键 { j++; // 数值加1 if(j>99) j=0; // 如果数值大于99,重新从0开始 } } } P0=table[i/10]; // 将十位数码管的编码输出到P0口 LSA=1;delay(5);LSA=0; // 显示十位数码管 P0=table[i%10]; // 将个位数码管的编码输出到P0口 LSB=1;delay(5);LSB=0; // 显示个位数码管 P0=table[j/10]; // 将十位数码管的编码输出到P0口 LSC=1;delay(5);LSC=0; // 显示十位数码管 P0=table[j%10]; // 将个位数码管的编码输出到P0口 LSA=1;delay(5);LSA=0; // 显示个位数码管 } } ``` 这段代码中,P2.2、P2.3 和 P2.4 分别连接到数码管的 LSA、LSB 和 LSC 引脚,P0 口连接到数码管的 a~g 引脚。通过检测按键是否被按下,来改变 i 和 j 两个变量的数值,从而控制数码管的显示。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值