Jump to content
43oh

1602 LCD connected via I2C to MSP432 fails to show every character


Recommended Posts

Hello,

 

I'm writing a program for interfacing a 1602 LCD to MSP42 with the use of I2C protocol. I'm not writing my own routines, so I decided to go with DriverLib ones. 

LCD successfully initializes and after I try with different combinations of signals to get different characters, only some appear. 

Let me start from the beginning. I initialize the LCD to 4 bit mode with the code below:

void lcdInit(void){

	I2C_masterSendSingleByte(EUSCI_B0_MODULE, 0x30);
	__delay_cycles(10000);
	I2C_masterSendSingleByte(EUSCI_B0_MODULE, 0x30);
	__delay_cycles(10000);
	I2C_masterSendSingleByte(EUSCI_B0_MODULE, 0x30);
	__delay_cycles(10000);
	I2C_masterSendSingleByte(EUSCI_B0_MODULE, 0x20);
	__delay_cycles(10000);
	I2C_masterSendSingleByte(EUSCI_B0_MODULE, 0x28);
	__delay_cycles(10000);
	I2C_masterSendSingleByte(EUSCI_B0_MODULE, 0x08);
	__delay_cycles(10000);
	I2C_masterSendSingleByte(EUSCI_B0_MODULE, 0x01);
	__delay_cycles(10000);
	I2C_masterSendSingleByte(EUSCI_B0_MODULE, 0x06);
	__delay_cycles(10000);
	I2C_masterSendSingleByte(EUSCI_B0_MODULE, 0x0C);

}

After it exectues, the LCD is lit on and the cursor blinks. Now, in 4 bit operation we have to send data in 2 chunks. Each chunk is 6 bits, 4 data + 2 for RS and RW. 

Going by the LCD reference (http://www.tme.eu/en/Document/53481d6ef60900b7bb1011c164e7f0a0/rc1602b-biw-esx.pdf), I thought I could write a character "A" with two successive commands, like:

	I2C_masterSendSingleByte(EUSCI_B0_MODULE, 0x9);
	I2C_masterSendSingleByte(EUSCI_B0_MODULE, 0x21);

// 0x9  = 0b001001 // last 2 bits are RW and RS
// 0x21 = 0b100001 //

However, nothing usually happens, and if I'm lucky with the combinations, the characters from last row (LCD reference, page 11) are printed (?, /, O, _, ..) and no others. 

I can't seem to figure out what is going on exactly to try to get a pattern of errors being made. I'm almost sure I'm sending the wrong commands and not bit shifting properly. And ideas?

 

Thanks!

Link to post
Share on other sites

Hey!

 

Yes, I'm in the process of analyzing the Energia libraries and the PCF8574T documentation. In the mean time, the good sign is that the LCD at least initializes and shows something, so I'm guessing I'm not that far away from the solution.

Question about the I2C_masterSendSingleByte() routine though. Does it send 8 bits, i. e. 0x9 is sent as 0b00001001, or does it simplify to like 0b1001? I'm assuming it starts with MSB.

Link to post
Share on other sites

I could use some further explanation: in LiquidCrystal_I2C.cpp (line 231 or so) there's a function Send(), which takes in 2 parameters, byte as a value and mode. Mode is Rs (0b00000001), as far as I can tell, which enables the write command to LCD. So for example, if I wanted to send a write 0x9 command over to LCD, the following would occur:

 

0b00001001 gets chopped up into 2 pieces:

  • High nibble: 0000
  • Low nibble: 1001

Each nibble gets OR-ed with Rs, which enables writing:

  • HN | Rs = 0b00000001
  • LN | Rs = 0b00001001

Each nibble is then sent to LCD and pulsed with En (0b00000100)

  • (HN | Rs) sent
  • (HN | Rs) | En
  • (HN | Rs) &~ En
  • (LN | Rs) sent
  • (LN | Rs) | En
  • (LN | Rs) &~ En

This would be the general procedure, If I understand this correctly.

Link to post
Share on other sites

The protocol employed is a hardware protocol, you need to know how the PCF8574 is wired to the LCD-panel to be able to send data correctly. I 4-bit mode it is possible to control it completely over I2C but one or more display control lines may be connected to the MCU directly anyway. It seems like that at least one might be from reading your latest post but I have to admit I do not understand your pseudo code. Regarding transfer format you will find this on page 767 in slau356a.pdf (MSP432 tech ref): "The I2C mode operates with byte data. Data is transferred MSB first..."

 

This contains an example of how it can be wired for full control over I2C: http://www.microchip.com/forums/m830041-p2.aspx

Link to post
Share on other sites

CCS doesn't support MSP432 Energia sketches yet, so for the time being in just trying different write options. I managed to get some letters displayed randomly (hex values sent not matching letter values), so the LCD is initialized okay, I just can't seem to get the right sequence.

 

For writing command I'm doing the following:

#define Rs  0x1
#define En  0x4

HighNibble = (byte_data & 0xF0);
LowNibble = ((byte_data << 4) & 0xF0);


I2C_masterSendSingleByte(EUSCI_B0_MODULE, (HighNibble|Rs));
__delay_cycles(1000);
I2C_masterSendSingleByte(EUSCI_B0_MODULE, ((HighNibble|Rs) | En));
__delay_cycles(1000);
I2C_masterSendSingleByte(EUSCI_B0_MODULE, (HighNibble|Rs) & ~En);
__delay_cycles(1000);
I2C_masterSendSingleByte(EUSCI_B0_MODULE, (LowNibble|Rs));
__delay_cycles(1000);
I2C_masterSendSingleByte(EUSCI_B0_MODULE, ((LowNibble|Rs) | En));
__delay_cycles(1000);
I2C_masterSendSingleByte(EUSCI_B0_MODULE, (LowNibble|Rs) & ~En);

This tries to emulate the Send() command in LiquidCrystal_I2C.cpp. To my surprise, this displays 2 characters and not only one, so something is not quite right yet!

Link to post
Share on other sites

@@Blairo Ok, maybe enough information to be able to help some more now ;-)

 

