51单片机 第二节 点亮LED

本笔记默认学习者已拥有:
1.Keil5和stc烧写工具 等各种软件、驱动、环境;
2.有一个属于自己的 51单片机开发板及相关零件 ;
3.认识C语言的语法;
本人使用的51开发板为 郭天祥C51 TX-1C增强版开发板
本笔记根据B站up主:江科大自化协的教学视频 整理得到ヾ(•ω•)
虽然上来就是原理图,但千里之行始于足下,望能怀沉稳之心看到最后




2-1 点亮一个LED



原理分析

上图为TX-1C的LED模板的原理图,其 IO口 均为 P1口,视频中为P2,以下P2在TX-1C中均对P1!!!

LED模板原理图

1.VCC 可视为电源的正极,GND为接地线(可视为电源的负极),P20、P21 等均为单片机的P2口引脚;

TX-1C 是用 排阻 和 LED 相连的;

2.电阻的作用为 限流 ,因为 VCC 的电压为5V,直接 接VCC 可能使 LED 烧毁;
3.单片机通过从引脚输出高、低电平(高为5V,低为0V,为TTL电平,可分别视为正、负极):

\[(一种电平规范)TTL \begin{cases} 5V,视为正极+,等价逻辑"1"\\ 0V,视为负极-,等价逻辑"0" \end{cases}\]

4.让LED亮灭的问题 转化为 单片机引脚给高低电平的问题
(引脚给高电平,两端都是高电平,LED不亮;引脚给低电平,形成电平差,LED亮)

图1

4.单片机(MCU)内有CPU,而MCU中有很多 寄存器(一种存储器),寄存器以8个为一组,每个寄存器通过导线,经过驱动器 增大电流,然后连接到 IO口 端口上;
5.CPU可以通过直接访问寄存器(在寄存器中写值);
6.寄存器以8个为一组,P2口也是以8个为一组;

7.给高低电平的问题 转化为 配置P2口寄存器问题
CPU通过控制 寄存器 来控制 硬件电路,硬件电路来执行我们想要完成的功能




实践代码

图2

1.给P20口 赋值 0(给低电平),其他口 赋值 1(给高电平),这样就只有D1 一个LED亮,剩下的都不亮;
2.赋值是由 P2寄存器 确定的,要给P2寄存器 赋值 1111 1110 这一数字;

注意这里 寄存器 和 LED 顺序关系,
\(P20 \to D1 \to P2寄存器最后一位\)
\(P27 \to D8 \to P2寄存器第一位\)



点亮一个LED.c

#include<reg51.h>
//#include<REGX52.H>与其在某些 表达 上有所不同,但功能基本相似
void main(){
	P1=0xFE;//1111 1110
	//原视频为 P2=0xFE,而我的开发板对应端口为P1 
	while(1);
	/*
	单片机 会 优先执行 主函数main, 
	主函数执行结束后,会从头执行主函数,不断执行
	这显然是会损坏单片机的, 使用while(1)语句可以避免这种情况
	使程序停止 
	*/ 
}

运行结果如下:

点亮一个LED




使LED间隔点亮.c

#include<reg51.h>
void main(){
	P1=0x55;//0101 0101
	while(1);
}

运行结果如下:

点亮LED2




2-2 LED闪烁

1.让LED闪烁,写下了如下的代码:

#include<reg51.h>
void main(){
	while(1){
		P1=0xFE;//1111 1110
		P1=0xFF;//1111 1111
	}
}

2.发现LED并没有闪烁,但亮度比点亮LED时暗淡不少
(图左为当前代码的运行结果,图右为 点亮一个LED.c 的运行结果)

LED闪烁1

3.亮度变暗,是单片机速度的问题,单片机的速度是MHZ的等级,1MHZ就是每秒运行一百万次
所以LED是由于闪的特别快,所以才显得暗;
4.所以要想看到闪烁效果,要让其以一秒为周期闪烁

LED2

5.stc烧录工具中的软件延时计算器可以自动生成延迟函数,但同时要注意8051指令集项不要选错



LED闪烁.c

#include<reg51.h>
#include<intrins.h>//_nop_();需要 该头文件 
void Delay500ms()		//@11.0592MHz,我的晶振规模和视频中不同
{
	unsigned char i, j, k;

	_nop_();//_nop_();为空语句函数,什么也不会执行 
	i = 4;
	j = 129;
	k = 119;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}
/*
void Delay500ms(){
	uint unsigned int i,j;
	for(i=500;i>0;i--) 
		for(j=110;j>0;--j);
}
此为一种可视为等价的 函数写法 
*/
void main(){
	while(1){
		P1=0xFE;//1111 1110
		Delay500ms();
		P1=0xFF;//1111 1111
		Delay500ms();
		//以1秒为一个周期,即每隔500ms闪烁一次 
		//1s=1000ms
	}
}

运行结果如下:

IMG_4224




2-3 LED流水灯

这里考虑到读者,直接使用了位运算

LED流水灯.c

#include<reg51.h>
#include<intrins.h>
#define uint unsigned int 
//这里 定义了一个 x ms 的函数 
void Delayms(uint x)		//@11.0592MHz
{
	unsigned char i, j;
	while(x--){
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
	}
}
void main(){
	P1=0xFE;
	while(1){
		Delayms(500);
		P1<<=1; P1+=1;
		//使用位运算将指令位移,并且补1 保证流水灯效果 
		if(P1==0xFF) P1=0xFE;
		//当P1变为 1111 1111 时,需要进行 类似复位的操作,体现循环流水效果 
	}
}

运行结果如下:

IMG_4225.GIF




相关知识

电阻

1.有些电阻上会有数字,例如102代表了\(10*10^2=1000=1K\)阻值的电阻;
2.类似的,474代表了\(47*10^4=470000=470K\)阻值的电阻;
3.即前两位为有效数字,后一位为倍率,若\(X\)代表前几位数字,\(Y\)代表最后一位数字有(\(X\)不一定只是两位,也可能是一位或者更多位)

\[阻值=X*10^Y \]

原文地址:https://www.cnblogs.com/Potrem/p/51_2.html