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.

20x2 LCD interface with tm4C129gxl Launchpad, 4 bit mode.

Other Parts Discussed in Thread: TPS2052B

Hello,

I am trying to connect 20x2 LCD, in 4 bit mode with tm4c129gxl Launchpad. Earlier I have done connected this LCD with tm4c123gxl Launchpad and it was working. I have used Hello example from the TIVAWARE and modified it as per requirement.

The problem is LCD does not display anything, I have checked on oscilloscope the EN and RS pins does not get high. Both the pins remains continuously in low state.

Is there any special care I need to take while porting the code from TM4C123 to TM4C129.

Please share your view. I am attaching my code for reference.

Thank you.

Regards,

Anup.

 

//*****************************************************************************
//
// hello.c - Simple hello world example.
//
// Copyright (c) 2012-2014 Texas Instruments Incorporated.  All rights reserved.
// Software License Agreement
// 
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
// 
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
// 
// This is part of revision 2.1.0.12573 of the EK-TM4C123GXL Firmware Package.
//
//*****************************************************************************

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
//#include "driverlib/gpio.c"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
//#include "driverlib/sysctl.c"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"
#include "inc/hw_gpio.h"
#include "inc/hw_sysctl.h"
#include "inc/tm4c1294ncpdt.h"
#include "drivers/pinout.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom_map.h"



//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif

// System clock rate in Hz.
//
//*****************************************************************************
uint32_t g_ui32SysClock;

//*****************************************************************************

//LCD code
//PE0 to PE3 Data Lines
//PD6 = RS
//PD7 = E
//R/W = GND
//#define databits GPIO_PORTE_AHB_DATA_R


#define databits GPIO_PORTE_AHB_DATA_R



void LCD_command(unsigned char data)
{

	GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6|GPIO_PIN_7,0x00);
	SysCtlDelay(400);
	GPIOPinWrite(GPIO_PORTE_BASE,GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3,data); // DATA Pins for 4 bit mode
	SysCtlDelay(400);
	databits=data>>4;
	GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6|GPIO_PIN_7,0x80);
	SysCtlDelay(400);
	GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6|GPIO_PIN_7,0x00);
	databits=data;
	GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6|GPIO_PIN_7,0x80);
	SysCtlDelay(400);
	GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6|GPIO_PIN_7,0x00);

}

void LCD_command_8bit(unsigned char data)
{
	GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6|GPIO_PIN_7,0x00);
	SysCtlDelay(15000);
	GPIOPinWrite(GPIO_PORTE_BASE,GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3,data); // DATA Pins for 4 bit mode
	SysCtlDelay(15000);
	databits=(data);
	GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6|GPIO_PIN_7,0x80);
	SysCtlDelay(15000);
	databits=(data);
	GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6|GPIO_PIN_7,0x00);

}
void LCD_data(unsigned char data)
{
	GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6|GPIO_PIN_7,0x00);
	GPIOPinWrite(GPIO_PORTE_BASE,GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3,data); // DATA Pins for 4 bit mode
	GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6,GPIO_PIN_6);
	SysCtlDelay(400);
	databits=data>>4;
	GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_7,GPIO_PIN_7);
	SysCtlDelay(400);
	GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_7,0);
	databits=data;
	GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_7,GPIO_PIN_7);
    SysCtlDelay(400);
    GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_7,0);

}

void clear (void)
{
	LCD_command(0x01);
	SysCtlDelay(30000);
}

void LCD_Init()
{
	// clear();
	SysCtlDelay(SysCtlClockGet()/30);
	LCD_command_8bit(0x30);
	LCD_command_8bit(0x30);
	LCD_command_8bit(0x30);
	LCD_command_8bit(0x20);
	LCD_command(0x28);
    LCD_command(0x0C);
    clear();
    LCD_command(0x06);

}

void LCD_String_Display(unsigned char *str)
{

 while(*str)
 {
	 LCD_data(*str);
	 str++;
 }
return;
}

int main(void)
{
	g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
	                SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
	                SYSCTL_CFG_VCO_480), 120000000);

	// SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

	 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
	 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
	 GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE,GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);
	 GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE,GPIO_PIN_6|GPIO_PIN_7);
    LCD_Init();
    clear();
    LCD_String_Display("WELCOME");
    LCD_command(0xC0);
    LCD_String_Display("WORLD");
    SysCtlDelay(50000);
    GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6,0x00);
}

