目录
[4.点亮 LED 灯](#4.点亮 LED 灯)
[4.1 认识 LED 灯](#4.1 认识 LED 灯)
[4.2 寄存器](#4.2 寄存器)
[4.2.1 寄存器原理](#4.2.1 寄存器原理)
[4.2.2 存储数据](#4.2.2 存储数据)
[4.3 数据类型](#4.3 数据类型)
[4.4 LED 灯实验](#4.4 LED 灯实验)
[4.4.1 点亮一个 LED 灯](#4.4.1 点亮一个 LED 灯)
[4.4.2 LED 灯闪烁](#4.4.2 LED 灯闪烁)
[4.4.3 LED 流水灯](#4.4.3 LED 流水灯)
4.点亮 LED 灯
4.1 认识 LED 灯
发光二极管:单向导电性。电流大小一般控制在3-20 mA;
电流较大时,会在发光二极管引脚串接电阻,限制电流,该电阻又被称为限流电阻 ;

一般有直插式、贴片式两种方式;


观察下实物图,对比上左图:
上图 PR9,PR10 指并联后的四个 LED 灯电阻,即 下图的 PR9,PR10
102即电阻:1000 欧;
该电阻表示方式:如 321:320 欧;573:57 000 欧;

4.2 寄存器
4.2.1 寄存器原理
任何单片机,内部都有寄存器,用来存储数据和控制器件。
51单片机是一种广泛使用的微控制器,它包含了一系列的寄存器,用于存储和控制数据
cpu 通过配置寄存器来控制硬件电路进而完成执行的功能
【采用寄存器,可以减少 CPU 访问内存的次数,从而提高CPU的工作速度】
【CPU访问寄存器所用的时间要比访问内存的时间短】
4.2.2 存储数据
学习单片机,本质上就是在学习它的寄存器。
单片机中所有数据都是 二进制 形式存储和传送的。 写程序时可以是十进制 十六进制 二进制。
可是,如果我们直接使用二进制表示,程序会直接认为其为十进制,进而传送数据错误
如下:会将二进制 1111 1110 误认为是 十进制: 111,111,110

所以我们在编程时,使用十六进制;
TTL 信号规定,+5V 等价于逻辑 "1",0V 等价于逻辑 "0"(采用二进制来表示数据时)。
单片机通电,默认其为高电平,即 "1";
单片机的寄存器被放到内部特定的地址空间,并被命名,这个命名文件就叫做单片机的头文件
4.3 数据类型
C51数据类型:
4.4 LED 灯实验
4.4.1 点亮一个 LED 灯
单片机只要上电,就会一直工作,不会停下来
当主函数执行完之后,又会从头开始执行
类似于"一直开灯"的状态
我们一般将核心代码写入一个 while 死循环中
4.4.2 LED 灯闪烁
在 STC-ISP 中生成一个延时函数:
复制到 Keil 中:
根据需求输入不同的实参进而控制灯亮与灭的时间;
cpp
#include <at89c51RC2.h>
#include <intrins.h>
//点亮一个 LED 灯
//void main()
//{
// while(1)
// {
// P2 = 0xFE //1111 1110
// }
//}
//LED 灯闪烁
void Delayms(int xms) //@11.0592MHz
{
unsigned char data i, j;
while(xms--)
{
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
void main()
{
while(1)
{
P2 = 0xFE;
Delayms(8000);
P2 = 0xFF;
Delayms(1000);
}
}
4.4.3 LED 流水灯
实现 8 个 LED 灯轮流点亮的效果;
方案一:
简单易懂,但稍嫌麻烦,不够精简;
cpp
#include <at89c51RC2.h>
#include <intrins.h>
//LED 流水灯实验
sbit led1 = P2^0;
sbit led2 = P2^1;
sbit led3 = P2^2;
sbit led4 = P2^3;
sbit led5 = P2^4;
sbit led6 = P2^5;
sbit led7 = P2^6;
sbit led8 = P2^7;
void Delay1ms(unsigned int ms)//@11.0592MHz
{
unsigned char data i, j;
while(ms--)
{
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
void main()
{
while(1)
{
//LED灯的阳极引脚连接电源VCC,阴极引脚为P2^0-P2^7,故赋值 0 即可使其发光
led1 = 0;
Delay1ms(1000);
led1 = 1;
led2 = 0;
Delay1ms(1000);
led2 = 1;
led3 = 0;
Delay1ms(1000);
led3 = 1;
led4 = 0;
Delay1ms(1000);
led4 = 1;
led5 = 0;
Delay1ms(1000);
led5 = 1;
led6 = 0;
Delay1ms(1000);
led6 = 1;
led7 = 0;
Delay1ms(1000);
led7 = 1;
led8 = 0;
Delay1ms(1000);
led8 = 1;
}
}
方案二:
利用 左移运算符;
cpp
#include <at89c51RC2.h>
#include <intrins.h>
// 延时函数(原代码不变)
void Delay1ms(unsigned int ms) //@11.0592MHz
{
unsigned char data i, j;
while(ms--)
{
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
void main()
{
//所有51单片机的局部变量,都建议在函数开头集中定义
unsigned char i;
while(1)
{
P2 = 0x01; //0xfe = 0000 0001
for(i=0;i<8;i++)
{
Delay1ms(500); // 延时500ms
//P2 = 0xfe<<i; //这样不符合流水灯的要求:该灯亮起并熄灭后,下一个灯又亮起并熄灭,如此循环;
P2 = ~(0x01<<i);
}
}
}
方案三:
使用 crol( )------循环左移函数,_cror_是循环右移,后面写上变量的名称、移动的位数
常见于流水灯等编程中;
cpp
#include <at89c51RC2.h>
#include <intrins.h>
// 延时函数(原代码不变)
void Delay1ms(unsigned int ms) //@11.0592MHz
{
unsigned char data i, j;
while(ms--)
{
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
void main()
{
//所有51单片机的局部变量,都建议在函数开头集中定义
unsigned char i;
while(1)
{
P2 = 0xfe; //0xfe = 1111 1110
for(i=0;i<=8;i++)
{
Delay1ms(500); // 延时500ms
P2 = _crol_(0xfe,i);
}
}
}