51单片机模块学习——LED模块、独立按键、动态数码管

开发软件:Keil4(编写程序)、STC-ISP(烧录下载)
开发平台:普中科技51单片机A4版本
参考:B站江协科技51单片机学习视频

一、LED模块

LED模块是单片机上8个连着的小灯。
在这里插入图片描述
图上可见,8个LED小灯实际上由8个二极管组成,一端被设置为高电平(VCC),另一端可以用代码编辑。设定为低电平(0),则该LED发光,高电平(1)则LED熄灭。

 #include <REGX52.H>
 
 void main()
 {
 	P2=0xFD;
	while(1){
	
	}
 }

举个例子,上述代码,将P2设置为0xFD,即11111101,此时D2的负极被设定为0(低电平),我们可以观察到D2点亮,其余LED熄灭。
同样的,我们设定P2_1=0,同样可以观察到上述效果。这是因为P2本身是一个字节(8位),我们可以对其进行位操作,单选一位进行赋值也是可以的。

#include <REGX52.H>
#include <INTRINS.H>

void Delay500ms()		//@12.000MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 4;
	j = 205;
	k = 187;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}


void main()
{
	while(1){
	  P2=0xFE;
	  Delay500ms();
	  P2=0xFF;
	  Delay500ms();
	}
}

上述代码利用STC-ISP生成了一个延时函数,作用是停止代码运行一段时间。
这段代码先让第一个LED发光,过了500ms后,LED熄灭,又过了500ms,LED再亮。由此,我们得到了一个闪烁的LED灯。
除此之外,我们可以再尝试做一个LED流水灯。

//LED流水灯
#include <REGX52.H>
#include <INTRINS.H>

void Delay500ms()		//@12.000MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 4;
	j = 205;
	k = 187;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void main(){
	while(1){
		P2=0xFE; //1111 1110
		Delay500ms();
		P2=0xFD;   //1111 1101
		Delay500ms();
		P2=0xFB;	 //1111 1011
		Delay500ms();
		P2=0xF7;	 //1111 0111
		Delay500ms();
		P2=0xEF;
		Delay500ms();
		P2=0xDF;
		Delay500ms();
		P2=0xBF;
		Delay500ms();
		P2=0x7F;
		Delay500ms();
	}

}

二、独立按键

独立按键是单片机上四个靠在一起的按键。
在这里插入图片描述
图上可见,当K1按键按下时,P3_1会接地,变成低电平(0)。
由此,我们可以结合第一部分的LED模块,利用独立按键控制LED小灯的熄灭。

 #include <REGX52.H>
 
 void main()
 {
	while(1){
	   if(P3_1==0)
	  	{
	   		P2_0=0;  
		}
	   else
	   	{
			P2_0=1;
	   	}
	}
 }

以上代码进行了一个判断,当K1按键按下时,P3_1=0,此时令P2_0=0,第一个LED点亮。松手后K1回弹,LED熄灭。
在此基础上,我们可以设计一个利用K1按键控制LED状态的程序,按下K1,LED点亮,再次按下K1,LED熄灭。
需要注意的是,独立按键按下时,P3引脚不是立刻变成0的。
在这里插入图片描述
因此代码可以写成

#include <REGX52.H>
void Delay1ms(unsigned int xms)		//@12.000MHz 延迟xms 毫秒
{
	unsigned char i, j;
	while(xms>0){
	i = 2;
	j = 239;
	do
	{
		while (--j);
	} while (--i);
	xms--;
	}
}

void main(){
	while(1){
		if(P3_1==0){
			Delay1ms(10);
			while(P3_1==0){
			}
			Delay1ms(10);
			P2_0=~P2_0;
		}
	}
}

除此之外我们还可以编写独立按键控制LED显示二进制、独立按键控制LED移位的代码。

//独立按键控制LED显示二进制
#include <REGX52.H>
void Delay1ms(unsigned int xms)		//@12.000MHz
{
	unsigned char i, j;
	while(xms>0){
	i = 2;
	j = 239;
	do
	{
		while (--j);
	} while (--i);
	xms--;
	}
}

void main(){
	char LED=0;
	while(1){
		if(P3_1==0){
			Delay1ms(10);
			while(P3_1==0){
			}
			Delay1ms(10);
			LED++;
			P2=~LED;
		}
	}
}
//独立按键控制LED移位
#include <REGX52.H>
void Delay1ms(unsigned int xms)		//@12.000MHz
{
	unsigned char i, j;
	while(xms>0){
	i = 2;
	j = 239;
	do
	{
		while (--j);
	} while (--i);
	xms--;
	}
}

void main(){
	char LED=0;
	P2=0xFE;
	while(1){
		if(P3_1==0){
			Delay1ms(10);
			while(P3_1==0){
			}
			Delay1ms(10);
			LED++;
			if(LED>=8){
				LED=0;
			}
			P2=~(0x01<<LED);
		}
	   if(P3_0==0){
			Delay1ms(10);
			while(P3_0==0){
			}
			Delay1ms(10);
			if(LED==0){
				LED=7;
			}
			else{
				LED--;
				}
		
			P2=~(0x01<<LED);
		}
	}
}

三、动态数码管模块

在这里插入图片描述
51单片机的动态数码管原理图如上图,它是由两个四位数码管拼接组成。
独立的数码管如下图
在这里插入图片描述
在这里插入图片描述
内部电路有这么两种,也就是二极管往上接还是往下接的区别

以上面的共阴极连接方式为例,我们选中8位数码管的某一个数码管,上面给0(低电平),下面选择某几个端口给1(高电平),即可点亮某个数码管的部分内容。例如,给BC口(64)赋值为1,其余赋值为0,此时P0=0x06,数码管显示1。
博主自己整理了一下0-9对应的P0值,分别为0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F
那么如何选择数码管呢?实际上LED1-8的端口连接了一个74HC138译码器
在这里插入图片描述
三个输入P2_2、P2_3、P2_4决定了Y0-7的输出,Y口低电平有效,也就是说,P2_4=0 P2_3=0 P2_2=0时,LED1=0,其余LED=1。
我们可以编写一个函数,输入两个参数(选择的二极管,显示的数字),让单片机运行此函数时,数码管显示数字。

unsigned char NumTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
void nixie(unsigned char Location,Num)
{
	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=	NumTable[Num];
}

目前我们所学的内容可以帮助我们实现在数码管中选择一位进行显示,那么我们可不可以选择多位同时显示呢?
有同学说,这还不简单吗?直接依靠上面的函数,利用这样的代码不就可以了吗

void main
{
while(1)
	{
		nixie(1,1);
		nixie(2,2);
	}
}

这样的做法自然是巧妙的,利用人的视觉残留,显示多位数字
但是,机器设备不能做到完美的切换,也就是说,我上一秒还选择1号数码管,下一秒就选择2号数码管,机器的反应时间没有那么快,上述代码在运行时会出现残影,我们需要在nixie函数中添加延时函数以及P2选口复位,这样才能保证无残影。之后再利用nixie函数就可以实现同时显示多个数字的效果了。

//数码管段码表
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,消影
}

/
/
/
/
/
作者是第一次在CSDN上分享学习内容,写的不好请多多包涵。
欢迎大家在评论区和作者讨论。
码字不易,求各位看官点个关注~

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