(三)51单片机基础——独立按键与数码管

       

        从小就对电器元件比较感兴趣吧,经常拿坏的电器里面的芯片拆下来玩,甚至那些没坏的电器,比如我家的电视,也会希望它能坏掉,我好去看看里面是什么样子的,为什么能播放节目……,所以我第一眼看到51单片机的时候,更多的是兴奋。

        但是在学习的时候,遇到了许多的困难和问题,在此记录一下,看看能不能帮到需要的人。首先就是关于软件的,相比于其他语言的集成编译环境的安装,我觉得Keil5的安装更为困难,并且需要破解使用,并且需要选择合适的型号,一旦选错,代码就不能运行,还要在每个项目编写的时候勾选生成hex文件;还有安装CH341SER串口,安装好了好久都没能成功,后来发现是数据线的问题,在更换了几根数据线的情况下终于成功了,所以以后遇到类似的情况,可以选择换数据线;还有stc-isp-v6.88R烧录软件,同样需要选择型号,选错了同样不能找到单片机,自然不能成功烧录,并且每次烧录的时候要重启一下单片机(冷启动),才能烧录成功。还有一个就是关于芯片的问题,之前乱玩的时候,不小心把芯片接反了,导致芯片烧坏,还是自己重新买了一块芯片安装上去,才恢复正常,所以一定要注意正反。

         之前学会了有关控制LED亮灭的知识点,接下来我们来看一下如何通过独立按键来控制LED灯的亮灭,还是一样的步骤,我们需要来学习一些有关独立按键的电路知识。

        首先独立按键就是控制电路的连通,GND是电源负极,后面四个接口都是接在单片机的CPU上,而单片机接通电源时默认就是高电平,当按键被按下的时候,就变成了低电平,而这个变化可以通过寄存器来获取到(按键松开的时候,寄存器是高电平,按键按下的时候是低电平),再结合代码来解释一下。

#include <REGX52.H>

void main()
{
	while(1)
	{
		if(P3_1==0 || P3_0==0)	//P3_1是K1,P3_0是K2,如果K1按键或K2按键按下
		{
			P2_0=0;		//通过P2_0来控制一个LED灯,就不需要像上节那样通过向每个接口赋值来操控
           //LED1输出0,点亮
		}
		else
		{
			P2_0=1;		//LED1输出1,熄灭
		}
	}
}

运行结果如下所示:

独立按键0

        接下来我们来看一下通过独立按键来控制LED显示二进制的代码吧,不过可能需要一点C语言基础,要知道取反和基本运算符。

在这之前,还是需要了解一个电路知识,就是消抖,不过我们先来了解一下按键的抖动吧!

按键的抖动:对于机械开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开,所以在开关闭合及断开的瞬间会伴随一连串的抖动

        对于消抖,大概有两种方法,第一是通过硬件消抖,在次不做介绍,第二种就是通过软件来操作,通过延时来消抖。 

#include <REGX52.H>

void Delay(unsigned int xms)
{
	unsigned char i, j;    //八位二进制的数,便于我们操控单片机
	while(xms--)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}

void main()
{
	unsigned char LEDNum=0;
	while(1)
	{
		if(P3_1==0)			//如果K1按键按下
		{
			Delay(20);		//延时消抖
			while(P3_1==0);	//松手检测
			Delay(20);		//延时消抖
			
			LEDNum++;		//变量自增
			P2=~LEDNum;		//变量取反输出给LED
		}
	}
}

运行结果如下所示:

独立按键1

        这个代码是控制LED灯位移,大家可以试着分析一下,知识点和之前类似,就是加了一个移位的操作来实现LED的位移。

#include <REGX52.H>
void Delay(unsigned int xms);

unsigned char LEDNum;

void main()
{
	P2=~0x01;				//上电默认LED1点亮
	while(1)
	{
		if(P3_1==0)			//如果K1按键按下
		{
			Delay(20);
			while(P3_1==0);
			Delay(20);
			
			LEDNum++;		//LEDNum自增
			if(LEDNum>=8)	//限制LEDNum自增范围
				LEDNum=0;
			P2=~(0x01<<LEDNum);	//LED的第LEDNum位点亮
		}
		if(P3_0==0)			//如果K2按键按下
		{
			Delay(20);
			while(P3_0==0);
			Delay(20);
			
			if(LEDNum==0)	//LEDNum减到0后变为7
				LEDNum=7;
			else			//LEDNum未减到0,自减
				LEDNum--;
			P2=~(0x01<<LEDNum);	//LED的第LEDNum位点亮
		}
	}
}

void Delay(unsigned int xms)
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}

运行结果如下所示:

独立按键2

