速通51单片机————点亮LED与控制LED

本章将介绍LED的点亮操作,以及如何用按键控制LED。

由于是速通,并不是傻瓜式教学,故具体的文件操作与烧录过程就不一一展示了,注重具体的代码实现与原理,具体过程请看下面给出的视频链接,看过一次操作即可。

前置知识为:C语言基础(这个很重要),以及数电的进制转换基础,以及:自备51单片机(博主的单片机为共阳连接)以及对应的软件,详细请看B站视频: [1-2] 开发工具介绍及软件安装_哔哩哔哩_bilibili

下面简单介绍一下数电的进制转换基础(二进制与十六进制的相互转换)

前置知识(数电进制转换与共阳连接及共阴连接)

进制转换

由于在计算机中都是采用二进制,而在代码中我们需要写入十六进制,故我们只需要二进制与十六进制相互转换的关系即可,其中二进制的四位从左到右依次对应十六进制的8 4 2 1,例如1101就是8+4+1=13。

共阳连接

共阳连接即对应着:

0------灯亮

1------灯灭

共阴连接

共阴连接即对应着:

0------灯灭

1------灯亮

一、点亮第一个LED灯

在本章中使用的51单片机中共有8个灯,对应着两组二进制,而51单片机中的P2端口则对应着八个灯,通过两组二进制来控制,但是实际上是用两个十六进制的数,

如下:该情况就对应着LED灯间隔亮暗

cpp 复制代码
#include <REGX52.H>

void main()
{
	P2=0xAA;//1010 1010
	
}

二、令LED灯闪烁

只需要让一个灯在01之间来回循环即可,但是在语句之间执行速度很快,所以需要delay延迟,在stc-isp中会有延迟时间函数可以自动生成,这里直接就拿来用就好。

cpp 复制代码
#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=0xFF;//1111 1111
		Delay500ms();		
	}
}

三、使LED灯流水线式闪烁

这个本质是和上面一样的,通过输入给P2不同的进制,加上循环,从而达到不同的灯流水线式的闪烁,可以看下面代码的注释,0代表亮,1代表灭

cpp 复制代码
#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;//1110 1111
		Delay500ms();
		P2=0xDF;//1101 1111
		Delay500ms();
		P2=0xBF;//1011 1111
		Delay500ms();
		P2=0x7F;//0111 1111
		Delay500ms();		
	}
}

我们不能一直依靠软件生成的延迟函数来固定延迟

可以尝试生成1毫秒的延迟代码,通过构造形参的方式,传入我们需要循环的次数,例如x次,那么就会循环x*1毫秒

cpp 复制代码
#include <REGX52.H>
#include <stdio.h>



void Delay1ms(unsigned int x)		//@12.000MHz
{
	unsigned char i, j;
	
	while(x)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
		x -= 1;
	}
}

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

四、使用独立按键控制LED灯

P3_1为第一个独立按键的按钮,按下则代表为0,松开则代表为1,此时我们只需要判断好按钮的状态,从而进入条件使灯亮暗即可。

控制LED灯亮灭

cpp 复制代码
#include <REGX52.H>

void main()
{
	while(1)
	{
		if(P3_1 == 0)//按下按键
		{
			P2_0 = 0;//亮
		}
		else
		{
			P2_0 = 1;//否则为暗
		}
	}
}

控制LED灯状态

按下按钮之后,让灯亮或者灯灭,我们需要利用按位取反的性质,单独对某个灯的状态按位取反,就能实现对某个灯的亮暗操作了,我们知道P2对应着八个灯,那么P2_0则对应着其中一个灯,我们就单独控制这个就好。

在物理世界中,按键按下时由于会有微小弹性,所以按下之后的短暂时间内会有回弹,此时如果不控制这段时间的话就会出现按下之后会有多次瞬间闪烁,那么我们就需要在按下之后消除掉这短暂的时间,也就是delay一下,再执行接下来的语句。当然,在松开之后同样需要消除一下短暂的时间

