LCD 8-bit mode to 4-bit mode
Asked Answered
I

6

2

We have a character LCD (www.cloverlcd.com/pdf/S6A0069.pdf) that we got to work in 8 bit mode. However, now we are trying to get it to work in 4 bit mode but it doesn't seem to be displaying anything. I think the function set instruction isn't been written. Can somebody please check if I am approaching this the right way? I'll post my 8 bit code (which is working) and my 4 bit code (which I'm trying to get to work)

     //8 bit working
    COMPortC(0x3C);     //function set                                          
    Delay1KTCYx(10);
    COMPortC(0x0F);     //Turn on display and configure cursor settings         
    Delay1KTCYx(10);
    COMPortC(0x01);     //clear display
    Delay1KTCYx(10);
    COMPortC(0x06);     //increment mode and increment direction (entry mode set)
    Delay1KTCYx(10);
    COMPortC(0x02);     //Return Home

       //4 bit
    COMPortC(0x20);     //function set                                          
    Delay1KTCYx(10);
    COMPortC(0x20);     //function set                                          
    Delay1KTCYx(10);
    COMPortC(0x80);     //function set                                          
    Delay1KTCYx(10);

    COMPortC(0x00);     //Turn on display and configure cursor settings         
    Delay1KTCYx(10);
    COMPortC(0xF0);     //Turn on display and configure cursor settings         
    Delay1KTCYx(10);
Isolecithal answered 30/10, 2008 at 0:50 Comment(2)
Question: if it works in 8 bit mode, why would you want to use 4 bit?Inkwell
We're trying to switch to 4 bit mode because we need 4 extra wires to go to other components connected to our microcontroller.Circumnavigate
P
1

It looks okay up to a point but I wonder about a couple of things:

1/ Why do you output 0x20 twice to set the CGRAM address in the 4-bit section? Surely this is needed only once.

2/ The other two writes (0x00 and 0xf0), I don't understand from the docs. Can you fix up the comments to indicate what they're meant to be doing?

3/ Once you switch to 4-bit mode, do you need to redo the other instructions (the increment and return home)? It may be that switching modes resets all the data.

4/ One thing I did notice is that the busy flag indicates the system cannot yet receive another instruction. It may be that you're passing them in too fast. What happens when you increase the delays from 10 to 100.

Just some things to try - let us know the outcomes.

=====

RESPONSE:

Thanks for the reply

1 and 2) I am writing these values based on page 29 of the datasheet (www.cloverlcd.com/pdf/S6A0069.pdf).

3) You are right, I do need to do the other instructions as well but for now, I am just trying to get the cursor to blink in 4 bit mode (so the first two instructions are sufficient)

4) I just tried the 100 delays, it didn't work.

Sorry for the bad comments, I'll try to post better code next time.

Thanks

=====

EDIT:

I see how it works now. In 4-bit mode, it only uses d7,d6,d5,d4 but every instruction is 2 writes (to make a 8-bit instruction). So it uses a trick to write the instruction 20 (in 8-bit mode) or 22 (2020 in 4-bit mode) both of which set the mode to 4-bit. Very clever, Samsung, I'm impressed.

Try to go through the entire init sequence. It may be that the display doesn't fully start until initialization is complete.

So you need to output (hex) 20,20,80,00,f0,00,10,00,60,00,20. The bold ones are the ones you need to add.

Also, I need to ask two more questions (please reply as a comment to this answer rather than posting another answer)

1/ Does COMPortC() actually check the busy signal before outputting data?

2/ The delay of 10, what unit is it in, millisecs, microsecs, etc?

Precentor answered 30/10, 2008 at 1:12 Comment(13)
1) yes COMPortC() does check for a for busy 2) The delay is in cycles. I'm not sure what the exact frequency of the uC is but I was told that the delay function is per 1000 cycles, so delay(10) is 10000 cycles. Also, we used the exact same delay as 8 bit which worked. So probably not timing.Circumnavigate
Okay, if that's based on fosc at 270kHz, 10k cycles is about 37 milliseconds. That should be more than enough time for the longest required wait, especially if you're checking busy flag as well.Precentor
Did you try the full init sequence?Precentor
Currently, what I am doing is writing first nibble, delay, write second nibble, delay, check busy flagCircumnavigate
Okay, let's see if it IS switching to 4-bit. Output the init sequence 20,20,80,0f,01,06,02 and see if it works. If 20,20,80 doesnt switch, it should work okay. If it has switched, you'll simply write 0's to RDRAM and still see no display.Precentor
I've got something to display by adding a busy check after the second nibble of function set. i will try the init sequence now like you said. Thanks for you help thus farCircumnavigate
I get this weird symbol that looks like it fills up the entire square, but has a top like a roof. It's not on the ASCII table.Circumnavigate
I thought COMPortC() did a busy check before trying to send out the next byte/nybble. Your busy check shouldn't have mattered if that were the case. Is COMPort() your function and can you post the src? The weird symbol could be from CGRAM rather than one of the ROM chars.Precentor
If COMPort() is yours maybe it would be better to be "sleep(10); while (!busy) {}; output (data); return;" or something similar. That way pre-conditions are guaranteed before you attempt write.Precentor
Q: did you get this progress with the 20,20,80,0f,01,06,02 output or are you still using the top 4-bit version (20,20,80,00,f0,00,10,00,60,00,20)?Precentor
Yup, i am running through your entire init sequence. I've modified COMPort() to exclude the busy. And I've added a whole new function for calling busy.Circumnavigate
I've uploaded my entire init function in another postCircumnavigate
Mike, you've about reached my limit of assistance since you appear to be doing everything right according to the docs. I would suggest contacting Samsung if possible to see if they can tell you why it's not working.Precentor
C
1

