Blairo 1 Posted September 22, 2015 Share Posted September 22, 2015 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! Quote Link to post Share on other sites
terjeio 134 Posted September 22, 2015 Share Posted September 22, 2015 The datasheet you have linked to is not for a I2C device, it has a 4-bit or 8-bit parallel interface. It is also specified for 5V operation. Are you sure it is the correct one? Quote Link to post Share on other sites
Blairo 1 Posted September 22, 2015 Author Share Posted September 22, 2015 The LCD comes with I2C backpack, the same setup works in Energia, I'm just trying to make it work in CCS. I'm using a voltage level conversion between MSP and LCD for logic (3.3 V <-> 5 V). Quote Link to post Share on other sites
terjeio 134 Posted September 22, 2015 Share Posted September 22, 2015 Ok, then the datasheet does not make much sense without information about how the I2C protocol is implemented. Maybe http://forum.arduino.cc/index.php?topic=229027.0 contains useful info? It indicates a command byte followed by one or more 8-bit data bytes - but your device might be different... Quote Link to post Share on other sites
Fmilburn 445 Posted September 22, 2015 Share Posted September 22, 2015 Hello @@BlairoThe Energia code I gave you that worked is written for the Hitachi HD44780 if that helps. EDIT: I've tested the Energia code with the following I2C backpacks based on the NXP chip.: PCF8574A (PCF8574AT) PCF8574 (PCF8574T) Datasheets are readily available for the above. Quote Link to post Share on other sites
Blairo 1 Posted September 23, 2015 Author Share Posted September 23, 2015 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. Quote Link to post Share on other sites
Blairo 1 Posted September 23, 2015 Author Share Posted September 23, 2015 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. Quote Link to post Share on other sites
terjeio 134 Posted September 23, 2015 Share Posted September 23, 2015 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 Quote Link to post Share on other sites
Blairo 1 Posted September 23, 2015 Author Share Posted September 23, 2015 Okay, thanks for the answer. I'll check out your link. About the pseudocode, I was just going through the procedure of 4 bit mode operation. Anyways, I'll aks again if I have some more questions! Quote Link to post Share on other sites
Fmilburn 445 Posted September 23, 2015 Share Posted September 23, 2015 @@Blairo My edits to that library were pretty minor to change it over from Arduino to Energia and I did not dive into it as deep as you are. You may already be doing this but have you tried bringing the Energia sketch into CCS and then using the debugger to watch what happens as you step through it? Good luck! Quote Link to post Share on other sites
abecedarian 330 Posted September 23, 2015 Share Posted September 23, 2015 Current CCS does not support import of MSP432, CC3xxx or C2000 sketches. Quote Link to post Share on other sites
Blairo 1 Posted September 23, 2015 Author Share Posted September 23, 2015 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! Quote Link to post Share on other sites
terjeio 134 Posted September 23, 2015 Share Posted September 23, 2015 @@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... Blairo 1 Quote Link to post Share on other sites
Blairo 1 Posted September 24, 2015 Author Share Posted September 24, 2015 Great, thanks for your help! I'll test this as soon as possible and report back with some further questions (probably some further problems too) . Quote Link to post Share on other sites
Blairo 1 Posted September 24, 2015 Author Share Posted September 24, 2015 It works! 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! bluehash 1 Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.