这就是独立按键的一些知识了,就先介绍到这!

 接下来就是介绍数码管了,相对于前面的知识来说,数码管对于电路的要求更多,所以比较难理解。首先,我们来介绍一下数码管的构造。

        首先,我们先来研究一个数码管,右图是两种连接方式,一种是共阴极的连接方法, 另一种是共阳极的连接方法,开发板就是共阴极连接的,所以我们只讲解共阴极,共阳极的原理也是一样的,就不细细讲解。首先,负极接地(位选),再对各个引脚赋值(和LED那章类似),就可以显示出相应的数字了。

        之后,我们就要开始研究四位一体的数码管了,四位一体的数码管并不是单纯的把四个数码管拼接在一起,那样引脚数码过多,不利与操作。个人认为这个四位一体数码管设计的十分巧妙,仅仅使用了12个引脚就解决了(一个数码管是10个引脚,就加了2个引脚,却能多控制3个数码管),让我们来看看四位一体的数码管的构造吧!

        这个数码管点亮的方式,和 一个数码管类似,就是需要去控制4个位选端,其他的引脚和之前的类似,但是呢,有人可能有疑问了,这样只能显示一个数字啊,如果要显示1234,明显是做不到的,确实是这样的,但是我们有办法解决这个问题。

在这之前,还要介绍一个东西——译码器。

        译码器,可以用3个io口去控制8个io口,进一步减少了需要操作的引脚数。左下角是使能端,可以理解为电源。控制原理就是,用3位二进制,通过转换成十进制,操控对应的端口(低电平有效)。

这个是缓冲器 ,可以理解为提高驱动能力,传输电位信号(双向)。


电路知识介绍完毕,于是,我们现在开始点亮数码管了。

#include <REGX52.H>

//数码管段码表
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};   
//数组,默认大家都会

//数码管显示子函数
void Nixie(unsigned char Location,Number)
{
	switch(Location)		//位码输出,也就是译码器的那三个接口
	{
		case 1:P2_4=1;P2_3=1;P2_2=1;break;
		case 2:P2_4=1;P2_3=1;P2_2=0;break;
		case 3:P2_4=1;P2_3=0;P2_2=1;break;
		case 4:P2_4=1;P2_3=0;P2_2=0;break;
		case 5:P2_4=0;P2_3=1;P2_2=1;break;
		case 6:P2_4=0;P2_3=1;P2_2=0;break;
		case 7:P2_4=0;P2_3=0;P2_2=1;break;
		case 8:P2_4=0;P2_3=0;P2_2=0;break;
	}
	P0=NixieTable[Number];	//段码输出,就是后面那8个引脚
}

void main()
{
	Nixie(2,3);	//在数码管的第2位置显示3
	while(1)
	{
		
	}
}

运行结果如下所示:

        我们还要一个问题没有解决,那就是,如何在数码管上显示不同数字,答案就是,反复刷新,因为单片机频率比较快,所以通过反复刷新,人眼是看不出来的。 但是在刷新的过程中,数码管显示不是特别清楚,有残影(如下图所示),是因为在位选和段选切换的时候,就会发生数据篡位,所以我们需要消影,具体做法就是,在一次位选和段选结束之后,选择清零,这样就可以了,代码如下所示。


#include <REGX52.H>

//数码管段码表
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};

//延时子函数
void Delay(unsigned int xms)
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}

//数码管显示子函数
void Nixie(unsigned char Location,Number)
{
	switch(Location)		//位码输出
	{
		case 1:P2_4=1;P2_3=1;P2_2=1;break;
		case 2:P2_4=1;P2_3=1;P2_2=0;break;
		case 3:P2_4=1;P2_3=0;P2_2=1;break;
		case 4:P2_4=1;P2_3=0;P2_2=0;break;
		case 5:P2_4=0;P2_3=1;P2_2=1;break;
		case 6:P2_4=0;P2_3=1;P2_2=0;break;
		case 7:P2_4=0;P2_3=0;P2_2=1;break;
		case 8:P2_4=0;P2_3=0;P2_2=0;break;
	}
	P0=NixieTable[Number];	//段码输出
	Delay(1);		//显示一段时间
	P0=0x00;		//段码清0,消影
}

void main()
{
	while(1)
	{
		Nixie(1,1);		//在数码管的第1位置显示1
//		Delay(20);
		Nixie(2,2);		//在数码管的第2位置显示2
//		Delay(20);
		Nixie(3,3);		//在数码管的第3位置显示3
//		Delay(20);
	}
}

运行结果如下所示:

        如果想要显示多位数字,可以修改一下延时时间,就可以实现了。好了,这就是有关数码管的知识点了。

  • 13
    点赞
  • 120
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值