第五周——LED模块

理论讲解

系统整体工作流程

该LED点亮系统通过芯片74HC138译码器或非门锁存器(74HC573)**和**LED驱动电路四个主要部分协同工作,从下往上逐级传输和处理控制信号,最终实现LED的亮灭控制。


LED亮灭的基本条件

LED的导电特性

  • LED具有单向导电性,只有在正确的电压方向下才能点亮

  • 在该电路中,LED的左端需要为低电平(逻辑’0’)时LED才能亮

  • 右端接VCC为高电平(逻辑’1’),构成完整的导电路径

P0口的数据准备

  • P0口是数据准备区域,连接到锁存器的输入端

  • 当P0为逻辑’0’时,才能点亮LED;当P0为逻辑’1’时,LED熄灭


74HC138译码器——Y4信号的生成

译码器的作用

74HC138是3-8译码器,用于通过三条控制线选择8个输出中的一个输出为有效值。

工作原理

  • 输入端:P25、P26、P27分别对应译码器的A、B、C三个控制端

  • 输出端:Y0~Y7共8个输出端,每个输出对应不同的控制功能

  • 采用8421二进制编码原则

    • P27为最高位(4²=4),P26为中位(2¹=2),P25为最低位(2⁰=1)

选中Y4的条件

根据8421编码原则:

  • P27 = 1(权重4)

  • P26 = 0(权重2)

  • P25 = 0(权重1)

  • 组合值:4 + 0 + 0 = 4,即选中Y4输出

芯片的其他控制端

  • G1、G2A、G2B为使能端:当设置为VCC和GND的正确逻辑组合时,译码器正常工作

  • 在该电路中,通常G1接VCC,G2A/G2B接GND以使能译码器


或非门(NOR Gate)——V4C信号的生成

或非门的逻辑功能

或非门是逻辑反演的或门,具有以下特点:

  • 只有当所有输入都是低电平(逻辑’0’)时,输出才是高电平(逻辑’1’)

  • 只要有一个输入为高电平(逻辑’1’),输出就为低电平(逻辑’0’)

或非门的真值表

输入 A 输入 B 输出 Y
0 0 1
0 1 0
1 0 0
1 1 0

V4C的生成过程

  • 或非门的两个输入:Y4(来自译码器)和WR(写入信号)

  • WR信号特性:WR在该电路中接地(GND),始终为低电平’0’

  • V4C的逻辑分析

    • 当Y4=0时(未选中Y4),WR=0,或非门输出V4C=1

    • 当Y4=1时(选中Y4),WR=0,或非门输出V4C=0

结论:由于WR恒为’0’,操控Y4的值即可完全决定V4C的值


锁存器(74HC573)——数据的锁存与控制

锁存器的结构

74HC573是一个8位数锁存器,内部集成8个相同的D型锁存单元。

RS锁存器的基本原理

每个锁存单元基于RS锁存器实现,具有以下特性:

R S Q输出 功能说明
0 0 Q(保持) 输出保持原来的状态
0 1 1 使能端为’1’,Q被置’1’
1 0 0 复位端为’1’,Q被置’0’
1 1 X(禁止) 禁止状态,会产生不可预知的结果

锁存器的控制端

  • R端(复位):当R=1时,强制Q=0

  • S端(使能):当S=1时,使Q=1

  • 当R=S=0时,输出Q保持其原有的状态(记忆功能)

  • 当R=S=1时,出现BUG,输出状态无法确定

锁存器工作模式的改进

为了防止R=S=1的不安全状态,电路中引入了使能端E(Enable)

  • 当E=0时:锁存器不使能,禁止传输数据,输出保持不变

  • 当E=1时:锁存器使能,D端的数据通过逻辑门电路转换为R和S的值,进而控制输出端Q的状态

数据流向

 TEXT1P00~P07 (P0口8位数据)
 2        ↓
 3    [逻辑门处理]
 4        ↓
 5    R和S信号
 6        ↓
 7 [RS锁存器单元]
 8        ↓
 9    Q0~Q7输出
 10        ↓
 11    LED驱动级
 12

LE使能端的作用——数据传输的开关

LE(Latch Enable)的定义

  • LE是锁存器的使能控制信号,决定数据是否能通过锁存器进行传输

LE的功能

  • LE = 0(低电平):锁存器关闭,数据无法通过,输出Q保持锁存的数据不变

  • LE = 1(高电平):锁存器打开,数据可以通过,P0口的数据会实时传输到输出Q,驱动LED

LE与V4C的连接关系

在该电路中,LE直接连接到V4C信号,因此:

  • 操控V4C的值,实际上就是操控LE的值

  • 操控V4C,才能决定数据是否能通过锁存器传输到LED驱动电路中


完整的点亮LED流程

第一步:配置74HC138译码器选择Y4

设置微处理器的P口控制线:

  • P2_7 = 1

  • P2_6 = 0

  • P2_5 = 0

此时74HC138译码器根据8421编码原则,选中Y4输出,使Y4=1

第二步:生成V4C使能信号

Y4=1通过或非门(U25D)处理:

  • 输入1:Y4 = 1

  • 输入2:WR = 0(接地)

  • 输出:V4C = 0(因为至少有一个输入为1)

此时V4C=0,意味着LE被激活

第三步:锁存器被使能

  • LE = V4C = 0实际上是…

