LCD control F-51543NFU-LW-ADN / PWB51543C-2-V0 (from tape library)

Author of the original: Ivan Kostoski, on Habré @ikostoski
  • Transfer
  • Tutorial

Hello again, Habr! Having translated the article on managing the LCD module with a driver, but without my own video RAM, I decided to translate another publication on the same topic. Here the module is already simpler, monochrome, but to “revive” it is no less interesting.

LCD control with driver, but without controller

The display that the author is going to work with is taken from an old tape library. The controller did not survive, but a search for anything related to “263645-001” showed that there was an FPGA. It is believed that directly control such LCD modules from Arduino, etc. impossible, you need an intermediate link - the SEDxxxxx series controller, which does not “make friends” with the breadboard, and has more inputs than the module itself. But this is not so. Here are as many as four similar projects:

On ATmega8515
On it
On ESP32

And some even control eight-bit AVR VGA monitors ...

In general, the author succeeded, the software under the MIT license is here .

Still image

To make sure that everything works, you must first try to output a single-bit raster image from the flash memory of the microcontroller. To get a negative voltage, three “Crones” were taken, the voltage from the divider was applied to the V0 pin, which was used as a tuning resistor. And here is Lenna on the screen:

The author still cannot understand how he managed to turn the picture over (look at which side the cable is). In any case, there is this example on the project page on GitHub.

Text mode

But the video ROM is of little use, and there are no 9600 bytes for video RAM in the Arduino. The text mode comes to the rescue, in which the ROM of the character generator and the video RAM combined have less volume than the video RAM in the graphic mode. Supporters of the Republic of Kazakhstan and the “Specialist” can break spears endlessly on this subject.

A short example in AVR assembly language:

lpm r24, Z  
;----------            (CL2 rising edge)
out %[data_port], r24
ld r30, X+
swap r24;              (CL2 rising edge)
out %[data_port], r24
lpm r24, Z
;----------            (CL2 rising edge)
out %[data_port], r24

Required Hardware

For the F-51543NFU-LW-ADN / PWB51543C-2-V0 module, the author applied:

Arduino on AVR with a clock frequency of 16 MHz (tested on Uno, Leonardo and a clone similar to ProMicro).

Source of negative voltage. For the author, this is an unstabilized DC-DC converter A0524S-1W with input and output isolation. Converters for the MC34063 are also suitable (this chip is very easy to find - just disassemble the cheapest USB-charging for a cigarette lighter) or MAX749. Stabilization is not required, the range of permissible voltages at this input for the module used here is quite wide. The nominal value is minus 24 V, the maximum is minus 30 relative to the common wire and 35 between Vdd and Vee. The current consumption is 6 mA.

Two N-channel MOSFETs with logic level control. The author used IRL530n, the stock, of course, is large, but it certainly will not burn out. One transistor controls the backlight, the other a negative voltage source.

250 kΩ trimming resistor for supplying voltage to input V0. Set so that -16.8 V at a temperature of +25 ° C on the movable contact. This is from a datasheet, and so, of course, such accuracy is not needed.

Several 10-kilo resistors for pulling down.

Layout and jumpers.

What would you do now? QR watch? Let's ask kote:

Kote offers to implement a simulation of some common LCD with a controller. So that another “thinking” that works with the display on the HD44780, only large, can be connected to this Arduino.

Font - also in RAM

We take an example with EGA and VGA - there, when working in text mode, it was done just that. Only here there were 64 characters in total, but at least everything got into RAM, unlike the graphic mode. True, the main cycle of events has slowed down, but you can try tile graphics:

Graphic mode and halftone

In Arduino on AVR there is not so much RAM, and that’s the point. Even in Mega. 320x240 even with one bit per pixel - it's already 9600 bytes. Only four halftones will require twice as much. With external RAM, for example, 23LC512 in SQI mode, you can try to implement something similar to DMA, but it’s simpler and more profitable to remake everything on ESP32, where there is more static RAM and DMA is easier.

If you just want to connect such a display to a PC via USB, you can try using ATmega32u4 for this - there will be enough resources even for gradations of brightness (using FRC, what it is is described in my previous translation). But not with the “mega” used as an interface converter, but with a PC that will itself scan the LCD on the fly at a speed of 5.4 megabits per second.

When the module still stood in the tape library, there was a GUI and gradations of brightness - everything was there.

Updates will be. In the meantime ...

And this is not a photo montage, but the result of control from a PC. And we will switch from to GitHub - there is still a lot of interesting things in

Signals for controlling such modules

FLM - First Line Marker - first line marker, may also be called FRAME, VSYNC, etc.
CL1 - Row latch pulse - write string pulse, may also be called. LOAD, HSYNC, etc.
CL2 - Pixel shift clock - pixel change pulse, may also be called. CP (change pixel), etc.
M - alternating signal, due to which the pixels are controlled by alternating voltage, can also be called BIAS (offset), etc.

