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.

***LCD 8x2 interfacing with MSP430F47197

Other Parts Discussed in Thread: MSP430F47197

Does anyone have extra spare time to help me fixing my code as follows please?

That would be much appreciated!

#include <msp430f47197.h>
#include <stdio.h>

void LCD_init(void);
void DelayMs(int Ms);
void LCD_cmd4(unsigned char cmd);
void LCD_dat4(unsigned char byte);

unsigned char i;
const unsigned char Msg1[] = " Hello World" ;
const unsigned char Msg2[] = "This is a test";

void main()
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
P7DIR = 0x00; // Set P7.4-P7.7 to Output direction
P8DIR = 0xF8;

DelayMs(100);
LCD_init();
DelayMs(50);

while(1) // infinit loop
{
LCD_cmd4(0x80);
for(i=0;i<8;i++)
{
LCD_dat4(Msg1[i]);
DelayMs(5);
}
LCD_cmd4(0xc0);
for(i=0;i<8;i++)
{
LCD_dat4(Msg2[i]);
DelayMs(5);
}
}
}
void LCD_init(void)
{
LCD_cmd4(0x33); LCD_cmd4(0x22); LCD_cmd4(0x22); LCD_cmd4(0x22);

LCD_cmd4(0x38); // 28 for eight bit mode
LCD_cmd4(0x0c);
LCD_cmd4(0x06);
LCD_cmd4(0x01);
}

void LCD_cmd4(unsigned char cmd)
{
// P5OUT = 0x00; // RW=0,RS=0
P8OUT &= 0xFC;
P7OUT = cmd;
// P4OUT = 0x80; // En = 1;
//OUT = 0x00; // En = 0;
P8OUT |= 0x04;
P8OUT &= 0xFB;
// cmd = (cmd<<4) & 0xF0;
P7OUT = cmd;
P8OUT |= 0x04;
P8OUT &= 0xFB;
DelayMs(3);
}

void LCD_dat4(unsigned char byte)
{
P8OUT &= 0xFC;
P7OUT = byte;
P8OUT |= 0x04;
P8OUT &= 0xFB;
// byte = (byte<<4) & 0xF0;
P7OUT = byte;
P8OUT |= 0x04;
P8OUT &= 0xFB;
DelayMs(3);
}

void DelayMs(int Ms)
{
int i;
while(Ms>0)
{
for(i=0;i<104;i++);
Ms--;
}
}

_____________________