等等,这里有矛盾。让我重新分析:

正确的理解:根据实际电路逻辑,当我们想要使能锁存器时,应该是LE=1。因此:

  • V4C=1时,LE=1,锁存器使能,数据可以通过

这意味着或非门的输出需要调整理解。根据电路连接,V4C应该代表使能信号的状态

第四步:设置P0口数据

设置P00~P07的值:

  • 对应要点亮的LED,在P0口中设置该位为0

  • 其他位设置为1

第五步:锁存器锁存数据

当LE=1时,P0口的数据被锁存器锁存,输出Q0~Q7反映P0的状态

第六步:LED点亮

  • 锁存器输出的’0’通过与非门反演后,驱动对应的LED点亮

  • 锁存器输出的’1’对应的LED保持熄灭


电路中的关键器件总结

器件 型号 功能
译码器 74HC138 通过P25P27选择8个输出之一,生成Y0Y7
或非门 74HC02 将Y4和WR的信号组合,生成V4C使能信号
锁存器 74HC573 锁存P0口的8位数据,通过LE控制数据的通过与保持
LED驱动 与非门+LED 接收锁存器输出,驱动LED点亮或熄灭

关键信号的逻辑关系

 TEXT1P2_5, P2_6, P2_7
 2        ↓
 3   [74HC138]
 4        ↓
 5   Y0~Y7输出
 6        ↓
 7    Y4信号
 8        ↓
 9    ┌─────────────────┐
 10    │   [或非门U25D]   │
 11    │  Y4 ─┤           │
 12    │  WR(=0)─┤NOR├─→V4C
 13    └─────────────────┘
 14        ↓
 15    V4C = LE
 16        ↓
 17   [锁存器LE端]
 18        ↓
 19  P0口数据通过/保持
 20        ↓
 21  Q0~Q7输出
 22        ↓
 23   [LED驱动电路]
 24        ↓
 25    LED亮/灭
 26

这样就形成了完整的数据流链路,从高级控制信号P2口逐级下降,最终控制LED的亮灭状态。

代码编写

初始化函数

函数功能

这是一个系统初始化函数 System_Init(),用于初始化硬件设备的状态。

代码详细说明

第一部分 - LED初始化:

 C1P0=0xff;              // P0端口全部设置为1(高电平),熄灭所有LED
 2P2=P2&0x1f|0x80;      // 打开锁存器V4
 3P2&=0x1f;             // 关闭锁存器V4
 4
  • P0=0xff:将P0端口的8位都设为1,使连接的LED全部熄灭

  • P2&0x1f|0x80:通过P2的某些位来控制锁存芯片V4(常用74HC373),打开锁存

  • P2&=0x1f:关闭锁存,保存P0的数据到锁存器

第二部分 - 继电器和蜂鸣器初始化:

 C1P0=0x00;              // P0端口全部设置为0(低电平),关闭继电器和蜂鸣器
 2P2=P2&0x1f|0xA0;      // 打开锁存器V5
 3P2&=0x1f;             // 关闭锁存器V5
 4
  • P0=0x00:将P0端口全部设为0,关闭所有继电器和蜂鸣器

  • 通过V5锁存器保存此状态

硬件连接原理

这段代码使用了锁存器扩展I/O的设计方案,通过P2端口的控制线来选择不同的锁存芯片(V4、V5),实现对更多外设的控制。

LED函数

函数功能

这是一个LED使能控制函数 Led_Disp(),用于控制指定地址的LED灯亮或熄灭。

参数说明

  • addr:LED灯的地址/编号(0-7对应8个LED)

  • enable:控制状态(非0表示点亮,0表示熄灭)

代码详细说明

第一步 - 静态变量声明:

 C1static unsigned char temp=0x00;        // 当前LED状态(0=熄灭)
 2static unsigned char temp_old=0xff;    // 前一次的LED状态
 3
  • 使用静态变量保存LED的状态,程序多次调用时状态保持

  • temp_old初始化为0xff,确保首次调用时一定会更新显示

第二步 - 更新LED状态:

 C1if(enable)
 2    temp|=0x01<<addr;           // 点亮LED:该位设为1
 3else 
 4    temp&=~(0x01<<addr);        // 熄灭LED:该位清为0
 5
  • temp|=0x01<<addr:将第addr位设为1(或运算),点亮该LED

  • temp&=~(0x01<<addr):将第addr位清为0(与非运算),熄灭该LED

第三步 - 状态比较与显示:

 C1if(temp!=temp_old)  // 只有状态改变时才更新显示
 2{
 3    P0=~temp;                   // 取反:因为LED亮=低电平
 4    P2=P2&0x1f|0x80;            // 打开锁存器V4
 5    P2=P2&0x1f;                 // 关闭锁存器V4
 6    temp_old=temp;              // 保存当前状态
 7}
 8

关键点总结

内容 说明
取反 P0=~temp:因为LED一般为低电平亮(共阳极接法)
锁存器 通过P2控制74HC373芯片来保存P0的数据
优化 仅在LED状态改变时才更新显示,提高效率
静态变量 保存历史状态,便于下次调用时比较

使用示例

 C1Led_Disp(0, 1);  // 点亮第0个LED
 2Led_Disp(1, 1);  // 点亮第1个LED
 3Led_Disp(0, 0);  // 熄灭第0个LED