这次带来的设计是基于 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;
- }
- }
复制代码
成品如下:
|