一.点亮一个LED
(直插式、贴片式)
中文名:发光二极管
用途:照明、广告灯、指示灯、屏幕
471=47*10=470Ω,限流,保护电路47*1000
共阳极,输入0,点亮
控制寄存器P2,十六进制
例.点亮D0: P2=0XFE;//1111 1110
二.LED闪烁
#include <reg52.h> //定义单片机的一些特殊功能寄存器
sbit led=P2^0; //定义指定LED灯的管脚
void delay(unsigned int i) //延时函数。unsigned int定义无符号整型,范围0-655535
{
while(i--); //i=1时,大约延时10us
}
void main() //主函数,程序从这里开始执行
{
while(1)
{
led=0; //0表示低电平,共阳极二极管点亮
delay(50000); //大约延时450ms
led=1; //1表示高电平,LED熄灭
delay(50000); //大约延时450ms
}
}
(延时函数可以用编译器自动生成)
三.LED流水灯
法一:移位法
左循环
#include <reg51.h>
void delay(unsigned int i) //延时函数
{
while(i--);
}
void main(void) //主函数,程序从这里开始执行
{
int j; //引入变量,定义字符
while(1)
{
P2=0xfe; //即11111110,将8个LED的状态赋值给P2
delay(50000);
for(j=0;j<8;j++) //循环8次,因为有8个LED灯
{
P2=P2<<1 | 0x01; //实现程序左移1位,或运算,有1为1,全0为0
delay(50000);
}
}
}
按位左移(<<),右边补0,有乘2的效果 1111 1110<<2 1111 1100 0000 0001 1111 1101
按位右移(>>),左边补原符号位,有除2的效果
按位或(|),有1为1,全0为0,
按位与(&)
按位异或(^)
按位取反(~)~11111100 00000011
法二:数组法
#include <reg51.h>
unsigned char LED [8] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //定义8个LED灯点亮
void delay(unsigned int i) //延时函数
{
while(i--);
}
void main(void) //主函数,程序从这里开始执行
{
int j;
for(j=0; j<8; j++) //循环函数,实现流水效果
{
P2 = LED[j]; //赋值给LED端口
delay(50000);
P2 = 0xff; // 清屏,使所有LED熄灭
}
}
四.独立按键
(轻触按键)
#include <REGX52.H>
int main(void)
{
while(1)
{
if(P3_1==0) //如果K1按键按下
{
P2_0=0; //LED1输出0,点亮
}
else
{
P2_0=1; //LED1输出1,熄灭
}
}
}
按键抖动
按键消抖:硬件消抖,软件消抖
软件消抖->通过延时
效果:独立按键控制LED亮灭
#include <REGX52.H>
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
xms--;
}
}
int main(void)
{
while(1)
{
if(P3_1==0) //如果K1按键按下
{
Delay(20); //延时消抖20ms
while(P3_1==0); //松手检测
Delay(20); //延时消抖
P2_0=~P2_0; //LED1取反
}
}
}
效果:独立按键控制LED的移位 0000 0010 1111 1101
#include <REGX52.H>
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
int main(void)
{
unsigned char LEDNum = 0;//进行初始化
P2 = 0xFE;
while(1)
{
if(P3_1 == 0) //如果当独立按键K1按下的话 —— LED灯移位
{
Delay(20); //按键消抖20ms
while(P3_1 == 0); //检测松手
Delay(20); //按键消抖
LEDNum++; //自增++
if(LEDNum>=8)
{
LEDNum=0;
}
P2 = ~(0x01<<LEDNum);
}
五.矩阵键盘
(将两端都接到io口上,形成交错矩阵形式,8个io口控制16个按键,减少iO口的占用)
#include <REGX52.H>
#include "Delay.h"
/**
* @brief 矩阵键盘读取按键键码
* @param 无
* @retval KeyNumber 按下按键的键码值
如果按键按下不放,程序会停留在此函数,松手的一瞬间,返回按键键码,没有按键按下时,返回0 !
*/
unsigned char MatrixKey()
{
unsigned char KeyNumber=0;
P1=0xFF;// 1111 1111 全部置高电平默认
P1_3=0; // 矩阵按键第一行扫描
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=1;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=5;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=9;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=13;}
P1=0xFF;
P1_2=0; // 矩阵按键第二行扫描
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=2;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=6;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=10;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=14;}
P1=0xFF;
P1_1=0; // 矩阵按键第三行扫描
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=3;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=7;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=11;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=15;}
P1=0xFF;
P1_0=0; // 矩阵按键第四行扫描
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=4;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=8;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=12;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=16;}
return KeyNumber;
}
六.数码管
本质是多个封装在一起的发光二极管,生活中很常见,应用广泛
上面是共阴,下面是共阳 0110 0000 ->0x06 1101 1000->0x8E
138译码器工作原理
控制ABC(C为高位)三个口,操作某一位
效果:动态显示8位数码管
#include "reg52.h"
#include "intrins.h"
//38译码器A、B、C
sbit sA = P1^0;
sbit sB = P1^1;
sbit sC = P1^2;
//位选控制码表
unsigned char code table[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
//延迟1ms
void delay500us(void) //误差 0us
{
unsigned char a,b;
for(b=71;b>0;b--)
for(a=2;a>0;a--);
}
//显示八数码管
void showDigital()
{
int i;
for(i=0;i<8;i++)
{
switch(i)
{
case(0):
sA = 0;sB = 0;sC = 0;break;
case(1):
sA = 1;sB = 0;sC = 0;break;
case(2):
sA = 0;sB = 1;sC = 0;break;
case(3):
sA = 1;sB = 1;sC = 0;break;
case(4):
sA = 0;sB = 0;sC = 1;break;
case(5):
sA = 1;sB = 0;sC = 1;break;
case(6):
sA = 0;sB = 1;sC = 1;break;
case(7):
sA = 1;sB = 1;sC = 1;break;
}
P0 = table[i+1];
delay500us();
P0 = 0x00;//消影
}
}
void main()
{
while(1)
showDigital();
}
消影:位选 段选 消影 位选 段选 位选 段选
七.定时器
计时系统,实现软件计时;替代Delay,提高CPU运行效率(按键不灵敏)
模式0→13位定时器/计数器。
★模式1→16位定时器/计数器,这个是最常用的一个模式。
★模式2→8位自动重装模式,这个算是第二个最常用的一个模式。第二种模式主要用于串口通信产生波特率来用的『在电子通信领域,波特(Baud)即调制速率,指的是有效数据讯号调制载波的速率,即单位时间内载波调制状态变化的次数』
模式3→两个8位计数器。
第一部分:时钟,SYSclk:系统时钟,即晶振周期,一般51为12MHZ,进行分频,12分频后就是1MHZ,即1us,c计数器,timer定时器
T0 Pin外部接口提供时钟
第二部分:计数,16位,65535,每来一个脉冲就+1,加到最大值就申请中断
第三部分:中断