蓝桥杯基础教程之数码管操作(下)学习蓝桥杯必看基础!

前言

前篇最后提到了一个问题就是
如何让前四个数码管显示1后四个数码管显示2又如何实现呢?
这个问题在使用静态数码管显示的方式是达不到的!因为这8个单独的数码管的管选都是连在一起的,在显示一个效果的时候,只要是位选为1的数码管都会显示相同的效果。那么如何才能使数码管在同一时间显示不同的显示效果呢?这个就要提到今天需要讲到的动态数码管的显示了。

动态数码管的显示

首先需要知道的一个知识就是人眼的视觉暂留现象
百度百科给出的含义
在这里插入图片描述
这个现象就被运用在了动态数码管的显示上面。如何用呢?
ms
一定要将上述图片的话,仔细分析,因为人的视觉暂留要持续0.1-0.4s,也就是100ms-400ms,我们有8个数码管,每个两毫秒,因此总的下来才16ms,完全满足条件。这个尽管每次我们只点亮一个数码管,但是因为人眼的视觉暂留效果,我们看起来就像是数码管都亮着的。这样我们数码管点亮前,将想要显示的数据输出到管选,就能够实现不同的数码管显示不同的显示效果,并且看起来是同时点亮的!

时间控制

可以看到为了实现动态数码管的显示,我们首先要制造2ms的定时,让每到一个定时数码管的显示就能够切换到下一个数码管的显示,然后依次循环下去。
这里实现2ms的定时有两个方法:

  • 使用定时器实现
  • 使用空指令函数nop while等组成delay函数实现。
    这里强烈要求使用定时器实现,因为delay函数会严重影响程序的及时响应,不清楚原因的同学,可以看一下。

单片机为什么不推荐使用delay而要使用定时器呢?

代码编写

#include "STC15F2K60S2.h"

typedef unsigned char uchar;
typedef unsigned int uint;
enum{
    
     LED = 4 , EXT , DIG , CODE };
#define Select( x ) P2 = ( P2 & 0x1f ) | ( x << 5 ); P2 = (  P2 & 0x1f  )
sbit BEEP = P0^6; sbit RELAY = P0^4;

xdata uchar CA[] = {
    
    0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};
uchar buffer[] = {
    
    0, 1, 2, 3, 4, 5, 6, 7};

void Timer1Init(void)		//2毫秒@12.000MHz
{
    
    
	AUXR |= 0x40;		//定时器时钟1T模式
	TMOD &= 0x0F;		//设置定时器模式
	TL1 = 0x40;		//设置定时初值
	TH1 = 0xA2;		//设置定时初值
	TF1 = 0;		//清除TF1标志
	TR1 = 1;		//定时器1开始计时
	//加上
	ET1 = 1;		//允许定时器1中断
	EA = 1;		   	//全局允许中断开启
}
//中断处理程序
void Timer1Handle()	interrupt 3
{
    
    
	P0 = 0xff;
	Select(CODE);
	P0 = 1 << digSel;
	Select(DIG);
	P0 = CA[buffer[digSel]];
	Select(CODE);
	digSel = (digSel + 1)%8;
}




//外设初始化
void extInit()
{
    
    
	//外设初始化
	BEEP = 0;
	RELAY = 0;
	Select( EXT );     //大致步骤就是先准备好要放在P0上的数据,然后打开对应锁存器,然后马上关闭!
	P0 = 0xff;            //最好不要先打开锁存器,放上数据,再关闭,这样在打开的时候会有未知的干扰!
	Select( LED );
}

void main()
{
    
    
	extInit();
	Timer1Init();
	while(1);
}

关于定时器的基本知识,我这里不会做出说明,这个不了解的可以去百度。这里只说这部分的运行原理和机制。
Timer1Init这个函数是用来初始化定时器的,这部分可以通过自动生成
在这里插入图片描述
注意:在后面需要加上

	ET1 = 1;		//允许定时器1中断
	EA = 1;		   	//全局允许中断开启

然后后面Timer1Handle()函数后面用到了关键字interrupt 3指定中断号3
其中中断号在芯片手册会给出
在这里插入图片描述
这里强烈建议使用定时器1来作为数码管扫描的功能------原因
下面重点分析中断处理函数

//中断处理程序
void Timer1Handle()	interrupt 3
{
    
    
	P0 = 0xff;
	Select(CODE);
	P0 = 1 << digSel;
	Select(DIG);
	P0 = CA[buffer[digSel]];
	Select(CODE);
	digSel = (digSel + 1)%8;
}

下面的解释请务必看懂
首先在进入中断程序后,P0 = 0xff(首先送入数据),然后select(CODE)打开管选,让当前正在显示的数码管熄灭,P0 = 1 << digSel;这句是送入需要点亮数码管的位选数据。
我们不需要去纠结digSel是什么数据,我们需要知道的是数码管的共阳端是1才能够点亮的,我们可以注意到digSel是unsigned char是8位的,1<<digSel,是让一个8位的数据也正是对应8个数码管同时只有一个点亮。
然后P0 = CA[buffer[digSel]]; 这行程序就比较让人回味了,它提供了一种’解码’方式,将需要显示的数据的段码输出到P0,这里需要关注digSel的值了,请注意首先的值是buffer[digSel],这里的值是buffer数组中对应在digSel位置的值,这里以digSel为1为例子,那么buffer[digSel]的值就是1


uchar buffer[] = {
    
    0, 1, 2, 3, 4, 5, 6, 7};
buffer[1] = 1

那么对应的CA[buffer[digSel]]的值就是0xf9,这个0xf9也正是1的段码数据

段码表
0	--	0xc0
1	--	0xf9
2	--	0xa4
3	--	0xb0
4	--	0x99
5	--	0x92
6	--	0x82
7	--	0xf8
8	--	0x80
9	--	0x90

因此P0 = CA[buffer[digSel]];也就是提供了一个解码方式输出到P0,那么为什么不直接使用P0 = CA[1];
而要使用P0 = CA[buffer[digSel]];这样呢?
因为,这里的digSel还有其它作用,结合buffer[]这个数组,它可以实现buffer中从左到右8个数据都依次对应数码管从左到右8个显示!!
回看一下P0 = 1 << digSel;这个digSel正好选择了对应的位置数码管点亮。
上述解释可能不是很好,这段需要耐心理解一下,一定要理解,最好自己过一遍流程!,一定要理解


如果实在理解有困难,那么就将这段程序背下来

//中断处理程序
void Timer1Handle()	interrupt 3
{
    
    
	P0 = 0xff;
	Select(CODE);
	P0 = 1 << digSel;
	Select(DIG);
	P0 = CA[buffer[digSel]];
	Select(CODE);
	digSel = (digSel + 1)%8;
}

然后记住,改变buffer中从左到右的数据就是改变CT107D这款板子上数码管从左到右的显示数据。

如果要解答上篇最后的回答,那么就直接使用上面给出的程序,然后将
buffer[] = {1, 1, 1, 1, 2, 2, 2, 2};就行了
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_37429313/article/details/113814190