目录
(2)功能:(具体看真值表就能懂,就是简单的集成的多路与非门)
一、硬件部分了解:(有些引脚已经被接好,初学者不用了解)
1、74HC573锁存器:
(1)原理图:
图1
(2)功能:
(a)LE控制锁存(不管之后输入什么数据,之后保持输出都之前输入的数据)还是数据改变
(b)D0-D7确定改变的数据,其中D0-D7与Q0-Q7一一对应(正输出)
(3) 使用锁存器原因
由于单片机IO口有限,所以要利用锁存器,让一个IO口可以控制多个外设
2、SN74HC02DRG4四路二输入或非门
(1)原理图:
图2
(2)功能:(具体看真值表就能懂,就是简单的集成的多路或非门)
3、74HC138译码器:
(1)原理图:
图3
(2)功能:
实现用A0-A2控制Y0-Y7,其中对应方式是以二进制与十进制的对应方式,如100控制Y4=0,其他都为1(反输出)
(3) 使用译码器原因:
与锁存器类似的,使用译码器是为了让1个IO口可以扩展成多个IO口
4、整体电路理解:
由图1可知发光二极管一端接着vcc,由基本电路可是可知,那么就要在另一端施加低电平且构成回路以产生正向电流,使发光二极管亮。
由于输出口不是与IO口直接相连,所以我们要使锁存器处于数据可改变状态即LE为高电平,而LE由Y4C控制。
由图2可知,Y4C的输出由SN74HC02DRG4决定,即Y4和WR决定。其中WR由J13,我们在这里选择IO扩展模式,所以选择将2和3短接,即WR接GND,Y4C输出与WR无关;而由图3可知,Y4由译码器控制。
当单片机向译码器输入100时,Y4=0——》Y4C=1——》LE=1——》锁存器处于数据可改变状态——》向任意P0口输入低电平——》LED灯亮
二、参考代码:
实现功能:使八个LED灯顺序点亮,然后再顺序熄灭,最后全部闪三下
1、代码思路:
确认J13外部跳帽连接着IO,令P27=1,P26=0,P25=0,使LE=1,锁存器处于数据改变状态,P0口控制灯的亮灭
2、宏定义:
#ifndef _PUBLIC_H
#define _PUBLIC_H
#include <reg52.h>
#define u8 unsigned char
#define u16 unsigned int
void Delay_1ms(u16 num);
#endif
#include "Public.h"
// 延时函数(最小约1ms@12MHz)
void Delay_1ms(u16 num)
{
unsigned int i;
while(num--)
for(i=0; i<628; i++);
}
3、主函数:
// 使用程序前,将J13调整为IO模式(2-3脚短接)
#include "reg52.h"
#include "Public.h"
sbit HC138_A2=P2^7;
sbit HC138_A1=P2^6;
sbit HC138_A0=P2^5;
void LED_LE_ON();
void LE_OFF();
void Buzzer_LE_ON();
// 主函数
void main(void)
{
u8 i;
while(1)
{
//关闭蜂鸣器
Buzzer_LE_ON();
P0=0x00;
LED_LE_ON();
//顺序点亮
for(i=0;i<=8;i++)
{
P0=0XFF<<i;
Delay_1ms(100);
}
Delay_1ms(800);
//顺序熄灭
for(i=0;i<=8;i++)
{
P0=~(0XFF<<i);
Delay_1ms(100);
}
Delay_1ms(800);
//全部连续闪三下
for(i=0;i<3;i++)
{
P0=0x00;
Delay_1ms(300);
P0=0xff;
Delay_1ms(300);
}
Delay_1ms(800);
LE_OFF();
}
}
void LED_LE_ON()
{
HC138_A2=1;
HC138_A1=0;
HC138_A0=0;
}
void Buzzer_LE_ON()
{
HC138_A2=1;
HC138_A1=0;
HC138_A0=1;
}
void LE_OFF()
{
HC138_A2=0;
HC138_A1=0;
HC138_A0=0;
}
更新:
4、参考代码(模块化):
(1)宏定义:
#ifndef _PUBLIC_H
#define _PUBLIC_H
#include <reg52.h>
#define u8 unsigned char
#define u16 unsigned int
void Delay_1ms(u16 num);
void Close_All(void);
void Delay_10us(u16 num);
#endif
#include "Public.h"
// 延时函数(最小约1ms@12MHz)
void Delay_1ms(u16 num)
{
unsigned int i;
while(num--)
for(i=0; i<628; i++);
}
/*
输入变量:无
输出变量:无
功能:关闭蜂鸣器和继电器
*/
void Close_All(void)
{
//关闭蜂鸣器和继电器
P0 = 0x00;
P2 = (P2 & 0x1f) | 0xA0;
P2 &= 0x1f;
//关闭LED灯
P0 = 0xff;
P2 = (P2 & 0x1F) | 0x80;
P2 &= 0x1f;
}
void Delay_10us(u16 num)
{
u16 i;
while(num--)
for(i=0; i<3; i++);
}
(2)主函数:
// 使用程序前,将J13调整为IO模式(2-3脚短接)
#include "reg52.h"
#include "Public.h"
void LED_ON(u8 L_X);
// 主函数
void main(void)
{
u8 i;
Close_All();
while(1)
{
//顺序点亮
for(i=0;i<=8;i++)
{
LED_ON(0XFF<<i);
Delay_1ms(100);
}
Delay_1ms(800);
//顺序熄灭
for(i=0;i<=8;i++)
{
LED_ON(~(0XFF<<i));
Delay_1ms(100);
}
Delay_1ms(800);
//全部连续闪三下
for(i=0;i<3;i++)
{
LED_ON(0x00);
Delay_1ms(300);
LED_ON(0xff);
Delay_1ms(300);
}
Delay_1ms(800);
}
}
/*
输入变量:P0口的对应的16进制数
输出变量:无
功能:选择相应的锁存器后,通过P0口控制LED灯亮
*/
void LED_ON(u8 L_X)
{
P0 = L_X;
P2 = (P2 & 0x1f) | 0x80;
P2 &= 0x1f;//用完就关,随手关门从我做起
}
补充:
- 如果要灯闪烁,记得灯灭的时候也要记得延时,延时0.5秒最合适
更新:
通过对位操作理解的加深,更新了一个控制某个LED灯翻转,但不影响其他LED灯的函数:
// 使用程序前,将J13调整为IO模式(2-3脚短接)
#include "reg52.h"
#include "Public.h"
void LED_ON(u8 L_X);
void LED_ON_Lx(u8 L_X);
u8 last_led = 0xff;
// 主函数
void main(void)
{
u8 i;
Close_All();
while(1)
{
//顺序点亮
for(i=0;i<=8;i++)
{
LED_ON_Lx(i);
Delay_1ms(100);
}
Delay_1ms(800);
//顺序熄灭
for(i=0;i<=8;i++)
{
LED_ON_Lx(i);
Delay_1ms(100);
}
Delay_1ms(800);
//全部连续闪三下
for(i=0;i<3;i++)
{
LED_ON(0x00);
Delay_1ms(300);
LED_ON(0xff);
Delay_1ms(300);
}
Delay_1ms(800);
}
}
/*
输入变量:P0口的对应的16进制数
输出变量:无
功能:选择相应的锁存器后,通过P0口控制LED灯亮
*/
void LED_ON(u8 L_X)
{
P0 = L_X;
P2 = (P2 & 0x1f) | 0x80;
P2 &= 0x1f;
}
/*
输入变量:Lx灯翻转
输出变量:无
功能:选择相应的锁存器后,通过P0口控制某个LED灯翻转,但不影响其他LED灯
注意:使用前要对last_led进行宏定义
*/
void LED_ON_Lx(u8 L_X)
{
//由于P0口是公用的口,我们要对每次点灯的数据进行记录,不然会受其他操作的影响
P0 = last_led ^ (0x01<<(L_X-1));
last_led = P0;
P2 = (P2 & 0x1f) | 0x80;
P2 &= 0x1f;
}