目录
一、原理介绍
1、LED灯的原理
LED灯称为发光二极管,具有单向导通性。当给D1发光二极管加上正向电压,它的电流方向是从左往右的,通过二极管内的电子与空穴的复合,形成电流释放能量,就可以发出特定颜色的光,释放的能量越多,光的波长就越短,从而使光的颜色不同。
LED自身也有电阻,会分走部分电压,电源所提供的电压必须大于二极管的管压降,二极管才有可能发光。硅管的管压降一般为0.7V,锗管的管压降一般为0.3V。
2、电阻R1的作用
R1电阻的作用是限制电流过大,防止LED电流过大被烧坏。
3、为什么D2二极管不用外接电阻?
D2二级管的正极接在引脚,负极接地,单片机的引脚的输出电流有限,不用考虑电流过大的情况。不过实际上不会采用这种接法,因为单片机输出电流是有限的,这样接无法同时点亮多个LED灯,还可能影响到单片机其他模块的运行,
4、点灯原理
对于D1二极管:当引脚置为0时,两边电压差为5V,那么实际近似电流就I=(5V-二极管管压降)/(R1+二极管电阻),这样二极管就会发光。
对于D2二极管:引脚为1,即可点灯成功。
二、点亮一个LED灯
博主购买的单片机是STC89C52RC,但是商家给的是51单片机的资料,均属于51系列,基本上没啥差别。
看一下原理图和LED模块:
电路分析
首先看LED模块,左侧是电源正极,当引脚输出低电平时,LED灯亮。本次实验我想控制D1亮,其他二极管不亮。
写法1:写明P2口每一位的状态
#include <reg52.h>
void main()
{
while(1)
{
P2=0xFE;//1111 1110
}
}
D1灯属于二进制的末位,可以用这种16进制的写法。
写法2:控制单个引脚
#include <reg52.h>
sbit LED1=P2^0;
void main()
{
while(1)
{
LED1=0;
}
}
三、LED灯闪烁
51单片机的晶振为12Mhz,一个时钟周期=1/12us,一个机器周期=12个时钟周期=1us。
单次延迟时间=123*8*1us≈1ms(包含后置加加的时间)
本次使用D1和D2两个LED灯循环闪烁。
代码
#include <reg52.h>
#define uint unsigned int
sbit LED1=P2^0;
sbit LED2=P2^1;
//延时1ms函数
void delay_1ms()
{
int i=0;
for(i=0;i<123;i++)
{
}
}
//自定义延时时间函数
void delay_ms(uint t)
{
while(t--)
{
delay_1ms();
}
}
void main()
{
while(1)
{
//交替闪烁
LED1=0;
LED2=1;
//休眠
delay_ms(1000);
//交替闪烁
LED1=1;
LED2=~LED2;//也可以写成这种取反的方式
//休眠
delay_ms(1000);
}
}
四、流水灯
写法1:使用数组
#include <reg52.h>
#define uchar unsigned char
//延时1ms函数
void delay_1ms()
{
int i=0;
for(;i<123;++i);
}
//自定义延时时间函数
void delay_ms(unsigned int t)
{
while(t--)
{
delay_1ms();
}
}
void main()
{
uchar arr[8]={0XFE,0XFD,0XFB,0XF7,0XEF,0XDF,0XBF,0X7F};
while(1)
{
int i=0;
for(;i<8;++i)
{
P2=arr[i];
delay_ms(500);
}
}
}
将8种LED灯的状态写成16进制,存储在一个数组中,使用循环遍历修改P2引脚的状态,每个LED亮0.5秒,达到流水灯的效果。
写法2:移位运算符
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
void delay_1ms()
{
int i=0;
for(;i<123;++i);
}
void delay_ms(unsigned int t)
{
while(t--)
{
delay_1ms();
}
}
void main()
{
uchar m=0XFE;
while(1)
{
int i=0;
for(;i<8;++i)
{
P2=m;
m=_crol_(m,1);//左移库函数
delay_ms(500);
}
}
}
使用库函数的方法点流水灯,当然这个移位也可以自己写:
void main()
{
while(1)
{
uchar m=0X01;//0000 0001
int i=0;
for(;i<8;++i)
{
P2=~m;
m<<=1;
delay_ms(500);
}
}
}
五、独立按键+点灯
1、独立按键原理
独立按键相当于一根导线,未按下时,左侧为高电平,右侧为低电平;一旦按下按键,对应引脚将会检测到低电平。所以独立按键的核心思想就是判断引脚的高低电平。
本次实验按下K1按键,D1亮;按下K2按键,D2亮。
2、按键消抖
机械开关的断开和闭合时,由于机械触点的弹性作用,开关在闭合和断开时不会马上稳定的接通。
以按下按键为例,接通瞬间,引脚接收到的电平是忽高忽低的状态,就好像我们多次按下了按键。所以我们写代码的时候,需要判断的是开关稳定闭合后的引脚电平状态。通过延时函数达到代码消抖的功能。
3、代码
#include <reg52.h>
sbit LED1=P2^0;
sbit LED2=P2^1;
sbit K2=P3^0;
sbit K1=P3^1;
void delay_1ms()
{
int i=0;
for(;i<123;++i);
}
void delay_ms(unsigned int t)
{
while(t--)
{
delay_1ms();
}
}
void main()
{
while(1)
{
if(K1==0)
{
delay_ms(20);//延时消抖,防止按键勿扰动(消抖)
if(K1==0)//如果if仍成立,说明按键确实被按下了
{
LED1=0;
LED2=1;
while(K1==0);//等待按键弹起
//while后不用消抖是因为再次进入一个if都会判断抖动,否则需要判断断开的抖动
}
}
if(K2==0)//原理同上
{
delay_ms(20);
if(K2==0)
{
LED1=1;
LED2=0;
while(K2==0);
}
}
}
}