I'm not sure how your 4 bits are hooked up, but my guess is.... Since you are sending the bits on the upper nibble (0x*0 - where the star is), that you likely want to use the lower or least significant nibble which would be 0x0*.

COMPortCWithoutBusy(0x02);      //function set first nibble                                     
Delay1KTCYx(10);
COMPortCWithoutBusy(0x02);      //function set second nibble                                    
Delay1KTCYx(10);
BusyEnable();
Delay1KTCYx(10);
...
Crinose answered 30/10, 2008 at 8:8 Comment(0)
I
0

Here is a better commented piece of code for the 4 bit mode

    COMPortC(0x20);     //function set first nibble                                     
    Delay1KTCYx(10);
    COMPortC(0x20);     //function set second nibble                                    
    Delay1KTCYx(10);
    COMPortC(0x80);     //function set  third nibble                                        
    Delay1KTCYx(10);

    COMPortC(0x00);     //Turn on display and configure cursor settings first nibble
    Delay1KTCYx(10);
    COMPortC(0xF0);     //Turn on display and configure cursor settings second nibble
    Delay1KTCYx(10);

I still don't know what's wrong. Also, on page 18 of the datasheet, it shows a timing diagram that is almost identical to the timing diagram of the 8 bit mode, except that there is an AC3. What does that AC3 mean?

Isolecithal answered 30/10, 2008 at 1:43 Comment(0)
I
0
void LCDInitialization(void)
{

    COMPortCWithoutBusy(0x20);      //function set first nibble                                     
    Delay1KTCYx(10);
    COMPortCWithoutBusy(0x20);      //function set second nibble                                    
    Delay1KTCYx(10);
    BusyEnable();
    Delay1KTCYx(10);

    COMPortCWithoutBusy(0x80);      //function set  third nibble                                        
    Delay1KTCYx(10);
    BusyEnable();
    Delay1KTCYx(10);

    COMPortCWithoutBusy(0x00);      //Turn on display and configure cursor settings first nibble
    Delay1KTCYx(10);
    COMPortCWithoutBusy(0xF0);      //Turn on display and configure cursor settings second nibble
    Delay1KTCYx(10);
    BusyEnable();
    Delay1KTCYx(10);

    COMPortCWithoutBusy(0x00);      //disp clear first nibble                                       
    Delay1KTCYx(10);
    COMPortCWithoutBusy(0x10);      //disp clear second nibble                                  
    Delay1KTCYx(10);
    BusyEnable();
    Delay1KTCYx(10);

    COMPortCWithoutBusy(0x00);      //entry mode set first nibble                                       
    Delay1KTCYx(10);
    COMPortCWithoutBusy(0x60);      //entry mode set second nibble                                  
    Delay1KTCYx(10);
    BusyEnable();
    Delay1KTCYx(10);

    COMPortCWithoutBusy(0x20);      //20 first nibble                                       
    Delay1KTCYx(10);
    BusyEnable();
    Delay1KTCYx(10);
}
Isolecithal answered 30/10, 2008 at 4:33 Comment(0)
P
0

This is just another variant of the HD44780 LCD driver, and as such it should work fine with the following initialization routine:

void initlcd(void)
{
    delayms(20);    // Wait for LCD to power up ( >15ms )
    RS=0;       // Set RS low for instruction 
    write4(3);  // Set interface to 8 bits 
    delayms(5); // Wait for LCD execute instruction ( >4.1ms )
    write4(3);  // Set interface to 8 bits 
    delayms(1); // Wait for LCD execute instruction ( >100us )
    write4(3);  // Set interface to 8 bits 
    delayms(5);     // Wait for LCD execute instruction (At this point 
            // we could actually start using the busy flag) 
    write4(2);  // Set the display to 4 bit interface 
    delayms(5); // Wait for LCD execute instruction 
    write8(0x28);   // Set the display to two line and ???
    delayms(5); // Wait for LCD execute instruction 
    write8(6);  // ???
    delayms(5); // Wait for LCD execute instruction 
    write8(1);  // Clear the LCD
    delayms(5); // Wait for LCD execute instruction
    write8(0xf);    // ???
    delayms(5); // Wait for LCD execute instruction
    return;
}

You'll need to define your own write4, write8, and delayms functions, but they are relatively easy. Make sure you have the register select (RS) set to command mode. write4 sends one 4 bit command, while write 8 sends two four bit commands in a row, high nibble first, then low nibble:

void write8(uns8 byte)
{
    uns8 nibble;
    nibble = (byte & 0xf0) >> 4;    // Rotate the high 4 bits (7-4) of byte into bits (3-0) of nibble
    write4(nibble);         // Write the high 4 bits to the LCD
    nibble = byte & 0xf;        // Copy the low four bits of byte into the low four bits of nibble
    write4(nibble);         // Write the low 4 bits to the LCD
}

The code I wrote is meant for the PIC microcontroller, using the free version of the cc5x compiler. Should be understandable and portable to other languages.

The initialization routine has borrowed heavily from many others through many years of LCD initialization - finding and overcoming the various quirks of the HD44780 and variants. It should work well for most similar LCDs.

Phalanger answered 28/4, 2009 at 18:52 Comment(0)
I
-1

1 and 2) I am writing these values based on page 29 of the datasheet (www.cloverlcd.com/pdf/S6A0069.pdf).

3) You are right, I do need to do the other instructions as well but for now, I am just trying to get the cursor to blink in 4 bit mode (so the first two instructions are sufficient)

4) I just tried the 100 delays, it didn't work.

Isolecithal answered 30/10, 2008 at 1:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.