D0-D3 is a four-bit parallel data bus.

Leads for common wire, backlight power (e.g. VLED ±), module power (VEE and V0)

Do not neglect datasheets. The module may require another negative voltage, or it may turn out to be positive, or the converter may be built-in. The logic may differ, for example, with a unit on CL1 there will be no reaction on CL2. There may be a different backlight (CCFL (carefully, the inverter is a “bite”) instead of LEDs), or there is no pinout on the board, then you won’t know it without a datasheet. You cannot connect anything at random.

What is there to do

Transmit the string in pieces of four bits, recording is performed on the decline on the line CL2. After passing the line, write it down the recession on the CL1 line (yeah, after all, a little bit of RAM in the module is on one line). The next line will be selected automatically. After transmitting the entire frame, return to the beginning using the FLM signal. In a datasheet on LC79401 there is an example. Record at a sufficient speed, apply pulses to CL1 evenly. The controller hesitated a little - the screen blinked ugly.

After each frame, change the logic level at the input M to the opposite, so that the pixels are controlled by alternating voltage. Otherwise, the display deteriorates:

You can not trust this operation to the microcontroller, but put a countable trigger. Entrance to FLM, exit to M - in general, is understandable.

An example for outputting images from flash memory (see the beginning of the article) is called in this repository clglcd_simple

As already mentioned, it is impossible to do the same with RAM in Arduino on AVR - it will not be enough, therefore ...

And again - text mode

According to the datasheet, you can transmit data on a four-bit bus and “pull” CL2 with a frequency of up to 6 MHz. Therefore, you can quickly and quickly transfer the line, then the microcontroller solves other tasks a bit, and as the timer “tells” it, it “pulls” CL1 and repeats the cycle.

When generating characters for a horizontal resolution of 320 pixels, all this can be done in 20 μs (320 pixels / 4 bits = 80 pulses, CL2 is “pulled” with a frequency of 4 MHz). For the remaining tasks, 39.5 μs remains. CL1 “jerk” every 59.5 μs and get a frame rate of 70 Hz. Well, there will be more procedures for handling interruptions and so on, in general, the microcontroller will be busy controlling the display 45% of the time. “Whole” 45 or “total” 45? Probably the second: overwriting data in video RAM can be fast enough.

Do you want the microcontroller to spend less time managing the indicator, and more on other tasks? You can reduce the frame rate to 50 Hz, you can overclock the microcontroller to 20 MHz. With any of these methods, more clock cycles will take place between interrupt routines.

An output comparison timer switches the CL2 line every four clock pulses with a duty cycle of 50%. At the same time, the data goes to the outputs of the PORTB port, connected to the four-bit data bus of the module in such a way that they change at the moment the level rises to CL2, and at the time of decline they remain unchanged. Of course, this cannot be done without assembler:

  lpm r24, Z 
  ;----------            (CL2 rising edge)
  out %[data_port], r24
  ld r30, X+
  swap r24;              (CL2 rising edge)
  out %[data_port], r24
  lpm r24, Z
  ;----------            (CL2 rising edge)
  out %[data_port], r24

8 cycles - and four nibbles are transmitted. And what exactly to transmit depends on which symbol is in the corresponding video RAM cell, which pixels corresponding to this symbol should be transferred from the character generator ROM, and what is stored in the corresponding cells of this ROM.

The most inconvenient thing here is the need to stop the timer after exactly 80 pulses. Some timers, such as Timer4 in 32u4, cannot.

To obtain the signal supplied to the CL1 line, the author applied a different output of the microcontroller, intended both for the timer and for fast PWM. Which of this is applied here is understandable. It switches every 952 measures. Or if you count after the clock divider by 8 - it turns out every 119 pulses. At this point, the interrupt processing routine starts and forces the microcontroller to submit new data to the control line that will be required during the next pulse to CL1. Well, the level on the M line changes with half the frequency. And the LCD does not deteriorate. All signals together look like this:

The character generator consists of 256 characters - enough for 866, KOI-8R or 1251. 40xN characters are placed in the video RAM, where N is the number of lines depending on the height of the character. The width of the symbol is always 8 pixels, and the height can be 6, 8, 10, 12, 15, 16. The smaller it is, the less ROM is required for the character generator and more video RAM. With an 8x8 font (40 characters per 30 lines) you need 1200 bytes of RAM and 2048 bytes of ROM. With an 8x16 font (which looks best on this module), RAM needs 600 bytes, and ROM 4096. From the translator: you can store the font in the form of 8x8, and scale it vertically twice as programmatically, and cost 600 bytes of RAM and 2048 ROM. To store several fonts in ROM, you need to keep the address of the font start not in a constant, but in a variable, but it will not work to print the text in several fonts at once, unless, of course,

