Posted on Leave a comment

CH32V203C8 LED Clock – Part 1

3 April 2025

Time for another clock build. This time I will be using the CH32V203C8T6, as before, but will be driving the seven segment LED display directly, instead of using the TM1637 module.

For the LED display, I will be using a pair of ROHM LB-602MA2 dual digit seven segment displays with right-hand decimal points. The display color is green. These displays use a common anode configuration, although the individual segments are not tied together. This makes them more versatile, because you can wire up each segment separately or multiplex them, as you see fit. I will be multiplexing them.

I’m also going to try a “single segment” display algorithm to try to reduce component count. Only one of the thirty two (32) segments will be on at a given time. I hope that the resulting display is bright enough to be clearly seen. I can think of one good way to find out!

First, I look up the data sheet, which can be found at:

https://fscdn.rohm.com/en/products/databook/datasheet/opto/led_display/numeric/lb-602ak2-e.pdf

Sadly, this product is no longer recommended for new designs. On a happier note, I have a nice stash of them from my “collector” days. I’m really sort of surprised the data sheet was even still available. Good job, ROHM!

Now I have to assign some of the pins of the -203 chip to drive all these segments. The chip’s data sheet says there are 37 available GPIO pins. I’m using two for USART communication, PA9/TX & PA10/RX, at least through the debugging stage. They won’t really be necessary once everything is working properly. I will need to check the schematic of the WeActStudio BluePill+ board again to see what other pins have already been provisioned.

Port A

    User key:  0
    external flash (not connected):  4, 5, 6, 7
    MCO:  8
    USART1:  9, 10
    USB_DN, USB_DP:  11, 12
    SWDIO, SWCLK:  13, 14

Port B

    D1 (blue LED, active high):  2
        also
    BOOT1 (10 KΩ to ground)

Port C

    OSC32_IN, OSC32_OUT:  14, 15

Port D

    OSC_IN, OSC_OUT:  0, 1

So we can see that GPIO port A is already pretty busy. Ports C and D are 80% utilized with connections to quartz crystals, but they barely had any pins to pin with. That leaves us with GPIO Port B, which at the moment is only committed to LED duty. As I’m only going to be configuring these display driver pins as outputs, the existing LED connection should not create a conflict.

I propose a very simple mapping of segment and digit drivers:

PB0     segment a
PB1     segment b
PB2     segment c + blue LED
PB3     segment d
PB4     segment e
PB5     segment f
PB6     segment g
PB7     segment DP (right hand)

PB8     digit 1 (leftmost)
PB9     digit 2
PB10    digit 3
PB11    digit 4

Since the displays are packaged as dual digits, I can separate the two packages by just a smidge and leave room for a dedicated colon, made of two additional green 3mm LEDs.

All this circuit goodness is starting out on a solderless breadboard. If the proposed “single segment drive” methodology proves viable, I am thinking of committing this design to a printed circuit board (PCB). I’ve just ordered some non-differentiated, breadboard-compatible breakout boards for the LPQF48 package for more elaborate wiring experiments using this chip. They are taking about two weeks to be delivered these days.

While I’m developing the circuit and the firmware, the whole things is being powered by the 3.3V DC power output from the WCH-LinkE programming adapter. That’s also how I’m programming the chip and connecting the USART to the serial console. The final version of the prototype will be powered via the USB-C connector on the BluePill+ board along with its on-board 3.3V regulator.

Partially wiring up the LED array for testing, I get absolutely nothing visible. I even break out my trusty multimeter and verify the signal levels going to the display. All looks correct, except that I am reading zero voltage (and therefore zero current) across the current-limiting resistor. I double check the wiring against the manufacture’s data sheet and find everything is connected as it should be.

Then I realize that I’m thinking about this wrong. This has happened before and I predict that it will happen again. These LED displays are configured with a common anode, and I had assigned the signal levels as if they were the common-cathode configuration. The one thing we know about any diode, and let us not forget that LEDs are “light emitting diodes” is that they conduct current in one direction and one direction only.

So I need to swap everything around in the software. The digit drivers will be active high and the segment drivers will be active low. This works. Now would be a good time to define some constants that represent the different level combinations that I will be using, at least for the initial development stage.

