views:

1611

answers:

6

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);
+1  A: 

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?

paxdiablo
1) yes COMPortC() does check for a for busy2) 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.
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.
paxdiablo
Did you try the full init sequence?
paxdiablo
Yup, same thing.
Currently, what I am doing is writing first nibble, delay, write second nibble, delay, check busy flag
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.
paxdiablo
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 far
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.
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.
paxdiablo
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.
paxdiablo
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)?
paxdiablo
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.
I've uploaded my entire init function in another post
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.
paxdiablo
A: 

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, I need to register to delete this post.I will remember this for next time. Thank you for letting me know!
A: 

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?

Sorry, I need to register to delete this post. I will remember this for next time. Thank you for letting me know! – Mike (9 mins ago) [remove this comment]
A: 
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);
}
+1  A: 

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);
...
kenny
A: 

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.

Adam Davis