Ch552 控制 HPDL-1414 的计数器
这次带来的设计是基于 Ch552 的 HPDL-1414 数码管计数器。HPDL-1414 是一款历史悠久的数码管显示器,和最常见的7段数码管不同,它除了能够显示数字之外,因为有着足够的线段,还能显示英文字符。HPDL-1414 控制很简单,通过 GPIO 就可以选择点亮那些数码段组成。接下来的问题就是:对于CH552来说,GPIO 引脚不够。传统的扩展方法是使用I2C或者 74HC595 来进行扩展,这次选择的是ESR1117:这是一款国产串口GPIO芯片。显而易见的是:相比其他接口,通过串口扩展GPIO的方案更加简单方便。我们只需要将 TX RX 交叉连接之后即可。最终的电路设计如下:
除了支持 HPDL-1414 进行显示,还预留了3个 WS2812B 的位置,可以通过代码控制这些灯的颜色。
完整代码如下:
uint16_t Ascii2GPIO(uint8_t data, uint8_t pos)
{
uint16_t Esr = 0;
Esr = pos << 2;
if ((data & (1 << 0)) != 0) {
Esr = Esr | (1 << 1); //D0
}
if ((data & (1 << 1)) != 0) {
Esr = Esr | (1 << 0);
}
if ((data & (1 << 2)) != 0) {
Esr = Esr | (1 << 9);
}
if ((data & (1 << 3)) != 0) {
Esr = Esr | (1 << 8);
}
if ((data & (1 << 4)) != 0) {
Esr = Esr | (1 << 5);
}
if ((data & (1 << 5)) != 0) {
Esr = Esr | (1 << 4);
}
if ((data & (1 << 6)) != 0) {
Esr = Esr | (1 << 7);
}
return Esr;
}
void output(uint8_t HiByte, uint8_t LowByte) {
USBSerial_print("Serial out, HI:[");
USBSerial_print(HiByte, HEX);
USBSerial_print("] Low[");
USBSerial_print(LowByte, HEX);
USBSerial_println("]");
// GPIO 先准备好,RW 设置为HIGH,防止误动作
Serial0_write(0x3F); Serial0_write(0xC0); Serial0_write(0x98 | HiByte); Serial0_write(LowByte | 0b01000000);
USBSerial_print(LowByte, HEX);
delay(10);
// RW 设置为LOW, ESR 会直接拉GPIO
Serial0_write(0x3F); Serial0_write(0xC0); Serial0_write(0x98 | HiByte); Serial0_write(LowByte);
USBSerial_print(LowByte | 0b01000000, HEX);
delay(10);
// RW 设置为HIGH, RW 设置为HIGH,防止误动作
Serial0_write(0x3F); Serial0_write(0xC0); Serial0_write(0x98 | HiByte); Serial0_write(LowByte | 0b01000000);
delay(10);
}
void setup() {
Serial0_begin(9600);
delay(2000);
// GPIO 设置为 OUTPUT
Serial0_write(0x3F); Serial0_write(0xC0); Serial0_write(0x8F); Serial0_write(0xFF);
delay(10);
uint16_t c;
// 清除第1位显示(输出一个空格)
c = Ascii2GPIO( ' ', 0);
output(c >> 8, c & 0xFF);
// 清除第2位显示(输出一个空格)
c = Ascii2GPIO(' ', 1);
output(c >> 8, c & 0xFF);
// 清除第3位显示(输出一个空格)
c = Ascii2GPIO(' ', 2);
output(c >> 8, c & 0xFF);
// 清除第4位显示(输出一个空格)
c = Ascii2GPIO(' ', 3);
output(c >> 8, c & 0xFF);
delay(2000);
USBSerial_println("Start");
}
uint16_t Counter = 0;
uint16_t OldCounter = 0;
void loop() {
USBSerial_print("Counter");
USBSerial_println(Counter);
uint16_t c;
c = Ascii2GPIO(Counter % 10 + '0', 0);
output(c >> 8, c & 0xFF);
// 只在发生变化时才更新,减少闪烁感
if (((Counter / 10) % 10) != (OldCounter / 10) % 10) {
c = Ascii2GPIO((Counter / 10) % 10 + '0', 1);
output(c >> 8, c & 0xFF);
}
if (((Counter / 100) % 10) != (OldCounter / 100) % 10) {
c = Ascii2GPIO((Counter / 100) % 10 + '0', 2);
output(c >> 8, c & 0xFF);
}
if (((Counter / 1000) % 10) != (OldCounter / 1000) % 10) {
c = Ascii2GPIO((Counter / 1000) % 10 + '0', 3);
output(c >> 8, c & 0xFF);
}
OldCounter=Counter;
Counter++;
if (Counter > 9999) {
Counter = 0;
OldCounter=0;
}
}
成品如下:
这个作品制作简单,有兴趣的朋友可以尝试自行完成
工作的测试视频
https://www.bilibili.com/video/BV1Xz4y1V7yT/?share_source=copy_web&vd_source=5ca375392c3dd819bfc37d4672cb6d54
页:
[1]