Jump to content

How can I use the second line on my character LCD?

kelvinhall05
Go to solution Solved by mariushm,

The 8bit and 4 bit refer to how your microcontroller communicates with the LCD display.

The LCD display can use either 4 wires or 8 wires to receive the data from your microcontroller, plus 2..3 wires for non-data stuff.

 

See page 4 from the datasheet I linked above, I link again here:  http://www.newhavendisplay.com/specs/NHD-0216K1Z-FL-YBW.pdf

See also page 9 of the controller datasheet: http://www.newhavendisplay.com/app_notes/ST7066U.pdf

And also page 23 from same datasheet

 

image.png.a9fa94de1a1d9d988bba237ab5f5dcf6.png

 

So you can use either 4 wires or 8 wires to send data to the LCD display. If you use 4 wires, then you have to send first 4 bits from a byte, then send the next 4 bits from the send byte. So it takes twice as much time to send each byte of information to the lcd display, but you use less wires.

The E wire is used to tell the lcd display that you put new data on the wires, so you basically put the bits on the wires, set the E wire to 1 (5v), wait a very short time, then set it back to 0 (no voltage. That pulse tells the lcd display that new data is on its input and he should read that and so something with it.

The RS wire is used to put the LCD display between two modes. For any command (go to home, clear display, enable cursor, etc) the RS is 0 (no voltage), and for any stuff with data (move cursor to offset, write data to position) the RS must be 1 (5v)

The R/W wire is optional, by default the lcd display is on write mode, and can be used completely in write mode all the time. If you want to use some functions, you need to set that to 5v to switch the LCD display in read mode (for example, read if the lcd display is busy, still doing the previous command, or to read what's written in the memory, the predefined font)

 

The same datasheet tells you at page 10 and page 11 how to initialize the LCD display, here's me pasting the 8bit mode from there:

 

// 8-bit Initialization:
// D_I = RS pin 
// R_W = RW pin 
// E   = Enable pin 
// P1  = Port 1 of the microcontroller (8 bit, 8 wires)
// Delay = in ms, whatever in your programming language, 
// may have to set oscillator frequency as a constant to
// get delay to work, depending on compiler. Read manual.
//
void command(char i) {

P1 = i;                       //put data on output Port
D_I =0;                       //D/I=LOW : send instruction
R_W =0;                       //R/W=LOW : Write 
E  = 1;
Delay(1);                     //enable pulse width  >= 300ns 
E  = 0;                     //Clock enable: falling edge
}

void write(char i) {

P1 = i;                       //put data on output Port
D_I =1;                       //D/I=HIGH: send data
R_W =0;                       //R/W=LOW : Write 
E  = 1;
Delay(1);                     //enable pulse width  >= 300ns
E  = 0;                       //Clock enable: falling edge
}

/**********************************************************/ void init()

{

E = 0;
Delay(100);                   //Wait >40 msec after power is applied
command(0x30);                //command 0x30 = Wake up
Delay(30);                    //must wait 5ms, busy flag not available
command(0x30);                //command 0x30 = Wake up #2
Delay(10);                    //must wait 160us, busy flag not available
command(0x30);                //command 0x30 = Wake up #3
Delay(10);                    //must wait 160us, busy flag not available
command(0x38);                //Function set: 8-bit/2-line
command(0x10);                //Set cursor
command(0x0c);                //Display ON; Cursor ON
command(0x06);                //Entry mode set
}

 

This matches the datasheet , more or less :

 

image.png.5653fb5ff5ed642feeaa8197d400f2aa.png

 

 

once the display is initialized, you can position yourself to any location with the "set ddram address"

 

ex. move cursor/position to the 2nd character on the first line so offset 1, as we start from 0...

 

You have the instruction

 

image.png.6af7069244edfa7ecf3fe9b0c69c1161.png

 

Notice that bit 7 is set to 1 ... so you would say this:

 

command(128 + 1);   // 128 is 0b 1000 0000  which sets bit 7 to 1, and you add 1 to it which sets bit 0 to 1, and you get  1000 0001

 

So in the example above where the 2nd line starts at offset 0x40, you would say command(128 + 64 + offset on 2nd row) to move cursor to first character on 2nd line.

 

 

 

It's a 12x2 character LCD from Crystalfontz.com. I've tried the one solution I found that worked for some other people which is to just press "enter" any character over 40 times and it should move the cursor to the start of the second line, but it didn't work for me (and I pressed the button over 60 times). I'm only controlling it with toggle switches, not an Arduino or anything, but maybe there is some initialization command for the second line that I don't know about. Any help is appreciated. Thanks!

Quote me to see my reply!

SPECS:

CPU: Ryzen 7 3700X Motherboard: MSI B450-A Pro Max RAM: 32GB I forget GPU: MSI Vega 56 Storage: 256GB NVMe boot, 512GB Samsung 850 Pro, 1TB WD Blue SSD, 1TB WD Blue HDD PSU: Inwin P85 850w Case: Fractal Design Define C Cooling: Stock for CPU, be quiet! case fans, Morpheus Vega w/ be quiet! Pure Wings 2 for GPU Monitor: 3x Thinkvision P24Q on a Steelcase Eyesite triple monitor stand Mouse: Logitech MX Master 3 Keyboard: Focus FK-9000 (heavily modded) Mousepad: Aliexpress cat special Headphones:  Sennheiser HD598SE and Sony Linkbuds

 

🏳️‍🌈

Link to comment
Share on other sites

Link to post
Share on other sites

Most of those lcd displays are internally arranged as 64x2, or 64x4 with just the 12x2 or 16x2 being actually used.

 

So, to position yourself on the second line, you may have to go to character 0x40 (64) ...

 

Here's for example a 16x2 display, go to page 5: http://www.newhavendisplay.com/specs/NHD-0216K1Z-FL-YBW.pdf

See DDRAM Address which says the memory location for the character:

image.png.0ab2707e87a896a9c61fd27f32c7f8b8.png

 

And if you check out a 16x4 display from the same company, you can see how they interleave everything, so the 1st and 3rd row are basically a single row :

Datasheet: http://www.newhavendisplay.com/specs/NHD-0416BZ-NSW-BBW.pdf

 

image.png.12a42ea0da14b2ecae54087b128029c0.png

 

So as you can see, 1st line is from 0x00 to 0x0F (0..15 = 16 bytes), 2nd line is from 0x40..0x4F (64..79 , 16 bytes) , 3rd line is 0x10 to 0x1F (16..31, 16 bytes) and so on.

 

Others are arranged as 20x4 or 40x2

 

To position yourself somewhere use the library's function, or send the raw command to the display, see the datasheets above which use a controller that's clone to HD44780, so they use the same instructions.

Look at the "Set DDRAM address" instruction, page 6 in the datasheets above.

 

Also while you're testing, you may want to enable the cursor (see "Cursor or Display shift" instruction) and again, if you want to figure out the offset of each character, try printing 0123456789 several times to the screen.

Link to comment
Share on other sites

Link to post
Share on other sites

1 hour ago, Dujith said:

Which LCD? Exact type number will help

CFAH1202A-TTI-JT

https://www.crystalfontz.com/product/cfah1202attijt-12x2-character-lcd-display

Quote me to see my reply!

SPECS:

CPU: Ryzen 7 3700X Motherboard: MSI B450-A Pro Max RAM: 32GB I forget GPU: MSI Vega 56 Storage: 256GB NVMe boot, 512GB Samsung 850 Pro, 1TB WD Blue SSD, 1TB WD Blue HDD PSU: Inwin P85 850w Case: Fractal Design Define C Cooling: Stock for CPU, be quiet! case fans, Morpheus Vega w/ be quiet! Pure Wings 2 for GPU Monitor: 3x Thinkvision P24Q on a Steelcase Eyesite triple monitor stand Mouse: Logitech MX Master 3 Keyboard: Focus FK-9000 (heavily modded) Mousepad: Aliexpress cat special Headphones:  Sennheiser HD598SE and Sony Linkbuds

 

🏳️‍🌈

Link to comment
Share on other sites

Link to post
Share on other sites

2 minutes ago, kelvinhall05 said:

This LCD uses the same controller as the displays I linked to above, so what's written in those datasheet will apply to yours as well.

So most likely your display uses the same arrangement, with the second row starting from 64.

Link to comment
Share on other sites

Link to post
Share on other sites

12 minutes ago, mariushm said:

This LCD uses the same controller as the displays I linked to above, so what's written in those datasheet will apply to yours as well.

So most likely your display uses the same arrangement, with the second row starting from 64.

I found this at school while researching this a bit. Sorry that it's not a screenshot, it was on a school computer so I was unable to do so easily.

qGh3VCD1qeQC55fIbhgQUB7vGUPxROMNq2bffAzAluzJ3pgmxfYvLJhea3w_AlEa4zPwKk-MGEc3mfcqGk7hHAPFwpkyKtIRDqDb8jRL9U-rmBtv8g0ks2BwidBoLIKEkyUJ9RuspmxApxp4o2N31mt899cNR5IEf-sqOjgxecc9oBeLtahJVzpSGrNtWW9_ejfv73tw9ohjBK5MOdfD8OgGLgZjKbeDAPQv4PauWWzjz2ow-uODk8bIbXUE0Kz_INB69oDglFKMTfc-lTrCwX1pmvP5z8yHnQvVRpMvuDq8RtPMDjzAZC67L4hbheKjqNAN_lYwlUSHEKNVgz2LGbHV1Cqj-6cC6_dw18ax5-3vr-9dmixexGj1m8VR_MB6RbsBjEFoFyNH11S_CAJYex4Hoh6VO8uEdLNedxq15bWkNpWKCvXlrCRX00SlwXyprcomBrcqB_p7Lq6M8tC2WUvteKW-7ke4Stg99bShrsQ2L_2povKLavpEtLv8T8Ra8ki4A2mIP7R22nyrR-8hU8DdJKLkt8aMu_yYzy6nhSGGo9CTBFewhFkcKjISTvE5bvbM-a6X0nSaFo0UybYJaN0Oj9dwPZB9TC5Vwr0Y24X6b1puXnt0MGkKA2o5wUX34UDBw-GIvmYLLw9TUl6mNuV4E8pPLhg=w1050-h591-no

I think the first green line is what I want to do, but how do I turn that into an 8-bit string of binary?

Quote me to see my reply!

SPECS:

CPU: Ryzen 7 3700X Motherboard: MSI B450-A Pro Max RAM: 32GB I forget GPU: MSI Vega 56 Storage: 256GB NVMe boot, 512GB Samsung 850 Pro, 1TB WD Blue SSD, 1TB WD Blue HDD PSU: Inwin P85 850w Case: Fractal Design Define C Cooling: Stock for CPU, be quiet! case fans, Morpheus Vega w/ be quiet! Pure Wings 2 for GPU Monitor: 3x Thinkvision P24Q on a Steelcase Eyesite triple monitor stand Mouse: Logitech MX Master 3 Keyboard: Focus FK-9000 (heavily modded) Mousepad: Aliexpress cat special Headphones:  Sennheiser HD598SE and Sony Linkbuds

 

🏳️‍🌈

Link to comment
Share on other sites

Link to post
Share on other sites

The 8bit and 4 bit refer to how your microcontroller communicates with the LCD display.

The LCD display can use either 4 wires or 8 wires to receive the data from your microcontroller, plus 2..3 wires for non-data stuff.

 

See page 4 from the datasheet I linked above, I link again here:  http://www.newhavendisplay.com/specs/NHD-0216K1Z-FL-YBW.pdf

See also page 9 of the controller datasheet: http://www.newhavendisplay.com/app_notes/ST7066U.pdf

And also page 23 from same datasheet

 

image.png.a9fa94de1a1d9d988bba237ab5f5dcf6.png

 

So you can use either 4 wires or 8 wires to send data to the LCD display. If you use 4 wires, then you have to send first 4 bits from a byte, then send the next 4 bits from the send byte. So it takes twice as much time to send each byte of information to the lcd display, but you use less wires.

The E wire is used to tell the lcd display that you put new data on the wires, so you basically put the bits on the wires, set the E wire to 1 (5v), wait a very short time, then set it back to 0 (no voltage. That pulse tells the lcd display that new data is on its input and he should read that and so something with it.

The RS wire is used to put the LCD display between two modes. For any command (go to home, clear display, enable cursor, etc) the RS is 0 (no voltage), and for any stuff with data (move cursor to offset, write data to position) the RS must be 1 (5v)

The R/W wire is optional, by default the lcd display is on write mode, and can be used completely in write mode all the time. If you want to use some functions, you need to set that to 5v to switch the LCD display in read mode (for example, read if the lcd display is busy, still doing the previous command, or to read what's written in the memory, the predefined font)

 

The same datasheet tells you at page 10 and page 11 how to initialize the LCD display, here's me pasting the 8bit mode from there:

 

// 8-bit Initialization:
// D_I = RS pin 
// R_W = RW pin 
// E   = Enable pin 
// P1  = Port 1 of the microcontroller (8 bit, 8 wires)
// Delay = in ms, whatever in your programming language, 
// may have to set oscillator frequency as a constant to
// get delay to work, depending on compiler. Read manual.
//
void command(char i) {

P1 = i;                       //put data on output Port
D_I =0;                       //D/I=LOW : send instruction
R_W =0;                       //R/W=LOW : Write 
E  = 1;
Delay(1);                     //enable pulse width  >= 300ns 
E  = 0;                     //Clock enable: falling edge
}

void write(char i) {

P1 = i;                       //put data on output Port
D_I =1;                       //D/I=HIGH: send data
R_W =0;                       //R/W=LOW : Write 
E  = 1;
Delay(1);                     //enable pulse width  >= 300ns
E  = 0;                       //Clock enable: falling edge
}

/**********************************************************/ void init()

{

E = 0;
Delay(100);                   //Wait >40 msec after power is applied
command(0x30);                //command 0x30 = Wake up
Delay(30);                    //must wait 5ms, busy flag not available
command(0x30);                //command 0x30 = Wake up #2
Delay(10);                    //must wait 160us, busy flag not available
command(0x30);                //command 0x30 = Wake up #3
Delay(10);                    //must wait 160us, busy flag not available
command(0x38);                //Function set: 8-bit/2-line
command(0x10);                //Set cursor
command(0x0c);                //Display ON; Cursor ON
command(0x06);                //Entry mode set
}

 

This matches the datasheet , more or less :

 

image.png.5653fb5ff5ed642feeaa8197d400f2aa.png

 

 

once the display is initialized, you can position yourself to any location with the "set ddram address"

 

ex. move cursor/position to the 2nd character on the first line so offset 1, as we start from 0...

 

You have the instruction

 

image.png.6af7069244edfa7ecf3fe9b0c69c1161.png

 

Notice that bit 7 is set to 1 ... so you would say this:

 

command(128 + 1);   // 128 is 0b 1000 0000  which sets bit 7 to 1, and you add 1 to it which sets bit 0 to 1, and you get  1000 0001

 

So in the example above where the 2nd line starts at offset 0x40, you would say command(128 + 64 + offset on 2nd row) to move cursor to first character on 2nd line.

 

 

 

Link to comment
Share on other sites

Link to post
Share on other sites

6 minutes ago, mariushm said:

So in the example above where the 2nd line starts at offset 0x40, you would say command(128 + 64 + offset on 2nd row) to move cursor to first character on 2nd line.

 

 

image.png

All the stuff you said was extremely helpful, but this made the second line work! Thank you so much :D 

Quote me to see my reply!

SPECS:

CPU: Ryzen 7 3700X Motherboard: MSI B450-A Pro Max RAM: 32GB I forget GPU: MSI Vega 56 Storage: 256GB NVMe boot, 512GB Samsung 850 Pro, 1TB WD Blue SSD, 1TB WD Blue HDD PSU: Inwin P85 850w Case: Fractal Design Define C Cooling: Stock for CPU, be quiet! case fans, Morpheus Vega w/ be quiet! Pure Wings 2 for GPU Monitor: 3x Thinkvision P24Q on a Steelcase Eyesite triple monitor stand Mouse: Logitech MX Master 3 Keyboard: Focus FK-9000 (heavily modded) Mousepad: Aliexpress cat special Headphones:  Sennheiser HD598SE and Sony Linkbuds

 

🏳️‍🌈

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×