LCD _tm4c129.zip

 

  • Look here: (extracted from your code, above)

    void LCD_command_8bit(unsigned char data)
    {
    GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6|GPIO_PIN_7,0x00);
    SysCtlDelay(15000);
    GPIOPinWrite(GPIO_PORTE_BASE,GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3,data); // DATA Pins for 4 bit mode
    SysCtlDelay(15000);
    databits=(data);
    GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6|GPIO_PIN_7,0x80);
    SysCtlDelay(15000);
    databits=(data);
    GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6|GPIO_PIN_7,0x00);

    }

    Now the Lcd initialization - when in "4 bit mode" is well documented w/in HD44780 manual.  (which I've listed here, multiple times)   And such code "expects" repeated "3s" - which cannot be achieved via your use of, "LCD_command_8bit(0x30);" is not that true?

    You employ the 4 lsb of your data port "//PE0 to PE3 Data Lines."   Yet your, "LCD_command_8bit()" function employs NO shifts - thus outputs (only) the (unwanted) lower 8 bits!   The Lcd then "never" sees the vital "3" - let alone its required repetition.

    I'm in disbelief that this code - as listed here - would run on (even) the x123...

  • Hello cb1,

    Thank you for your suggestions. First of all I made some changes in code changed the port from Port E to Port L and from Port D to Port K and also inserted some delays as mentioned in LCD manual. So the code is working now. It is as below:

    //*****************************************************************************
    //
    // hello.c - Simple hello world example.
    //
    // Copyright (c) 2012-2014 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    // 
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    // 
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    // 
    // This is part of revision 2.1.0.12573 of the EK-TM4C123GXL Firmware Package.
    //
    //*****************************************************************************
    
    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/debug.h"
    #include "driverlib/fpu.h"
    #include "driverlib/gpio.h"
    //#include "driverlib/gpio.c"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/sysctl.h"
    //#include "driverlib/sysctl.c"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    #include "inc/hw_gpio.h"
    #include "inc/hw_sysctl.h"
    #include "inc/tm4c1294ncpdt.h"
    #include "drivers/pinout.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom_map.h"
    
    
    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "drivers/pinout.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    
    
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    void
    __error__(char *pcFilename, uint32_t ui32Line)
    {
    }
    #endif
    
    // System clock rate in Hz.
    //
    //*****************************************************************************
    uint32_t g_ui32SysClock;
    
    //*****************************************************************************
    
    //LCD code
    //PL0 to PL3 Data Lines
    //PK6 = RS
    //PK7 = E
    //R/W = GND
    
    
    
    #define databits GPIO_PORTL_DATA_R
    
    
    
    void LCD_command(unsigned char data)
    {
    	SysCtlDelay(SysCtlClockGet()/5000);
    	GPIOPinWrite(GPIO_PORTK_BASE, GPIO_PIN_6|GPIO_PIN_7,0x00);
    	SysCtlDelay(10);
    	GPIOPinWrite(GPIO_PORTL_BASE,GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3,data); // DATA Pins for 4 bit mode
    	SysCtlDelay(10);
    	databits=data>>4;
    	GPIOPinWrite(GPIO_PORTK_BASE, GPIO_PIN_6|GPIO_PIN_7,0x80);
    	SysCtlDelay(10);
    	GPIOPinWrite(GPIO_PORTK_BASE, GPIO_PIN_6|GPIO_PIN_7,0x00);
    	databits=data;
    	GPIOPinWrite(GPIO_PORTK_BASE, GPIO_PIN_6|GPIO_PIN_7,0x80);
    	SysCtlDelay(10);
    	GPIOPinWrite(GPIO_PORTK_BASE, GPIO_PIN_6|GPIO_PIN_7,0x00);
    	SysCtlDelay(10);
    }
    
    void LCD_command_8bit(unsigned char data)
    {
    	SysCtlDelay(10);
    	GPIOPinWrite(GPIO_PORTK_BASE, GPIO_PIN_6|GPIO_PIN_7,0x00);
    	SysCtlDelay(15000);
    	GPIOPinWrite(GPIO_PORTL_BASE,GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3,data); // DATA Pins for 4 bit mode
    	SysCtlDelay(15000);
    	databits=(data);
    	GPIOPinWrite(GPIO_PORTK_BASE, GPIO_PIN_6|GPIO_PIN_7,0x80);
    	SysCtlDelay(15000);
    	databits=(data);
    	GPIOPinWrite(GPIO_PORTK_BASE, GPIO_PIN_6|GPIO_PIN_7,0x00);
    	SysCtlDelay(15000);
    }
    void LCD_data(unsigned char data)
    {
        SysCtlDelay(SysCtlClockGet()/5000);
    	GPIOPinWrite(GPIO_PORTK_BASE, GPIO_PIN_6|GPIO_PIN_7,0x00);
    	GPIOPinWrite(GPIO_PORTL_BASE,GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3,data); // DATA Pins for 4 bit mode
    	GPIOPinWrite(GPIO_PORTK_BASE, GPIO_PIN_6,GPIO_PIN_6);
    	SysCtlDelay(10);
    	databits=data>>4;
    	GPIOPinWrite(GPIO_PORTK_BASE, GPIO_PIN_7,GPIO_PIN_7);
    	SysCtlDelay(10);
    	GPIOPinWrite(GPIO_PORTK_BASE, GPIO_PIN_7,0x00);
    	databits=data;
    	GPIOPinWrite(GPIO_PORTK_BASE, GPIO_PIN_7,GPIO_PIN_7);
    	SysCtlDelay(10);
        GPIOPinWrite(GPIO_PORTK_BASE, GPIO_PIN_7,0x00);
        SysCtlDelay(10);
    
    }
    
    void clear (void)
    {
    
    	LCD_command(0x01);
    	SysCtlDelay(30000);
    }
    
    void LCD_Init()
    {
    
    	    clear();
    
    		SysCtlDelay(SysCtlClockGet()/15);
    
    		LCD_command_8bit(0x30);
    
    		SysCtlDelay(SysCtlClockGet()/30);
    
    		LCD_command_8bit(0x30);
    
    		SysCtlDelay(SysCtlClockGet()/30);
    
    		LCD_command_8bit(0x30);
    
    		SysCtlDelay(SysCtlClockGet()/30);
    
    		LCD_command_8bit(0x20);
    
    		SysCtlDelay(SysCtlClockGet()/30);
    
    		LCD_command(0x28);
    
    		SysCtlDelay(SysCtlClockGet()/30);
    
    	    LCD_command(0x0C);
    
    	    SysCtlDelay(SysCtlClockGet()/30);
    
    	    clear();
    
    }
    
    void LCD_String_Display(unsigned char *str)
    {
    
     while(*str)
     {
    	 LCD_data(*str);
    	 str++;
     }
    return;
    }
    
    
    int main(void)
    
    {
    	//SysCtlDelay(30000);
    	g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
    	                SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
    	                SYSCTL_CFG_VCO_480), 120000000);
    	 SysCtlDelay(SysCtlClockGet()/5000);
    	 PinoutSet(false, false);
    	 ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK);
    	 ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOL);
    	 ROM_GPIOPinTypeGPIOOutput(GPIO_PORTK_BASE, GPIO_PIN_6|GPIO_PIN_7);
    	 ROM_GPIOPinTypeGPIOOutput(GPIO_PORTL_BASE, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);
        LCD_Init();
        clear();
        LCD_String_Display("WELCOME");
        LCD_command(0xC0);
        LCD_String_Display("WORLD");
        GPIOPinWrite(GPIO_PORTK_BASE,GPIO_PIN_6|GPIO_PIN_7,0x00);
    
    }
    

    Now coming back to the doubts, what happens is in "LCD_command_8bit" function if I insert right shift, so on initial power up LCD shows garbage value then I press reset and LCD display correct value. 

    What I think is as LCD ask for MSB first, so with the right shift it will get "3" first and at the time of power up LCD remain in 8 bit mode only. But still I need to check and I will find out the correct explanation.

    Now second is in earlier code I was using PD6 pin which is by default connected with USB TPS2052B in TM4C129 LP. So I changed the port from Port D to Port K.

    And in TM4C129 LP port is from PE0 to PE5 only not up to PE7. So I changed the port to Port L.

    With these changes the code is working. Now I want to use the single port. Suppose port E. In that case PE0 to PE3 works as data line and PE4 as RS and PE5 as E. But in case of single port condition the LCD shows garbage.

    I am trying to find solution . Please guide me .

    Thank you.

    Regards,

    Anup.  

  • anupsingh chandel said:
    Now I...use the single port "E."   In that case PE0-PE3 (data) - PE4 > RS, PE5 > E. But in case of single port condition the LCD shows garbage.

    While desirable to "use just one port" that gravely impacts your Lcd software.   You know that "4 shifts" are required to "massage" your "8 bit" port data into two, 4 bit nibbles, for transfer to the Lcd.   Thus - the intermix of those two "upper nibble bits" is likely to confound.

    Surely - at least for now - you can harvest those 2 control bits from a separate MCU port.   Once that's done - & Lcd up/running - we can return to, "one port (alone) for 4 bit Lcd operation.   Firm/I are huge proponents of KISS - and two ports best serves that key guideline.

    You've learned a critical lesson in discovering the need to employ "less used" port bits (and ports) in such external device control.   Always best to fully survey the MCU's ports - and potential operation - to prevent port/pin contention and the (endless) port change merry-go-round...