cpp 复制代码
#include <REGX52.H>

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


void main()
{
	while(1)
	{
		if(P3_1 == 0)//当按下按钮
		{
			Delay(20);//消除短暂时间
			while(P3_1 == 0);//如果一直按着还没松开则一直循环不动
			Delay(20);//松开后,消除短暂时间
			//此时完成一次按下松开的操作
			P2_0 =~ P2_0;//灯亮或者灯灭
		}
	}
}

控制LED灯显示二进制

首先要知道,我们让P2每加一,那么就会从0000000->00000001,此时自身取反就成了11111110,那么就是第一颗灯亮了,我们就按照这个就能控制LED灯显示二进制即可,那么步骤就是检测到按下抬起按键一次。为了方便起见,我们就不直接控制P2,我们另设一个char变量来传给P2。

cpp 复制代码
#include <REGX52.H>

void Delay(unsigned int xms)		//@12.000MHz
{
	unsigned char i, j;

	while(xms--)
	{
		i = 2;
		j = 239;
		do
		{
				while (--j);
		} while (--i);
	}
}

void main()
{
	unsigned char LEDNum = 0;//传给P2的参数
	while(1)
	{	
		if(P3_1 == 0)
		{
			Delay(20);
			while(P3_1 == 0);
			Delay(20);
			
			LEDNum++;
			P2 =~ LEDNum;
		}
	}
}

控制LED灯移位

利用LEDNum的计数来操控变量00000001**(0x01)**左移或者右移的位数

左移:令LEDNum++,一旦≥8,则复位0,然后进行左移LEDNum位。

右移:令LEDNum--,一旦≤0,则复位7,然后进行右移LEDNum位。

当移动完成后,再按位取反赋值给P2即可完成操作。

由于char变量是无符号,所以在判断右移的情况有稍微不同,具体如下代码所示

cpp 复制代码
#include <REGX52.H>

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

unsigned char LEDNum;

void main()
{
	P2 =~ 0x01;
	while(1)
	{	
		if(P3_1 == 0)
		{
			Delay(20);
			while(P3_1 == 0);
			Delay(20);
			
			LEDNum++;
			if(LEDNum >= 8)
			{
				LEDNum = 0;
			}
			P2 =~ (0x01<<LEDNum);
		}
		
		if(P3_0 == 0)
		{
			Delay(20);
			while(P3_0 == 0);
			Delay(20);
			
			/*LEDNum--;
			if(LEDNum < 0)
			{
				LEDNum = 7;
			}*/
			
			if(LEDNum <= 0)
			{
				LEDNum = 7;
			}
			else
			{
				LEDNum--;
			}
			P2 =~ (0x01 << LEDNum);
		}
	}
}
相关推荐
CS Beginner2 小时前
【ESP32】Keil搭建ESP32-C3环境
单片机·esp32
无垠的广袤3 小时前
【FPB-RA6E2 开发板】Zephyr 串口打印 DHT11 温湿度
c++·单片机·串口通信·开发板·瑞萨·传感器·dht11
曾浩轩3 小时前
跟着江协科技学STM32之3-4按键控制LED&光敏传感器控制蜂鸣器
科技·stm32·嵌入式硬件
尼喃3 小时前
单节锂电池充电芯片核心选型,高可靠性充电方案技术精要
单片机·51单片机·芯片
兆龙电子单片机设计4 小时前
【STM32项目开源】STM32单片机数字电子秤系统
stm32·单片机·物联网·开源·毕业设计
d111111111d4 小时前
逻辑最清晰的STM32F1/F4标准库工程创建
stm32·单片机·嵌入式硬件
pangtao20254 小时前
【瑞萨RA × Zephyr评测】iic测试(AHT20 (SCI I2C))
stm32·单片机·嵌入式硬件
怀民民民4 小时前
双通道点光源追踪系统
单片机·嵌入式硬件·开源·操作系统·串口·硬件·frtos
贪玩成性4 小时前
TM1652驱动代码
单片机·mcu