学习目标
- 理解数码管电路原理
- 理解74HC595移位寄存器原理
- 了解74HC595移位寄存器电路设计
- 加强二进制操作
- 驱动74HC595移位寄存器控制数码管
学习内容
数码管结构
共阴与共阳
共阳数码管是指将所有发光二极管的阳极接到一起,形成公共阳极(COM)的数码管,共阳数码管在应用的时候,应该将 COM 端口接到正极,当某一段发光二极管的阴极为低电平的时候,相对应的段就点亮,当某一字段的阴极为高电平的时候,相对应段就不亮。1位数码管
2位数码管
4位数码管
移位寄存器
74HC595 是一款 8 位 CMOS 移位寄存器。8 位并行输出端口为可控的三态输出,一 个串行输出端口,可以实现多级芯片串行控制,组成 8n 位(n 为芯片数量)并行输 。
优点:通过逻辑操作来控制LED的状态,少量的引脚控制更多的状态。
原理图
移位寄存器数据流程
移位寄存器的引脚:
- LATCH_CLOCK: 锁存时钟
- SHIFT_CLOCK: 移位时钟
- A: 数据输入信号管脚
- QA~QH: 数据信号转化出来的高低电平
- SQH: 串行数据输出管脚
上图帮我们认识了几个管脚的作用:
- A:数据信号输入
- QA~QH: 高低电平输出
同时再次加深了我们对74HC595功能的理解:将数据转换为高低电平的一个工具
移位寄存器控制流程
数量流程中,数据变成高低电平过程清楚了。但是数据是给到芯片的,给
这个过程是比较讲究的。
也就是我们传统说法,要按照规矩来传递数据。数据传递是要通过协议的。
我们通过 数据输入信号管脚
(原理图上标记为A)来输入数据。我们必须清楚的知道,一个引脚给数据,其实就是给高低电平信号,一个高低电平信号只能表示一个bit,而我们又8给输出口,理论上需要给8次高低电平才能满足8个端口的输出要求。但是如何去界定8给高低电平呢,就需要用时间去界定。提供了两个引脚:
- LATCH_CLOCK: 锁存时钟引脚
- SHIFT_CLOCK: 移位时钟引脚
移位:由低电平变为高电平,表示记录一个位的电平。
锁存:由低电平变为高电平,表示将记录的数据应用到电路中。
移位寄存器串联
本案例中是有两个移位寄存器U1
和U2
的。分别关注两个移位寄存器的A
和SQH
.
通过流程我们可以明确以下结论:
- 移位寄存器通过
A
输入数据 - 移位寄存器通过
SQH
输出数据 - 两个移位寄存器通过将一个的
SQH
输出到另外一个的输入A
口,两个移位寄存器就串联了 - 末端的移位寄存器输出口悬空表示不输出
- 数据会传递到末端,也就是数据会先填充的是末端。
串联后控制流程需要有所改变,改变如下:
- Logic分析仪
- Digtals
实现数码管显示
#include "Config.h"
#include "GPIO.h"
#include "Delay.h"
#define NIXIE_DI P44 // 数据输入
#define NIXIE_SCK P42 // 移位寄存器
#define NIXIE_RCK P43 // 锁存寄存器
void GPIO_config(void) {
GPIO_InitTypeDef GPIO_InitStructure; //结构定义
GPIO_InitStructure.Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4; //指定要初始化的IO,
GPIO_InitStructure.Mode = GPIO_PullUp; //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
GPIO_Inilize(GPIO_P4, &GPIO_InitStructure);//初始化
}
#define GET_BIT_VAL(byte, pos) (byte & (1 << pos))
int main() {
char i;
u8 a_dat = 0x12; // 0001 0010 字母位 5.
//&1000 0000
u8 b_idx = 0x1F; // 0001 1111 数字位
GPIO_config();
// 显示 7.
// 0111 1000
// 先发字母位 (控制显示的内容)
// 8bit,先发出去的会作为高位
for(i = 7; i >= 0; i--){ // 0点亮
NIXIE_DI = GET_BIT_VAL(a_dat, i);
// 寄存器的移位操作
NIXIE_SCK = 0;
NOP2();
NIXIE_SCK = 1;
NOP2();
}
// 再发数字位 (控制显示哪几个)
// 1111 1011
// 7.7.空7. 7.7.7.7. -------------------与二级制是反向
for(i = 7; i >= 0; i--){ // 只要不是0,就是高电平
NIXIE_DI = GET_BIT_VAL(b_idx, i);
// 寄存器的移位操作
NIXIE_SCK = 0;
NOP2();
NIXIE_SCK = 1;
NOP2();
}
// 锁存操作
NIXIE_RCK = 0;
NOP2();
NIXIE_RCK = 1;
NOP2();
while(1) {
}
}
练习题
- 实现数码管数字显示
- 通过串口控制数码管显示(串口指令,两个字节,一个控制显示,一个控制哪一个灯显示)