No3 蓝桥杯单片机实践之动态显示

动态显示这一块还不是理解的很透彻,先写写自己简单的想法吧,希望大家可能给点建议,尤其是延迟函数这块。

1:动态显示和静态显示的区别:

数码管分为“位选”和“段选”两个部分,先“位选”再“段选”。

当选择一个位时,段选就决定该位置显示什么内容;

当选择多个位时,段选则决定这多个位置同时显示什么内容。

以下图为例,为数码管的其中一块,有四个数字,com1~com4决定了选择这4个数字中的哪一个,而abcdefg dp则决定显示什么内容,但是不是每个数字都对应有abcdefg dp这些端口,而是这四个数字共用abcdefg dp这些端口,因此,理论上,不可能出现不同位置同时显示不同字符的情况,比如,当悬着com1和com2时,段选显示“6”(abcdefg dp控制)第一和第二个数字将会同时显示6。

要想实现不同位置同时显示不同字符的情况,有两种方法:

1.静态显示:给每个数字都各自搭配abcdefg dp端口。(缺点:端口多,成本高)

2.动态显示:仍然用上图所示的数码管结构,理论上来说不仅可能实现,但是实际情况下由于人肉眼的视觉延时等作用依次轮流的点亮多个位置的数字,(在此过程中可让每个位置的数字显示不同的内容)人的肉眼看起来就是不同位置同时显示了不同字符的情况。简单说,编写代码流程时,就直接按依次点亮正常的位选和段选就行了,可以实现多位不同显示的情况。

简单来说:

在不改变数码管结构的情况下,静态显示就是要么多个位置同时显示一样的数字,要么就是只选择一个位置变化不同字符,动态显示就是能够实现不同位置看起来同时不同字符的情况。

2. 数码管显示的延时问题

单片机工作流程是位选 -> 段选 ->位选 -> 段选 ->位选 -> 段选 ->位选 -> 段选 ... 完成段选后,单片机就会显示新的内容,单片机的操作是需要时间的,当第一组位选段选完成后,直接进行第二组位选段选的话,前面提到的人肉眼的视觉延时和单片机余晖作用,上一组显示的内容还没完全褪去,下一组新的内容就来了,这就会导致内容重叠,为了避免这种情况,常常每一组位选段选 完成后,都会加一个延时函数来“消影”,即延长一点时间让单片机不进行其他操作,给足时间让数码管上一组的余晖慢慢消失掉,这样就不会下一组的内容重叠。

感觉理解的不太到位,欢迎大佬指正交流。

3. 实践

相关器件结构回顾在数码管静态显示篇就写过了,这里不再赘述。

3.1 任务

3.2思路


按照动态显示的原理,就是依次点亮每一个位置即可,0~3位置分别显示2018,4~5位置显示“--”,6~7位置1~12依次变化。

先从最初状态开始,1~4位置分别显示2018,5~6位置显示“--”,7~8位置01。

为了代码可读性,可以设计一个函数来表示数码管的位选和段选,后续使用时传进相应位置和内容即可,如:2018显示,可读性就很强了。

并且要进行消影,一组位选段选 后就进行Delay。

7~8位置1~12依次变化,先将1~12分为12个静态过程,则1~12可以这样表示:月份的十位g_month / 12, 月份的个位为 g_month % 12(对12取余数)

现在怎么让1~12动起来?可用一个循环和对月份累加来进行操作,月份显示的话,设置一个变量g_month,让其从1开始,然后累加,当其>12, 让g_month 重新变回1。

所以需要一个循环和if判断(是否>12),这里老师的思路是:

主要是这个延时函数的变化,第一个延时函数什么都不做,就是消耗时间,第二个延时函数就是循环t次,每一次运行函数ShowSMG,我的理解就是这里要6~7位置仅从1~12的变化时,0~5位置还是不变化的,此前我们提到能够动态的原因时因为肉眼的延迟,如果只是单纯的Delay的话,就会延迟到了一定时间,而0~5位置的某些地方肉眼看起来会消失,所以要延迟让整个位置一直在运行?(哎这里不是太理解,大神救救!!!!)

3.3 完整代码如下:

#include "stc15f2k60s2.h"
unsigned int g_month = 1;


void Delay(unsigned char t)
{
	while(t--);
}

code unsigned char SMG_Table[] = 
{
0xc0, //0
0xf9, //1
0xa4, //2
0xb0, //3
0x99, //4
0x92, //5
0x82, //6
0xf8, //7
0x80, //8
0x90, //9
0x88, //A
0x83, //b
0xc6, //C
0xa1, //d
0x86, //E
0x8e,  //F
0xbf  //-
};

void selectHC138(unsigned int n)
{
	switch(n)
	{
		case 0: 
			P2 = (P2 & 0x1f) | 0x00;  break;
		case 1:
			P2 = (P2 & 0x1f) | 0x20;  break; 
		case 2:
			P2 = (P2 & 0x1f) | 0x40;  break; 
		case 3: 
			P2 = (P2 & 0x1f) | 0x60;  break; 
		case 4:
			P2 = (P2 & 0x1f) | 0x80;  break; 
		case 5:
			P2 = (P2 & 0x1f) | 0xa0;  break; 
		case 6:
			P2 = (P2 & 0x1f) | 0xc0;  break; 
		case 7:
			P2 = (P2 & 0x1f) | 0xe0;  break;
	}
}

void selectSMG(unsigned char position, unsigned char number)
{
	selectHC138(6);       // position
	P0 = 0x01 << position;   // position start from zero
	selectHC138(7);       // content
	P0 = SMG_Table[number];	
}

void ShowSMG()
{
	//2018
	selectSMG(0,2);
	Delay(500);    //xiao ying
	selectSMG(1,0);
	Delay(500);
	selectSMG(2,1);
	Delay(500);
	selectSMG(3,8);
	Delay(500);
	
	// --
	selectSMG(4,16);
	Delay(500);
	selectSMG(5,16);
	Delay(500);
	
	// month
	selectSMG(6,g_month/10);
	Delay(500);
	selectSMG(7,g_month%10);
	Delay(500);
}

void Delay_SMG(unsigned char t)
{
	while(t--)
	{
		ShowSMG();
	}
	
}

void close()
{
	selectHC138(5);
	P0 = 0x00;
	selectHC138(4);
	P0 = 0xff;
}

void main()
{
	close();
	while(1)
	{
		ShowSMG();
		g_month++;
		if(g_month>12)
		{
			g_month=1;
		}
		Delay_SMG(500);
	}
}

欢迎指正

  • 30
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值