The font is stored like this: first the top lines of all 256 characters, then one line below, and so on. There is a Python script in the misc folder of the repository that automatically converts the TTF font to the clglcd_font.h header file with the PROGMEM array in the required format. Classic pixel fonts for CC-BY-SA 4.0 can be found here .

And again - take an example with EGA and VGA

But this time with details. The character generator in RAM, as indicated above, contains a total of 64 characters, they can be identified by numbers from 0 to n or from 255-n to 255. They are stored in the same way: the top lines of all characters, then the following, and so on. Only all this is aligned taking into account the fact that the characters are not 256, but 64. For characters 8x16 pixels in size, 16 * 64 = 1024 bytes are required. The repository has an example of working with the character generator in RAM.

If both character generators are used at the same time - 256-character in ROM and 64-character in RAM, you will have to accept that not only there will be less RAM, but also the data transfer speed of the lines in the module will decrease - instead of 8 clock cycles, two nibbles will need 12, that is, not 20 microseconds, but 30, and instead of 45% of the time for LCD control it will take 60.

Halftone Graphic Mode

As indicated above, in this case, the microcontroller works simply as an interface converter. You will need ATmega32u4, and what to do is described here . Please note that the module may become damaged due to the program freezing on the PC.

So what is this four-wire loop - from the resistive sensor, it turns out.

Where to connect

As indicated above, a negative voltage is required, which in the first experiments can be removed from three “Crones”, and then assemble the converter, for example, on the MAX749. The power control signals, as well as the DISPOFF signal (this is an inverse signal, the module is turned on at one), pull down the resistors. During flashing and resetting the microcontroller, the appearance of logical units there is unacceptable.

Apply negative voltage after voltage + 5V, and a logical unit to the DISPOFF line - when data is already present on the control lines: at least one unit on the data bus, unit on CL1. Otherwise, the module may fail.

The inputs D0-D3 can be connected to the outputs of the same port of the microcontroller, for example, Px4-Px7, while the outputs Px0-Px3 cannot be used as GPIO. You can assign them other functions, for example, use them as the outputs of timers, serial interfaces, etc. If you use them as inputs, be careful: the built-in pull-up resistors can switch arbitrarily if they are not disabled (PUD - pull-up disable).

Input M - to the output of the comparison timer or PWM.

Input CL1 - to another output of the same timer.

Input CL2 - to the output of another comparison timer.

FLM - to any digital output.

DISPOFF - to any other digital output.

The rest depends on how you power up the module. The author prefers to control the backlight and Vee separately.

How to use firmware

Place the clglcd.h and clglcd.cpp files in a sketch.

Make a backup copy of the clglcd_config.h file and edit it taking into account what is connected to, as well as what functions you need: a character generator in RAM, etc. Attention, the code does not indicate the names of the Arduino pins, but the names of the microcontroller pins according to the datasheet. The names of the outputs of the comparison tamers are deciphered as follows: for example, 2, B is OC2B, which on the Arduino Uno corresponds to PD3. The examples show the connection options that have been earned by the author.

Generate the font file clglcd_font.h with a Python script in the misc folder (see above).

See in examples how to initialize, turn on and turn off the display. Put in the screen array the text that you want to display for verification.

Compile and fill the sketch. Check with a logic analyzer that the correct signals will go to the display, and with a voltmeter that all supply voltages are normal. Only then connect the display.

Add a code to the sketch that will do something, for example, receive text on a serial port and display it.

Display interruptions

The display needs to be updated constantly, which is what interrupt handling procedures do. If interruptions stop for more than 30 microseconds, the display will blink, and if more than 60 microseconds for a unit on the FLM line, it may fail. If you need to stop interrupts for a long time, first turn off the display with the DISPOFF signal (I repeat, this is an inverse signal, the module is turned on at one). Of course, if it turns off for two seconds every time you need to process data from a humidity and temperature sensor, few will like it, but it's better than ruining the module. Better yet, charge the rest to a separate microcontroller. Information exchange by the same microcontroller with devices operating on the 1-wire protocol and address LEDs is especially unacceptable. Arduino Pro Micro clones are inexpensive enough to buy two.


But the hardware-implemented interfaces will work perfectly: serial ports, I 2 C bus , SPI in master mode. In the slave - only if the master allows periodic “roll-off” of the slave by 25-35 μs. Of course, it still depends on how many “legs” are left unoccupied after connecting the display.

USB on 32u4 works just fine if you don't interrogate the management endpoint too often (slow interrupt routine code). The CDC driver and its APIs were fast enough.

Further in the file on GitHub the list of similar projects is repeated, the same as on the project page on

Thank you for your attention!

Also popular now: