数码管
一、数码管
-
原理图
1.1 数码管介绍
-
共阴和共阳
特性 共阴极 (Common Cathode) 共阳极 (Common Anode) 公共端接法 所有 阴极(-) 接 地 (GND) 所有 阳极(+) 接 电源 (VCC) MCU控制端 控制 阳极(+) 控制 阴极(-) 点亮条件 MCU输出 高电平 (HIGH) MCU输出 低电平 (LOW) 电流方向 MCU -> 灯 -> 地 电源 -> 灯 -> MCU 俗称 源电流 驱动 (Source Current) 灌电流 驱动 (Sink Current) -
软件仿真
1.2 移位寄存器
-
74HC595工作原理视频:https://www.bilibili.com/video/BV1xZ4y1Z7RP
-
74HC595 是一款 8 位 CMOS 移位寄存器(《74HC595N.PDF》的第2页)
-
将数据转换为高低电平的一个工具
- 通过逻辑操作来控制LED的状态,少量的引脚控制更多的状态
-
控制流程
- 移位:由低电平变为高电平,表示记录一个位的电平
- 锁存:由低电平变为高电平,表示将记录的数据应用到电路中
1.3 数码管操作
1.3.1 数码管显示
- 灵活显示
#include "GPIO.h"
#include "Delay.h"
#define NIX_DI P44 // 数据引脚
#define NIX_RCK P43 // 锁存寄存器引脚
#define NIX_SCK P42 // 移位寄存器引脚
void GPIO_config() {
GPIO_InitTypeDef info;
info.Mode = GPIO_OUT_PP; // 推挽输出
info.Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4; // 引脚
GPIO_Inilize(GPIO_P4, &info);
}
void main() {
char i; // 有-操作,不要用u8
u8 num; // 内容
u8 idx; // 位置
GPIO_config(); // 函数调用
num = 0xf8; // 内容
idx = 0xfb; // 位置
// idx = 0xf0;
// 内容
for (i = 7; i >= 0; i--) {
// 取出第i位,给数据引脚赋值
NIX_DI = num >> i & 1;
// 移位 0 - > 1
NIX_SCK = 0;
NOP2();
NIX_SCK = 1;
NOP2();
}
// 位置
for (i = 7; i >= 0; i--) {
// 取出第i位,给数据引脚赋值
NIX_DI = idx >> i & 1;
// 移位 0 - > 1
NIX_SCK = 0;
NOP2();
NIX_SCK = 1;
NOP2();
}
// 锁存 0 -> 1
NIX_RCK = 0;
NOP2();
NIX_RCK = 1;
NOP2();
while (1){
delay_ms(250);
}
}
1.3.2 自定义码表
- 码表显示
// 索引对应表格参见
u8 code LED_TABLE[] =
{
// 0 1 2 -> 9 (索引012...9)
0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,
// 0. 1. 2. -> 9. (索引10,11,12....19)
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,
// . - (索引20,21)
0x7F, 0xBF,
// AbCdEFHJLPqU (索引22,23,24....33)
0x88,0x83,0xC6,0xA1,0x86,0x8E,0x89,0xF1,0xC7,0x8C,0x98,0xC1
};
案例代码:
#include "GPIO.h"
#include "Delay.h"
#define NIX_DI P44 // 数据引脚
#define NIX_RCK P43 // 锁存寄存器引脚
#define NIX_SCK P42 // 移位寄存器引脚
void GPIO_config() {
GPIO_InitTypeDef info;
info.Mode = GPIO_OUT_PP; // 推挽输出
info.Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4; // 引脚
GPIO_Inilize(GPIO_P4, &info);
}
// 下标为0~9,对应内容也是0~9
// 其它内容,需要查表
u8 code LED_TABLE[] =
{
// 0 1 2 -> 9 (索引012...9)
0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,
// 0. 1. 2. -> 9. (索引10,11,12....19)
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,
// . - (索引20,21)
0x7F, 0xBF,
// AbCdEFHJLPqU (索引22,23,24....33)
0x88,0x83,0xC6,0xA1,0x86,0x8E,0x89,0xF1,0xC7,0x8C,0x98,0xC1
};
void main() {
char i; // 有-操作,不要用u8
u8 num; // 内容
u8 idx; // 位置
GPIO_config(); // 函数调用
// 第7个数码管显示3
num = LED_TABLE[3]; // 内容
// 1 << (n - 1) n 代表第n个数码管,只显示第n个数码管
idx = 1 << (7 - 1); // 位置
// 内容
for (i = 7; i >= 0; i--) {
// 取出第i位,给数据引脚赋值
NIX_DI = num >> i & 1;
// 移位 0 - > 1
NIX_SCK = 0;
NOP2();
NIX_SCK = 1;
NOP2();
}
// 位置
for (i = 7; i >= 0; i--) {
// 取出第i位,给数据引脚赋值
NIX_DI = idx >> i & 1;
// 移位 0 - > 1
NIX_SCK = 0;
NOP2();
NIX_SCK = 1;
NOP2();
}
// 锁存 0 -> 1
NIX_RCK = 0;
NOP2();
NIX_RCK = 1;
NOP2();
while (1){
delay_ms(250);
}
}
2.3.3 数码管驱动封装
Nixie.h代码:
#ifndef __NIXIE_H__
#define __NIXIE_H__
#include "GPIO.h"
// 声明宏变量
#define NIX_DI P44 // 数据输入
#define NIX_SCK P42 // 移位寄存器
#define NIX_RCK P43 // 锁存寄存器
// 初始化
void Nixie_init();
// num: 控制显示的什么内容
// idx: 控制显示哪几个显示
void Nixie_show(u8 num, u8 idx);
// num 对应的内容在数组的位置(索引),配合自定义码表
// 码表https://www.yuque.com/icheima/stc8h/kmz2mllvxs1uvdfy#lLhhp
// 除了0~9,刚好和下标一致,其它的内容,需要查表
// idx 显示在屏幕上的位置(1 -> 8),只有1个数码管显示
void Nixie_display(u8 num, u8 idx);
void Nixie_clear(); // 灯灭
#endif
Nixie.c代码:
#include "Nixie.h"
static void GPIO_config() {
GPIO_InitTypeDef info;
info.Mode = GPIO_OUT_PP; // 推挽输出
info.Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4; // 引脚
GPIO_Inilize(GPIO_P4, &info);
}
// 初始化
void Nixie_init() {
GPIO_config(); // IO
Nixie_clear(); // 灯灭
}
// num: 控制显示的什么内容
// idx: 控制显示哪几个显示
void Nixie_show(u8 num, u8 idx) {
char i; // char 类型
// 内容
for (i = 7; i >= 0; i--) {
// 取出第i位,给数据引脚赋值
NIX_DI = num >> i & 1;
// 移位 0 - > 1
NIX_SCK = 0;
NOP2();
NIX_SCK = 1;
NOP2();
}
// 位置
for (i = 7; i >= 0; i--) {
// 取出第i位,给数据引脚赋值
NIX_DI = idx >> i & 1;
// 移位 0 - > 1
NIX_SCK = 0;
NOP2();
NIX_SCK = 1;
NOP2();
}
// 锁存 0 -> 1
NIX_RCK = 0;
NOP2();
NIX_RCK = 1;
NOP2();
}
// 索引对应表格参见:
// https://www.yuque.com/icheima/stc8h/kmz2mllvxs1uvdfy#lLhhp
// 下标为0~9,对应内容也是0~9
// 其它内容,需要查表
u8 code LED_TABLE[] =
{
// 0 1 2 -> 9 (索引012...9)
0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,
// 0. 1. 2. -> 9. (索引10,11,12....19)
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,
// . - (索引20,21)
0x7F, 0xBF,
// AbCdEFHJLPqU (索引22,23,24....33)
0x88,0x83,0xC6,0xA1,0x86,0x8E,0x89,0xF1,0xC7,0x8C,0x98,0xC1
};
// num 对应的内容在数组的位置(索引),配合自定义码表
// 码表https://www.yuque.com/icheima/stc8h/kmz2mllvxs1uvdfy#lLhhp
// 除了0~9,刚好和下标一致,其它的内容,需要查表
// idx 显示在屏幕上的位置(1 -> 8),只有1个数码管显示
void Nixie_display(u8 num, u8 idx) {
Nixie_show(LED_TABLE[num], 1 << (idx - 1));
}
void Nixie_clear() { // 灯灭
Nixie_show(0xff, 0xff);
}
mian.c代码:
#include "Delay.h"
#include "Nixie.h"
void main() {
Nixie_init(); // 初始化
// ==========原始数据方式显示===========
Nixie_show(0xf8, 0xfb);
delay_ms(250);
delay_ms(250);
delay_ms(250);
delay_ms(250);
// ==========码表+位置方式显示===========
Nixie_display(9, 3); // 第3个数码管显示9
delay_ms(250);
delay_ms(250);
delay_ms(250);
delay_ms(250);
Nixie_clear(); // 灯灭
while (1){
delay_ms(250);
}
}
实现每个数码管输出不同的数字
main.c代码:
#include "Delay.h"
#include "Nixie.h"
void main() {
Nixie_init(); // 初始化
// 2025-08
while (1){
Nixie_display(2, 1);
NOP10();
Nixie_display(0, 2);
NOP10();
Nixie_display(2, 3);
NOP10();
Nixie_display(5, 4);
NOP10();
Nixie_display(21, 5); //-
NOP10();
Nixie_display(0, 6);
NOP10();
Nixie_display(8, 7);
NOP10();
Nixie_clear(); // 灯灭
}
}
void main01() {
u8 i;
Nixie_init(); // 初始化
// // ==========数码管跑马灯===========
// for (i = 1; i <= 8; i++) {
// Nixie_display(i, i);
// delay_ms(250);
// }
//
// Nixie_clear(); // 灯灭
while (1){
// 因为运行太快了,欺骗了眼睛
for (i = 1; i <= 8; i++) {
Nixie_display(i, i);
// delay_ms(1);
NOP10();
}
Nixie_clear(); // 灯灭
}
}