Now when I say, “This works,” I mean that when I write a value of 0x01FE to GPIOB’s output register, the segment a1 (segment a, digit 1) lights up… but just barely. My exceedingly cautious self installed relatively high-value resistors (1KΩ) on each of the digit driver pins for the first part of the experiment. Yes, the digit driver pins, not the segment driver pins. A normal person would have attached a high(er) current driver to the digit commons and put the current-limiting resistors in-line with the segment drivers. Then you could light up all the segments of a single digit at once, momentarily, then select the next digit and enable its expected segment driver pins, rotating through the digits fast enough to give the illusion that they were all lit up simultaneously. It’s an optical illusion, but it’s a good one.

But I’m trying something different here. I’m only going to illuminate a single segment at a time and have a 1/32 duty cycle, instead of a 1/4 duty cycle. These ROHM displays are rated up to 60 mA as long as the pulse width is 1 millisecond long and the duty cycle is 1/5. I am assuming that shorter pulse widths and higher duty cycles are OK.

Now would be a good time to measure the actual current flowing throw segment a1. It’s not much. I measure 10 mV (0.010 volts) across the 1KΩ resistor. Ohm’s Law tells us that the current is the voltage divided by the resistance. In this case, the voltage 0.01V divided by the resistance 1KΩ equals the current 10 μA (microamps). In case you were wondering, that’s not very much current at all. I’m actually surprised it was visible at all in normal room lighting.

Part of this smallness can be attributed to the fact that the -203 is operating at 3.3V and the typical forward voltage of each segment of this display is 2.1V, with the maximum being 2.8V. You have to exceed the diode’s forward voltage to get any current flowing at all, and then it’s an exponential relationship between the voltage and current after that.

If I could drive the LEDs with one of the -00X class chips or even the CH32X035, we could be running at 5V and deliver much more voltage to the LED. The main reason I’m not doing that at the moment is that none of those chips has a real-time clock (RTC) peripheral available, or a 32,768 Hz oscillator built in.

Now that does not rule out the possibility of a -00X based LED module driver that is controlled by a chip with RTC capability. But I already did that with the TM1637 module. And those chips by themselves are not especially expensive, and include all the power driving circuitry. So it doesn’t make a lot of sense to re-invent the wheel in this particular situation.

The maximum current rating of each segment at 100% duty cycle is 20 mA. The total power dissipation for the entire package (16 diodes) is 960 mW, or 60 mW per LED. So it’s time to crank up the power, but still in a responsible manner.

Now I measure 0.929 volts across a 100Ω current-limiting resistor. This represents a segment current of 9.29 mA. A younger me would have predicted a current limiting resistor of one tenth the previous value to produce a current ten times larger. I learned the truth about this when I designed my first LED array, which went on to be called variously the “IR Illuminator” or “IR Spotlight”, depending on where you bought one. It was originally an array of four parallel strings of nine infrared (IR) LEDs each. Later, I redesigned it as a 6×6 array for better power performance. My initial predictions of what size of current-limiting resistor were way off from the truth. A good way to learn about such things, I have found.

Now I think we can bump up the current even more, as long as we stay under 20 mA per segment. I measure 0.839 volts across a 75Ω resistor, giving a current of just over 11 mA. Not the doubling I had hoped for. We proceed:

Ohms    Voltage Current
        (volts) (mA)
----    ------- ------
1KΩ     0.010    0.01
100Ω    0.929    9.29
75Ω     0.839   11.00
47Ω     0.671   14.28
22Ω     0.412   18.73

And we have a winner! I think that over 90% of the rated current is plenty. No need to push it to ten tenths for this project. Also, it’s good to note that per the -203 data sheet, the maximum current into or out of any I/O pins is 25 mA, with a device total current of 150 mA. Since the plan is to illuminate only a single segment at a time, and that at only <20 mA, we should be good.

Now at first I found it odd that the voltage across the resistor was going down instead of up. More current means more voltage, yes? If this were a linear circuit, then yes. But as I mentioned before, the relationship between the forward voltage across a diode and the current is decidedly non-linear, and is, in fact, exponential in nature. So the forward voltage of the diode was also going up as the current rose. Tricksy little gizmos, these semiconductors!

Now comes a lot of wiring. It’s a good thing I like this part of the work. It’s something I have been doing for A Long Time Now and I’m starting to think that I’m getting pretty good at it.

Leave a Reply