Since I2C LCD interface isn't in working order just yet, I tried to quickly make the LCD work in standard 4 data pin + EN and RS mode. I got the following code from http://cacheattack.blogspot.si/2011/06/quick-overview-on-interfacing-msp430.html, where the code posted is for MSP430 , however it is simple enough that I figured it should work on MSP432 too with just a few adjustments (should be even simpler because 432 has a 5 volt power supply) - to spare you the suspense, I was wrong:
Code (compiles in CCS 6.1)
#include "msp.h"
#define LCM_DIR P4DIR
#define LCM_OUT P4OUT
//
// Define symbolic LCM - MCU pin mappings
// We've set DATA PIN TO 4,5,6,7 for easy translation
//
#define LCM_PIN_RS BIT0 // P4.0
#define LCM_PIN_EN BIT1 // P4.1
#define LCM_PIN_D7 BIT7 // P4.7
#define LCM_PIN_D6 BIT6 // P4.6
#define LCM_PIN_D5 BIT5 // P4.5
#define LCM_PIN_D4 BIT4 // P4.4
#define LCM_PIN_MASK ((LCM_PIN_RS | LCM_PIN_EN | LCM_PIN_D7 | LCM_PIN_D6 | LCM_PIN_D5 | LCM_PIN_D4))
#define FALSE 0
#define TRUE 1
//
// Routine Desc:
//
// This is the function that must be called
// whenever the LCM needs to be told to
// scan it's data bus.
//
// Parameters:
//
// void.
//
// Return
//
// void.
//
void PulseLcm()
{
//
// pull EN bit low
//
LCM_OUT &= ~LCM_PIN_EN;
__delay_cycles(20);
//
// pull EN bit high
//
LCM_OUT |= LCM_PIN_EN;
__delay_cycles(20);
//
// pull EN bit low again
//
LCM_OUT &= (~LCM_PIN_EN);
__delay_cycles(20);
}
//
// Routine Desc:
//
// Send a byte on the data bus in the 4 bit mode
// This requires sending the data in two chunks.
// The high nibble first and then the low nible
//
// Parameters:
//
// ByteToSend - the single byte to send
//
// IsData - set to TRUE if the byte is character data
// FALSE if its a command
//
// Return
//
// void.
//
void SendByte(char ByteToSend, int IsData)
{
//
// clear out all pins
//
LCM_OUT &= (~LCM_PIN_MASK);
//
// set High Nibble (HN) -
// usefulness of the identity mapping
// apparent here. We can set the
// DB7 - DB4 just by setting P1.7 - P1.4
// using a simple assignment
//
LCM_OUT |= (ByteToSend & 0xF0);
if (IsData == TRUE)
{
LCM_OUT |= LCM_PIN_RS;
}
else
{
LCM_OUT &= ~LCM_PIN_RS;
}
//
// we've set up the input voltages to the LCM.
// Now tell it to read them.
//
PulseLcm();
//
// set Low Nibble (LN) -
// usefulness of the identity mapping
// apparent here. We can set the
// DB7 - DB4 just by setting P1.7 - P1.4
// using a simple assignment
//
LCM_OUT &= (~LCM_PIN_MASK);
LCM_OUT |= ((ByteToSend & 0x0F) << 4);
if (IsData == TRUE)
{
LCM_OUT |= LCM_PIN_RS;
}
else
{
LCM_OUT &= ~LCM_PIN_RS;
}
//
// we've set up the input voltages to the LCM.
// Now tell it to read them.
//
PulseLcm();
}
//
// Routine Desc:
//
// Set the position of the cursor on the screen
//
// Parameters:
//
// Row - zero based row number
//
// Col - zero based col number
//
// Return
//
// void.
//
void LcmSetCursorPosition(char Row, char Col)
{
char address;
//
// construct address from (Row, Col) pair
//
if (Row == 0)
{
address = 0;
}
else
{
address = 0x40;
}
address |= Col;
SendByte(0x80 | address, FALSE);
}
//
// Routine Desc:
//
// Clear the screen data and return the
// cursor to home position
//
// Parameters:
//
// void.
//
// Return
//
// void.
//
void ClearLcmScreen()
{
//
// Clear display, return home
//
SendByte(0x01, FALSE);
SendByte(0x02, FALSE);
}
//
// Routine Desc:
//
// Initialize the LCM after power-up.
//
// Note: This routine must not be called twice on the
// LCM. This is not so uncommon when the power
// for the MCU and LCM are separate.
//
// Parameters:
//
// void.
//
// Return
//
// void.
//
void InitializeLcm(void)
{
//
// set the MSP pin configurations
// and bring them to low
//
LCM_DIR |= LCM_PIN_MASK;
LCM_OUT &= ~(LCM_PIN_MASK);
//
// wait for the LCM to warm up and reach
// active regions. Remember MSPs can power
// up much faster than the LCM.
//
__delay_cycles(100000000);
//
// initialize the LCM module
//
// 1. Set 4-bit input
//
LCM_OUT &= ~LCM_PIN_RS;
LCM_OUT &= ~LCM_PIN_EN;
LCM_OUT = 0x20;
PulseLcm();
//
// set 4-bit input - second time.
// (as reqd by the spec.)
//
SendByte(0x28, FALSE);
//
// 2. Display on, cursor on, blink cursor
//
SendByte(0x0E, FALSE);
//
// 3. Cursor move auto-increment
//
SendByte(0x06, FALSE);
}
//
// Routine Desc
//
// Print a string of characters to the screen
//
// Parameters:
//
// Text - null terminated string of chars
//
// Returns
//
// void.
//
void PrintStr(char *Text)
{
char *c;
c = Text;
while ((c != 0) && (*c != 0))
{
SendByte(*c, TRUE);
c++;
}
}
//
// Routine Desc
//
// main entry point to the sketch
//
// Parameters
//
// void.
//
// Returns
//
// void.
//
void main(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
InitializeLcm();
ClearLcmScreen();
PrintStr("Hello World!");
while (1)
{
__delay_cycles(100000);
}
}
Pin definitions changed to
#define LCM_DIR P4DIR #define LCM_OUT P4OUT #define LCM_PIN_RS BIT0 // P4.0 #define LCM_PIN_EN BIT1 // P4.1 #define LCM_PIN_D7 BIT7 // P4.7 #define LCM_PIN_D6 BIT6 // P4.6 #define LCM_PIN_D5 BIT5 // P4.5 #define LCM_PIN_D4 BIT4 // P4.4
And increased __delay_cycles value to accomodate for faster DCO speeds. LCD powers up okay when connected to 5 volts but doesn't blink an eye when I run the program. Is there anything else to change in the code in order to make it work? LCD data pins are connected directly to MSP pins. I'm guessing it has something to do with those hex values, I really can't think of anything else (unless the LCD is kaputt itself).
Thanks.