This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hello,
I am using a LaunchPad to develop an application. I have chosen the MSP430G2533 to use for my project. I have set up an LCD module to display values as I develop. For some reason I must build the project twice for any settings to take place. I am not certain why. I've rewired the LCD, used the LCD on other projects without any issues, changed LaunchPads, used another MSP430G2533 and nothing seems to make a difference. I even rewire the circuit to use Port 1 of n MSP430G2211 and this issue does not exist. Each time I build the project I get the expected results. What's odd is the first time It builds things work correctly. If I make a change the code does not change and the display is slightly dimmer then before.
I've removed the jumpers to the following. P1.0, P1.6, TXD and RXD.
I've been experimenting with the following code below. If anyone had any ideas I would love to hear them.
#include <msp430g2533.h>
// Defines
#define RS BIT2 // RS (Register Select) is connected to P2.2
#define EN BIT3 // EN (Enable) is connected to P2.3
#define D4 BIT4 // D4 (Data Bit) is connected to P2.4
#define D5 BIT5 // D5 (Data Bit) is connected to P2.5
#define D6 BIT6 // D6 (Data Bit) is connected to P2.6
#define D7 BIT7 // D7 (Data Bit) is connected to P2.7
#define MASK (RS + EN + D4 + D5 + D6 + D7); // Used to set all
#define COMMAND 0
#define CHARACTER 1
// Functions
void port2Init (void); // Port2 controls the LCD
void lcdInit (void);
void pulseE (void);
void sendByte (char byteToSend, char isCommandOrCharacter);
void clearLCD (void);
void printText (char *text);
void moveCursor(char row, char col);
void main (void)
{
WDTCTL = WDTPW + WDTHOLD; // Disable the Watchdog Timer
BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ; // Calibrated 1 MHz clock
port2Init(); // Initialize Port2
lcdInit(); // Initialize LCD
clearLCD(); // Clear LCD to prepare for the code
printText("Test Text"); // Enter text. This goes on the first line. This will stay.
for (;;)
{
}
}
void port2Init (void)
{
// Port 2 and it's pins are used for the LCD control.
// P2.0 = Not Used
// P2.1 = Not Used
// P2.2 = LCD RS (Pin 10)
// P2.3 = LCD E (Pin 11)
// P2.4 = LCD Data 4 (Pin 12)
// P2.5 = LCD Data 5 (Pin 13)
// P2.6 = LCD Data 6 (Pin 19)
// P2.7 = LCD Data 7 (Pin 18)
P2OUT = 0; // This initializes the P2OUT to all zeros. Same as 0b00000000
P2SEL = 0; // P2SEL must first be cleared so we can use P2.6 & P2.7 as IO pins.
// They are XIN & XOUT by default.
P2DIR = MASK; // This sets the corresponding pins for the LCD control to outputs
}
/*-------------------------------------------------------------------------------------------------------*/
void lcdInit (void)
{
P2OUT &= ~MASK; // This sets RS EN D4 D5 D6 and D7 to 0
__delay_cycles(100000); // This is an instrisic function which delays the program for the specified
// number of clock cycles. This delay is to let the LCD power up.
// Set LCD to 4 Bit Mode. Note RS is low from above so we are sending commands.
P2OUT = 0x20; // Function Set command from table sets LCD to 4 bit mode. Or 0x20;
pulseE(); // Pulse E to send the command
P2OUT &= 0x0F; // This clears the upper 4 bits D4-D7. x & 0 = 0, x & 1 = x. 0x0F;
// Send initial LCD setup commands
sendByte(0x28, COMMAND);// Function Set table 2. 4 bit, 2 line, 5x7 (2 line means two display lines)
sendByte(0x0C, COMMAND);// Display On, Cursor Underline Off, Cursor Blink Off
sendByte(0x06, COMMAND);// Character Entry Mode, Increment On, Display Shift Off
}
/*-------------------------------------------------------------------------------------------------------*/
void pulseE (void)
{
P2OUT |= BIT3; // E high
__delay_cycles(200);
P2OUT &= ~BIT3; // E low
__delay_cycles(200);
}
/*-------------------------------------------------------------------------------------------------------*/
void sendByte(char byteToSend, char isCommandOrCharacter)
{
// This is a cool funciton. It takes a byte and breaks it up into the upper 4 bits and lower 4 bits.
// It then send them each. See the notes to understand the function.
P2OUT &= ~MASK; // This sets all of the bits in the MASK to 0. RS is low
// which is command mode. EN is also low.
P2OUT |= (byteToSend & 0xF0); // This takes the byte sent in the function and uses the &
// operator with 11110000. This sets all the upper bits
// to the bits of byteToSend and set the lower 4 to 0000.
if (isCommandOrCharacter == CHARACTER) // This checks to see if we are sending a character.
{
P2OUT |= RS; // If we are sending a character we set RS high.
}
else
{
P2OUT &= ~RS; // If we are sending a command we set RS low.
// This is probalby redundant since we just set it above.
}
pulseE(); // We pulse E to send the upper 4 bits. Even though the lower
// bits are 0000, we don't care since we are in 4 bit mode.
P2OUT &= ~MASK; // We reset the bits to get ready for the lower 4 bits
P2OUT |= ((byteToSend & 0x0F) << 4); // This takes the byte sent in the function and uses the &
// operator with 00001111. This set the lower bits to the
// bits of byteToSend and the upper bits to 0000. Next we use
// the leftshift operator to shift the bits four places to the
// left. 0000xxxx bocomes xxxx0000.
if (isCommandOrCharacter == CHARACTER) // The rest is a repeat of the steps above.
{
P2OUT |= RS;
}
else
{
P2OUT &= ~RS;
}
pulseE();
}
/*-------------------------------------------------------------------------------------------------------*/
void clearLCD (void)
{
// This funciton clears the LCD
sendByte(0x01, COMMAND); // Clear all Characters
sendByte(0x02, COMMAND); // Returns cursor to the beginning of line 1
__delay_cycles(100000);
}
/*-------------------------------------------------------------------------------------------------------*/
void printText (char *text)
{
// This send the text. Not quite sure how it works but it sends a character at a time.
char *c;
c = text;
while ((c != 0) && (*c != 0))
{
sendByte(*c, CHARACTER);
c++;
}
}
/*-------------------------------------------------------------------------------------------------------*/
void moveCursor(char row, char col)
{
char address;
if (row == 0)
{
address = 0;
}
else
{
address = 0x40;
}
address |= col;
sendByte(0x80|address, COMMAND);
}
Hello J,
It more than likely has to do with the speed of the controller you are using. I have had that problem with several LCD displays. Since I wanted to be able to cut and paste my code, my solution was to call the initialization of the LCD twice. That is basically what you are doing when you build and load your program a second time.
The way to fix the problem would be to make sure you follow the timing sequence for I itializing the LCD. There are slight variations from one manufacturer to another. Also, on some LCDs if the Write pin is unused and left floating, then it sometimes causes errors.
Or, in your main, just call the lcdint() and clearLCD() again.
Thanks,
Oh my gosh! Thank you so much! That fixed the issue. I've been trying things are rewiring for 5 hours. Oddly enough I have followed the timing requirements of the LCD.
You mentioned that I am essentially calling the lcdInit method twice when I build and load the second time. Isn't each build unique? I can't see why it would work the second time around? Is it an LCD controller issue or the MSP430? Can you explain this a little more. If not I understand. Thanks for the help.
Take care,
Jon
You are welcome.
It is an LCD issue. Your configuration isn't completing the first time you do the initialization. Since you are not powering off the LCD, I believe the partial initialization remains in the LCD controller.
Thanks,
Jonthornham said:Oddly enough I have followed the timing requirements of the LCD.
You may think so. But it depends on what your clock source is as to how accurate the timing is. Just something to consider.
I am sure that there is a better engineered method to solving this other than just "call lcd_init() twice". That seem's pretty "hack-ish". My 2-cents.
If you read the response carefully, you would have noted the part that said the way to fix the issue...
If you have to test and present on more than one platform, some of which you will never use again, it doesn't hurt to be able to be hackish.
**Attention** This is a public forum