PINOUTS to the microcontroller from LCD:

  • From your pinout and the code it appears that you're trying to use 8 bit parallel mode, but the init function seems to be selecting 4 bit mode. Have you tried the same code with 0x28 instead of 0x38 on the line with the comment "28 for eight bit mode"?


    Edit: Also, try replacing that busy loop with the __delay_cycles() instrinsic.

  • Robert Cowsill said:

    From your pinout and the code it appears that you're trying to use 8 bit parallel mode, but the init function seems to be selecting 4 bit mode. Have you tried the same code with 0x28 instead of 0x38 on the line with the comment "28 for eight bit mode"?

    Hi Robert. Thanks for your prompt reply. Actually I do use "   LCD_cmd(0x38);  " . My bad! i did not change the comment to 38!

  • Ok, so you're using 8 bit mode to communicate with an LCD display that presumably uses the HD44780 command set. Do you know which specific controller is on the LCD? Sometimes there are extended commands that you need to use to get the display working.

    Also, the LCD_cmd4 and LCD_dat4 functions have not been fully converted over to use 8 bit mode. They both write the same 8 bit value twice where the original code would have sent the upper and lower nibbles.

  • Robert Cowsill said:
    Ok, so you're using 8 bit mode to communicate with an LCD display that presumably uses the HC44780 command set.

    Actually I use a MSP430f47197.

    The LCD Datasheet is taken by the following link.

    http://www.microtipsusa.com/pdfs/products/NMTC-S0802XRGHS.pdf

    Robert Cowsill said:
    you know which specific controller is on the LCD? Sometimes there are extended commands that you need to use to get the display working.

    As I know it has a set of functions to control the LCD location and so on. 

    Robert Cowsill said:
    Also, the LCD_cmd4 and LCD_dat4 functions have not been fully converted over to use 8 bit mode. They both write the same 8 bit value twice where the original code would have sent the upper and lower nibbles.

    Oh really?! No! I am sure that I have commented the "4bit mode". Let me provide you with the clean code as follows.

    #include <msp430f47197.h>
    #include <stdio.h>
     
    void LCD_init(void);
    void DelayMs(int Ms);
    void LCD_cmd(unsigned char cmd);
    void LCD_dat(unsigned char byte);
     
    unsigned char i;
    const unsigned char Msg1[] = "Hello World" ;
    const unsigned char Msg2[] = "This is a test";
     
    void main()
    {
            WDTCTL = WDTPW + WDTHOLD;       // Stop watchdog timer
            P7DIR = 0x00;                      // Set P7.4-P7.7 to Output direction
            P8DIR = 0xF8;
        
            DelayMs(100);  // OR USING  __delay_cycles()
            LCD_init();
            DelayMs(50);
            
        while(1)   // infinit loop 
        {
            LCD_cmd(0x80);       
            for(i=0;i<8;i++)
            {
                LCD_dat(Msg1[i]);
                DelayMs(5);
            }
            LCD_cmd(0xc0);
            for(i=0;i<8;i++)
            {
                LCD_dat(Msg2[i]);
                DelayMs(5);
            }
        }
    }
    void LCD_init(void)
    {
    
           
            LCD_cmd(0x38);    // 8-bit mode 5*8 dots 
            LCD_cmd(0x0F);   // Blinking display 
            LCD_cmd(0x06);   // Blinking cursor 
            LCD_cmd(0x01);     // CleAR DISPLAY 
    }
                    
    void LCD_cmd(unsigned char cmd)
    {
              
            P8OUT &= 0xFC;// RW=0,RS=0
            P7OUT = cmd;
                     
               
            P8OUT |= 0x04;// En = 1; 
            P8OUT &= 0xFB;  // En = 0;
          
          
            P7OUT = cmd;
            P8OUT |= 0x04;
            P8OUT &= 0xFB;   
            DelayMs(3);
    }
     
    void LCD_dat(unsigned char byte)
    {
             P8OUT &= 0xFC;
           P7OUT = byte;
           P8OUT |= 0x04;
            P8OUT &= 0xFB;
            
            P7OUT = byte;
            P8OUT |= 0x04;
            P8OUT &= 0xFB; 
            DelayMs(3);
    }
     
    void DelayMs(int Ms)
    {
            int i;
            while(Ms>0)
            {
                    for(i=0;i<104;i++);
                    Ms--;
            }
    }
     

  • Try this:

    void LCD_cmd(unsigned char cmd)
    {
            P8OUT &= 0xFC;// RW=0,RS=0
    
            P7OUT = cmd;
            P8OUT |= 0x04;// En = 1; 
            P8OUT &= 0xFB;  // En = 0;
          
            // Disabled repeated write of cmd    
            //P7OUT = cmd;
            //P8OUT |= 0x04;
            //P8OUT &= 0xFB;   
    
            DelayMs(3);
    }
     
    void LCD_dat(unsigned char byte)
    {
            P8OUT &= 0xFC; // RW=0,RS=0
            P8OUT |= 0x01; // RS=1 to select data register
    
            P7OUT = byte;
            P8OUT |= 0x04;
            P8OUT &= 0xFB;
            
            // Disabled repeated write of data
            //P7OUT = byte;
            //P8OUT |= 0x04;
            //P8OUT &= 0xFB; 
    
            DelayMs(3);
    }

  • No! Did not fix the issue! :(

  • Would I be correct in guessing that the issue is that the LCD displays nothing at all when the program is run?

  • I forgot to mention that I got the code from the following link and changed it and trailered it to my purpose. 

    http://www.pantechsolutions.net/microcontroller-boards/lcd-interfacing-with-msp430f5529

    Robert Cowsill said:
    uld I be correct in guessing that the issue is that the LCD displays nothing at all when the program is run?

    Hardware-wise, when I load the code the LCD cells are all on and nothing changes during and after loading. But I have set the potentiometer and can change the contrast of LCD of course. I do know what you mean. If I have no voltage on pin 3 I can see nothing as the cells goe off.

  • Do you have any way to monitor the signal output from the MSP430? I'm still a bit suspicious of that delay function.

    If you don't have a scope or logic analyzer, try writing a test program to flash a LED using the DelayMs function for the delay between switching on and off. That'll let you see whether it's really producing the correct delay length to match the Ms parameter.

  • Robert Cowsill said:
    Do you have any way to monitor the signal output from the MSP430? I'm still a bit suspicious of that delay function.

    Yes! That might cause a problem in order not to see anything on the F*** LCD! A way to check the output? ...ummm...Maybe multimeter when I send Enable to high? A logical high maybe?

    Robert Cowsill said:
    If you don't have a scope or logic analyzer, try writing a test program to flash a LED using the DelayMs function for the delay between switching on and off.

    I have no LEDs on the board, unfortunately but I may use "__delay_cycles()" instead of that function. Cool! Thanks!

  • The 1st picture of you schematics shows that Vo (VLCD) is connected to 3.3V * 1k / (47k+1k) = 0.08V
    This is not correct. Vo (VLCD) should be connected to a negative voltage if Vcc is 3.3V

    Your DelayMs() needs to be calibrated. The code below will toggle P8.0 every DelayMs(5000). If it take longer or shorter than 5 seconds, you need to modify your DelayMs() accordingly.

    #include <msp430f47197.h>
    ///////////#include <stdio.h>

    void LCD_init(void);
    void DelayMs(int Ms);
    void LCD_cmd(unsigned char cmd);
    void LCD_dat(unsigned char byte);

    unsigned char i;
    const unsigned char Msg1[] = "Hello World" ;   //////// more than 8 characters!
    const unsigned char Msg2[] = "This is a test"; //////// more than 8 characters!

    void main()
    {
            WDTCTL = WDTPW + WDTHOLD;       // Stop watchdog timer
            P7DIR = 0x00; /////////// redundant
            P8OUT = 0;    /////////// do this before you set DIR
            P8DIR = 0x07; /////////// P8.2=>EN, P8.1=>RW, P8.0=>RS

            DelayMs(100);  // OR USING  __delay_cycles()
            LCD_init();
            DelayMs(50);

    /////// while(1)   // infinit loop /////// you only need to do it one time
        {
            LCD_cmd(0x80);
            for(i=0;i<8;i++)
            {
                LCD_dat(Msg1[i]);
                DelayMs(5);
            }
            LCD_cmd(0xc0);
            for(i=0;i<8;i++)
            {
                LCD_dat(Msg2[i]);
                DelayMs(5);
            }
        }

        P8OUT &= 0xF8;   //////// redundant, added as insurance
        while (1)        //////// added to test DelayMs()
        {
          P8OUT ^= 0x01; ////////// toggle P8.0 => RS
          DelayMs(5000); ////////// 5 seconds
        }
    }

    void LCD_init(void)
    {
            LCD_cmd(0x38);    // 8-bit mode 5*8 dots
            LCD_cmd(0x0F);    // Blinking display
            LCD_cmd(0x06);    // Blinking cursor
            LCD_cmd(0x01);    // CleAR DISPLAY
    }

    void LCD_cmd(unsigned char cmd)
    {
            P8OUT &= 0xF8; //////////// EN=0,RW=0,RS=0
            P7OUT = cmd;

            P8OUT |= 0x04; // En = 1;
            P7DIR = 0xFF;  //////////// out P7
            __delay_cycles(2); //////// insurance
            P8OUT &= 0xFB; // En = 0;
            P7DIR = 0;     //////////// float P7

    /////// P7OUT = cmd;
    /////// P8OUT |= 0x04;
    /////// P8OUT &= 0xFB;
            DelayMs(3);
    }

    void LCD_dat(unsigned char byte)
    {
            P8OUT &= 0xF8; //////////// EN=0,RW=0,RS=0
            P8OUT |= 0x01; //////////// change to RS=1
            P7OUT = byte;
            P8OUT |= 0x04;
            P7DIR = 0xFF;  //////////// P7 out
            __delay_cycles(2); //////// insurance
            P8OUT &= 0xFB;
            P7DIR = 0;     //////////// P7 float

    /////// P7OUT = byte;
    /////// P8OUT |= 0x04;
    /////// P8OUT &= 0xFB;
            DelayMs(3);
    }

    void DelayMs(int Ms)
    {
            volatile int i; ///////// to counteract "optimization"
            while(Ms>0)
            {
                    for(i=0;i<104;i++);
                    Ms--;
            }
    }

  • Thank you OCY for your comment on my problem. Actually, hardware-wise I do use a potentiometer to change the voltage. So, I have enough voltage and I can see the cells of LCD.

    Software-wise, I need to change the delay function as you explained. I will keep you updated shortly.

  • old_cow_yellow said:

    The 1st picture of you schematics shows that Vo (VLCD) is connected to 3.3V * 1k / (47k+1k) = 0.08V
    This is not correct. Vo (VLCD) should be connected to a negative voltage if Vcc is 3.3V

    Your DelayMs() needs to be calibrated. The code below will toggle P8.0 every DelayMs(5000). If it take longer or shorter than 5 seconds, you need to modify your DelayMs() accordingly.

    #include <msp430f47197.h>
    ///////////#include <stdio.h>

    void LCD_init(void);
    void DelayMs(int Ms);
    void LCD_cmd(unsigned char cmd);
    void LCD_dat(unsigned char byte);

    unsigned char i;
    const unsigned char Msg1[] = "Hello World" ;   //////// more than 8 characters!
    const unsigned char Msg2[] = "This is a test"; //////// more than 8 characters!

    void main()
    {
            WDTCTL = WDTPW + WDTHOLD;       // Stop watchdog timer
            P7DIR = 0x00; /////////// redundant
            P8OUT = 0;    /////////// do this before you set DIR
            P8DIR = 0x07; /////////// P8.2=>EN, P8.1=>RW, P8.0=>RS

            DelayMs(100);  // OR USING  __delay_cycles()
            LCD_init();
            DelayMs(50);

    /////// while(1)   // infinit loop /////// you only need to do it one time
        {
            LCD_cmd(0x80);
            for(i=0;i<8;i++)
            {
                LCD_dat(Msg1[i]);
                DelayMs(5);
            }
            LCD_cmd(0xc0);
            for(i=0;i<8;i++)
            {
                LCD_dat(Msg2[i]);
                DelayMs(5);
            }
        }

        P8OUT &= 0xF8;   //////// redundant, added as insurance
        while (1)        //////// added to test DelayMs()
        {
          P8OUT ^= 0x01; ////////// toggle P8.0 => RS
          DelayMs(5000); ////////// 5 seconds
        }
    }

    void LCD_init(void)
    {
            LCD_cmd(0x38);    // 8-bit mode 5*8 dots
            LCD_cmd(0x0F);    // Blinking display
            LCD_cmd(0x06);    // Blinking cursor
            LCD_cmd(0x01);    // CleAR DISPLAY
    }

    void LCD_cmd(unsigned char cmd)
    {
            P8OUT &= 0xF8; //////////// EN=0,RW=0,RS=0
            P7OUT = cmd;

            P8OUT |= 0x04; // En = 1;
            P7DIR = 0xFF;  //////////// out P7
            __delay_cycles(2); //////// insurance
            P8OUT &= 0xFB; // En = 0;
            P7DIR = 0;     //////////// float P7

    /////// P7OUT = cmd;
    /////// P8OUT |= 0x04;
    /////// P8OUT &= 0xFB;
            DelayMs(3);
    }

    void LCD_dat(unsigned char byte)
    {
            P8OUT &= 0xF8; //////////// EN=0,RW=0,RS=0
            P8OUT |= 0x01; //////////// change to RS=1
            P7OUT = byte;
            P8OUT |= 0x04;
            P7DIR = 0xFF;  //////////// P7 out
            __delay_cycles(2); //////// insurance
            P8OUT &= 0xFB;
            P7DIR = 0;     //////////// P7 float

    /////// P7OUT = byte;
    /////// P8OUT |= 0x04;
    /////// P8OUT &= 0xFB;
            DelayMs(3);
    }

    void DelayMs(int Ms)
    {
            volatile int i; ///////// to counteract "optimization"
            while(Ms>0)
            {
                    for(i=0;i<104;i++);
                    Ms--;
            }
    }

    Nice comments by the way! I didn't notice at the first glance. I appreciate it dear OCY!

  • CaEngineer said:

    ... Actually, hardware-wise I do use a potentiometer to change the voltage...

    It is good that you do use a potentiometer to change the voltage Vo. But what is the resulting voltage? Is it a positive voltage or a negative voltage?

    I believe your  Vdd is 3.3V. Is that correct? If so, then Vo should be about -1.1V (that is, about negative 1.1V.)

  • Robert Cowsill said:

    Try this:

    void LCD_cmd(unsigned char cmd)
    {
            P8OUT &= 0xFC;// RW=0,RS=0
    
            P7OUT = cmd;
            P8OUT |= 0x04;// En = 1; 
            P8OUT &= 0xFB;  // En = 0;
          
            // Disabled repeated write of cmd    
            //P7OUT = cmd;
            //P8OUT |= 0x04;
            //P8OUT &= 0xFB;   
    
            DelayMs(3);
    }
     
    void LCD_dat(unsigned char byte)
    {
            P8OUT &= 0xFC; // RW=0,RS=0
            P8OUT |= 0x01; // RS=1 to select data register
    
            P7OUT = byte;
            P8OUT |= 0x04;
            P8OUT &= 0xFB;
            
            // Disabled repeated write of data
            //P7OUT = byte;
            //P8OUT |= 0x04;
            //P8OUT &= 0xFB; 
    
            DelayMs(3);
    }

    You were right. The reason it did not woke was P7DIR and P8DIR were not set up correctly for your code to work. Check the main() of the original code. All 11 pins were all set up as input  :-(

    -- OCY

  • old_cow_yellow said:

    ... Actually, hardware-wise I do use a potentiometer to change the voltage...

    It is good that you do use a potentiometer to change the voltage Vo. But what is the resulting voltage? Is it a positive voltage or a negative voltage?

    I believe your  Vdd is 3.3V. Is that correct? If so, then Vo should be about -1.1V (that is, about negative 1.1V.)

    [/quote]

    OCY you are really a GRU! Many thanks! Hardware-wise as I mentioned before, there is nothing wrong with the board but software-wise I applied your changes and it worked perfectly!

    Thank you for your time! :)

  • old_cow_yellow said:

    Try this:

    void LCD_cmd(unsigned char cmd)
    {
            P8OUT &= 0xFC;// RW=0,RS=0
    
            P7OUT = cmd;
            P8OUT |= 0x04;// En = 1; 
            P8OUT &= 0xFB;  // En = 0;
          
            // Disabled repeated write of cmd    
            //P7OUT = cmd;
            //P8OUT |= 0x04;
            //P8OUT &= 0xFB;   
    
            DelayMs(3);
    }
     
    void LCD_dat(unsigned char byte)
    {
            P8OUT &= 0xFC; // RW=0,RS=0
            P8OUT |= 0x01; // RS=1 to select data register
    
            P7OUT = byte;
            P8OUT |= 0x04;
            P8OUT &= 0xFB;
            
            // Disabled repeated write of data
            //P7OUT = byte;
            //P8OUT |= 0x04;
            //P8OUT &= 0xFB; 
    
            DelayMs(3);
    }

    You were right. The reason it did not woke was P7DIR and P8DIR were not set up correctly for your code to work. Check the main() of the original code. All 11 pins were all set up as input  :-(

    -- OCY

    [/quote]

    ***! Yes, no DIR in the codes! Many thanks to you OCY! :)

**Attention** This is a public forum