The En pin needs to pe pulsed high for a little over 50 ns to clock the data into the display, I would think you need to do that for the initialization sequence too.

The enable cycle time is 1.2uS min - which means there should be no need for delays while sending a nibble, you only need to wait a bit after each byte is sendt to allow the display time to process it (IMO). There is no need to negate the En bit either ( & ~En) as the En bit is not set in your data from the previous command.

 

I would suggest you try to do the transfer in functions, something like this (not tested):

void sendData (unsigned char byte_data) {


	unsigned char Nibble = (byte_data & 0xF0) | Rs;

	I2C_masterSendSingleByte(EUSCI_B0_MODULE, Nibble);
	I2C_masterSendSingleByte(EUSCI_B0_MODULE, Nibble|En);
	I2C_masterSendSingleByte(EUSCI_B0_MODULE, Nibble);

	Nibble = ((byte_data << 4) & 0xF0) | Rs;

	I2C_masterSendSingleByte(EUSCI_B0_MODULE, Nibble);
	I2C_masterSendSingleByte(EUSCI_B0_MODULE, Nibble|En);
	I2C_masterSendSingleByte(EUSCI_B0_MODULE, Nibble);
	__delay_cycles(1000);

}

void sendCommand (unsigned char command) {


	I2C_masterSendSingleByte(EUSCI_B0_MODULE, command);
	I2C_masterSendSingleByte(EUSCI_B0_MODULE, command|En);
	I2C_masterSendSingleByte(EUSCI_B0_MODULE, command);
	__delay_cycles(1000);

}

Your init sequence seems a bit odd too - for 4-bit I think this may be more like it:

sendCommand(0x30);
sendCommand(0x20);
sendCommand(0x80); // 2 lines, 5x8 dots
sendCommand(0x20);
sendCommand(0x80); // 2 lines, 5x8 dots
sendCommand(0x00);
sendCommand(0x80); // set D C B bits as needed
sendCommand(0x00);
sendCommand(0x10); // clear display
sendCommand(0x00);
sendCommand(0x40); // set I/D & SH as needed

but then I may be wrong - chinese datasheets are sometimes not easy to make sense of...

 

Link to post
Share on other sites

It works!  :D

 

I modified the initialization procedure a bit, similar to what you suggested and as the Raystar's documentation sheet said. Did not pay attention to that before, looks like the wrong initialization was the most likely culprit - not |'ing the command with Enable. Anyways, here's the init procedure for blinking, backlight on, right incrementation:

    sendCommand(0x30); //function set
    sendCommand(0x40); //function set
    sendCommand(0x34); 
    sendCommand(0x40); //function set
    sendCommand(0x34); 
    sendCommand(0x0); //display on
    sendCommand(0x3C); 
    sendCommand(0x0);  //display clear
    sendCommand(0x20);
    sendCommand(0x0);  //entry mode set
    sendCommand(0x38);

Everything works correctly now when sending command bytes over using the way described above. Thanks again!

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...