MicroPython-On-ESP8266——数码管的使用,2片HC595驱动四位数码管

MicroPython-On-ESP8266——数码管的使用,2片HC595驱动四位数码管

1. 背景

前面在使用四位数码管时,需要用来12个GPIO接口,结果咱micropython能驱动的esp8266开发板只有9个口能用,导致只能驱动两位数码管。还好动态扫描的机制是用到了。

这回来学习第三个数码管,由两片72HC595位移寄存器芯片驱动的四位数码管。

在这里插入图片描述

2. 位移寄存器芯片74HC595

先了解一下这个74HC595芯片(收下简称595)是个什么东西又是如何工作的。

2.1. 595原理图

在这里插入图片描述

符号 引脚 描述
Q0–Q7 第15脚,第1-7脚 8位并行数据输出 (DS引脚送进来的位数据可以依次推入到这8个位,实现了“串入并出”的效果。8个输出刚好可以用来控制数码管的8个段码,或者控制位码(理论上能控制八位的数码管))
GND 第8脚
Q7’ 第9脚 串行数据输出
(移位寄存器只有8个,再继续向里面送数据时,最开始的位会出这个引脚溢出。溢出的位可以送到下一个595芯片,这样就能实现无限串联了。)
/MR 第10脚 主复位(低电平清零数据,通常都是接到VCC用防止数据被清掉)
SH_CP 第11脚 数据输入时钟线
ST_CP 第12脚 输出存储器锁存时钟线
/OE 第13脚 输出有效(低电平有效,通过控制这个引脚可以产生数码管闪烁的效果(一开一关就是闪嘛))
DS 第14脚 串行数据输入(接收数据位的引脚,如果是串联的话就是按上一片595芯片的Q7’引脚)
VCC 第16脚 电源

2.2. 595使用流程

上面引脚说明里面,已经把除了 SH_CP 和 ST_CP 之外其他引脚的注意事项写进去了,最核心的两个单独说明一下:

首先595芯片是有两个寄存器的:

  • 移位寄存器:负责将DS引脚当前的数据状态推入到Q0数据位,同时Q0->Q1->Q2–>Q3–>…–>Q7会依次都向后推一位,可以想象成左轮手枪,你塞一颗子弹就要轮一下轮子再塞下一颗子弹,每轮一下那所有子弹的位置就都顺移了一下。
  • 存储寄存器:把当前输出到位移寄存器中的数据锁定到Qx引脚上并保持不变。就像你把左轮的子弹塞满或不再填充后,把轮子推到枪体上了,那位置就固定下来了。

问题来了,DS引脚用来塞子弹,那啥时候转一轮子(产生位移)、又啥时候把左轮推进去(锁存)呢?这就需要用到595芯片的另外两引脚了。

  • SH_CP(11脚):该引脚上升沿时数据寄存器的数据进行移位。
  • ST_CP(12脚):上升沿时移位寄存器的数据进入数据存储寄存器,下降沿时存储寄存器数据不变。

也就是说咱们平常把这两个引脚的电平置低,需要移位时就把SH_CP拉高一下,需要锁存时就把ST_CP引脚拉高一下,只要很段的时间就可以了。短到微秒级别,咱们在micropython里面都没有微秒级别的延时函数,直接不延时就行了。

3. 两片595驱动数码管的原理

咱们从手上这个数码管模块的原理图来分析
在这里插入图片描述
1)首先它这里对引脚名称的定义跟上面不一样,没关系,仔细对比一下就看明白了:

  • SER引脚就是DS引脚,用来装子弹的,在封装的模块上引出弯头针对,丝印名是DIO
  • SCLK引脚用来控制位移
  • RCLK引脚用来控制锁存到Qx数据口
  • QA-QH共8个数据输出口(跟上面Q0-Q7一样的)

2)上半部分数码

### 使用74HC595驱动两位数码管显示的代码示例 以下是基于ESP32平台的一个简单示例,展示如何通过74HC595移位寄存器来驱动两个7段数码管并显示数字。 #### 初始化GPIO引脚 为了控制74HC595,需要定义三个主要的GPIO引脚:`DS`(数据输入)、`SH_CP`(时钟信号)以及`ST_CP`(锁存信号)。这些引脚分别对应于74HC595的数据传输机制[^1]。 ```cpp #include <Arduino.h> // 定义74HC595所需的GPIO引脚 const int DS_Pin = 18; // 数据引脚 (Serial Data Input) const int SH_CP_Pin = 19; // 存储寄存器时钟引脚 (Shift Register Clock) const int ST_CP_Pin = 5; // 锁存寄存器时钟引脚 (Latching Pin) // 数码管字形编码表 byte digitSegments[] = { B00000011, // 0 B10011111, // 1 B00100101, // 2 B00001101, // 3 B10011001, // 4 B01001001, // 5 B01000001, // 6 B00011111, // 7 B00000001, // 8 B00001001 // 9 }; void setup() { pinMode(DS_Pin, OUTPUT); pinMode(SH_CP_Pin, OUTPUT); pinMode(ST_CP_Pin, OUTPUT); digitalWrite(ST_CP_Pin, LOW); // 初始状态设置为低电平 } void shiftOut(byte dataPin, byte clockPin, byte value) { for(int i=0;i<8;i++) { digitalWrite(clockPin, LOW); digitalWrite(dataPin, ((value << i) & 0x80) ? HIGH : LOW); digitalWrite(clockPin, HIGH); } } void displayNumber(int number, bool isSecondDigit=false){ if(number >=0 && number <=9){ digitalWrite(ST_CP_Pin, LOW); // 如果是第二个数码管,则点亮对应的选通端口 if(isSecondDigit){ shiftOut(DS_Pin, SH_CP_Pin, digitSegments[number]); shiftOut(DS_Pin, SH_CP_Pin, B11111110); // 假设第二位数码管由最低位置激活 }else{ shiftOut(DS_Pin, SH_CP_Pin, digitSegments[number]); shiftOut(DS_Pin, SH_CP_Pin, B11111101); // 假设第一位数码管由次低位激活 } digitalWrite(ST_CP_Pin, HIGH); delay(1); digitalWrite(ST_CP_Pin, LOW); } } void loop(){ for(int num=0;num<=99;num++){ int firstDigit=num/10; int secondDigit=num%10; displayNumber(firstDigit, false); displayNumber(secondDigit, true); delay(500); } } ``` 上述代码实现了从0到99之间的数值循环显示功能。其中,`digitSegments`数组存储了每一位数字符号所对应的二进制模式;函数 `displayNumber()` 负责向74HC595发送相应的数据以更新当前显示的内容。 ### 注意事项 - 上述程序假设每位数码管都连接到了不同的输出通道上,并且可以通过改变最后一位的值来进行切换。 - 实际电路设计可能有所不同,请根据实际接线调整代码中的逻辑部分。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值