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.

TM4C123GH6PM: Tiva C launchpad with LCD 16x2 in 8 bits mode

Part Number: TM4C123GH6PM

Hi, I've been strugling for 2 weeks triying to connect my launchpad to an LCD 16x2 in 8bits mode (I try 4bits too, but I read that it should be easier in 8bits), and I'm lost, I try changing everything, right all again, read forums about this and could not find any solution :/

Connections
D0-D7  ----> B0-B7

E ----> D0

Rs ---> D1

RW---> GND

I have the contrast connected , so I can regulate it.


My code (there are some irrelevant includes that are for other things):

#define TARGET_IS_BLIZZARD_RA1
#include <stdint.h>
#include "stdlib.h"
#include <stdbool.h>
//#include "inc/hw_can.h"
//#include "inc/hw_ints.h"
//#include "driverlib/fpu.h"
//#include "driverlib/can.h"
//#include "grlib/grlib.h"
//#include "drivers/cfal96x64x16.h"
//#include "utils/uartstdio.h"
//#include "driverlib/interrupt.h"

//#define TARGET_IS_BLIZZARD_RA1
#include <stdio.h>
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
//#include "driverlib/rom.h"
//#include "driverlib/uart.h"
//#include "driverlib/adc.h"
//#include "utils/uartstdio.h"
//#include "driverlib/pin_map.h"
//#include <inttypes.h> //se utiliza para imprimir los valores uint32_t


#include "math.h"


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

#define LCD_DATA GPIO_PORTB_BASE //LCD data port to PORTb
#define ctrl PORTE //LCD control port to PORTE
#define rs GPIO_PIN_1 //register select signal to RE0

#define en GPIO_PIN_2 //enable signal to RE2

//Function Prototypes
void init_LCD(void); //Function to initialise the LCD
void LCD_command(unsigned char cmd); //Function to pass command to the LCD
void LCD_data(unsigned char data); //Function to write character to the LCD
void LCD_write_string(char *str);//Function to write string to the LCD
void msdelay (unsigned int time); //Function to generate delay


// DEFINICION DE PUERTOS
#define perifericoData SYSCTL_PERIPH_GPIOB
#define writeData GPIO_PORTB_BASE
#define B0 GPIO_PIN_0
#define B1 GPIO_PIN_1
#define B2 GPIO_PIN_2
#define B3 GPIO_PIN_3
#define B4 GPIO_PIN_4
#define B5 GPIO_PIN_5
#define B6 GPIO_PIN_6
#define B7 GPIO_PIN_7
#define dataPins B0|B1|B2|B3|B4|B5|B6|B7

#define perifericoControl SYSCTL_PERIPH_GPIOD
#define writeControl GPIO_PORTD_BASE
#define E GPIO_PIN_0
#define RS GPIO_PIN_1
#define controlPins E|RS

#define perifericoLed SYSCTL_PERIPH_GPIOF
#define writeLed GPIO_PORTF_BASE
#define led1 GPIO_PIN_1
#define led2 GPIO_PIN_2
#define led3 GPIO_PIN_3
#define leds led3|led2|led1
#define cian 0x0C
#define azul 0x04
#define rojo 0x02
#define verde 0x08
#define off 0x00


int delayms (int tiempo){
int resultado = 1000 * (tiempo / (0.0000625*1000));
return resultado;
}
int delayus (int tiempo){
int resultado = 1000 * (tiempo / (0.0625*1000));
return resultado;
}

//Start of Main Program
int main(void)
{
char var1[] = "I";//Declare message to be displayed

/*Set the clocking to directly run from the crystal at 16MHz*/
SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);

/* Set the clock for the GPIO Port B y D */
SysCtlPeripheralEnable(perifericoControl);
SysCtlPeripheralEnable(perifericoData);
SysCtlPeripheralEnable(perifericoLed);
/* Set the type of the GPIO Pin */
SysCtlDelay(8000000);

GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, B0|B1|B2|B3|B4|B5|B6|B7);
GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE,E|RS);
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE,led3|led2|led1);
SysCtlDelay(8000000);


init_LCD(); // call function to initialise of LCD
SysCtlDelay(8000000);


/*
LCD_command(0xC0); // initiate cursor to second line 0b1100 0000
LCD_write_string(var2);//Display message on second line
*/
while (1){ //Loop here
LCD_write_string(var1); //Display message on first line
GPIOPinWrite(writeLed, led3|led2|led1 ,azul);//LED AZUL

SysCtlDelay(delayms(1000));
GPIOPinWrite(writeLed, led3|led2|led1 ,off);//LED AZUL
}
} //End of Main

//Function Definitions
void msdelay (unsigned int time) //Function to generate delay
{
unsigned int i, j;
for (i = 0; i < time; i++)
for (j = 0; j < 275; j++);//Calibrated for a 1 ms delay in MPLAB
}

void init_LCD(void) // Function to initialise the LCD
{
//16MHz ---- 62.5ns
SysCtlDelay(8000000); // 550000 ciclos
GPIOPinWrite(writeControl, RS | E, 0x00); //COLOCO RS Y E en 0 por las dudas Rs = 0 para instrucciones E = 1 cuando se comienza a escribir

//clear display 0b 0 0 0 0 0 0 0 1
//return home 0b 0 0 0 0 0 0 1 x
//entry mode set 0b 0 0 0 0 0 1 I/D S I/D = 1 mueve el cursor a la derecha S = 1 mueve el display
//display on/off 0b 0 0 0 0 1 D C B D display C cursor B blink
//cursor or display shift 0b 0 0 0 1 S/C R/L x x S/C = 0 mueve cursor R/L = 1 derecha
//function set 0b 0 0 1 DL N F x x DL = 1 - 8bits mode N = 1 - 2line display F = 1 - 5x11dots

// FIRST 

GPIOPinWrite(writeLed, leds ,rojo);
LCD_command(0x3F);
GPIOPinWrite(writeLed, leds ,off);
SysCtlDelay(delayms(5));

// SECOND

GPIOPinWrite(writeLed, leds ,rojo);
LCD_command(0x3F);
GPIOPinWrite(writeLed, leds ,off);
SysCtlDelay(delayus(110));

// THIRD

GPIOPinWrite(writeLed, leds ,rojo);
LCD_command(0x3F);
GPIOPinWrite(writeLed, leds ,off);
SysCtlDelay(delayus(110));

// FORTH

GPIOPinWrite(writeLed, leds ,rojo);
LCD_command(0x30);
GPIOPinWrite(writeLed, leds ,off);
SysCtlDelay(delayms(2));

// FIVETH

GPIOPinWrite(writeLed, leds ,rojo);
LCD_command(0x08);
GPIOPinWrite(writeLed, leds ,off);
SysCtlDelay(delayms(2));

//SIXTH

GPIOPinWrite(writeLed, leds ,rojo);
LCD_command(0x01);
GPIOPinWrite(writeLed, leds ,off);
SysCtlDelay(delayms(2));

//SEVENTH

GPIOPinWrite(writeLed, leds ,rojo);
LCD_command(0x06);
GPIOPinWrite(writeLed, leds ,off);
SysCtlDelay(delayms(2));

//EIGHTH  display on cursor on blink on

GPIOPinWrite(writeLed, leds ,rojo);
LCD_command(0x0F);
GPIOPinWrite(writeLed, leds ,off);
SysCtlDelay(delayms(2));

}

void LCD_command(unsigned char cmd) //Function to pass command to the LCD
{


GPIOPinWrite(writeData, B7|B6|B5|B4|B3|B2|B1|B0,cmd);

GPIOPinWrite(writeControl, RS | E, 0x00);
SysCtlDelay(delayus(3));

GPIOPinWrite(writeControl, RS | E, 0x01);//Generate High to low pulse on EN
SysCtlDelay(delayus(3));
GPIOPinWrite(writeControl, RS | E, 0x00);
SysCtlDelay(delayus(110));
}

void LCD_data(unsigned char data)//Function to write data to the LCD
{
/* Writing Command on Port B*///Send data on LCD data bus
GPIOPinWrite(writeControl, RS | E, 0x02);//RS = 1 since DATA to LCD
GPIOPinWrite(writeData, dataPins ,data);
GPIOPinWrite(writeLed, led3|led2|led1 ,verde);//LED VERDE

SysCtlDelay(delayus(3));


GPIOPinWrite(writeControl, RS | E, 0x03);//RS = 1 since DATA to LCD
SysCtlDelay(delayus(3));

GPIOPinWrite(writeControl, RS | E,0x02);
GPIOPinWrite(writeLed, led3|led2|led1 ,0x00);//LED
SysCtlDelay(delayus(110));
}
//Function to write string to LCD
void LCD_write_string(char *str)
{
int i = 0;
while (str[i] != 0)
{
LCD_data(str[i]); // sending data on LCD byte by byte
SysCtlDelay(8000000);
i++;
}
}

  • Most character LCDs out of the box will default to blinking a cursor. Do you see that?

    If no, are you driving the backlight? Is there a contrast pin?

  • My friend - you are, "Victim # 1xxx" of  your  '123 LPad's tieing pins PD0/PD1  directly   to  PB6/PB7!       This UNWANTED - often Damaging yet surely Delaying - UNEXPECTED "Cross-Connection of MCU pins - is SURE to "CAUSE YOUR ISSUE!      (yet - may  "not stand-alone" - I've made little effort to "review your code.")

    Review of  the '123 LPad's schematic - (if/when) you squint - (may) reveal the cross-connections - as described above.     You are especially unfortunate as you've employed BOTH "paired sets" of GPIO - to drive your Char-based LCD!     Thus your efforts were DOOMED.

    To overcome this LPad "short-coming" it is necessary to remove "Plague-Istors R9, R10."    (directly beneath the MCU)    We prefer to "tombstone these" (after removal - tack solder one resistor lead to its pad - vertically oriented (resembles a tombstone) - as this serves as a clear reminder that NOW - that board (may) work!

    If you employ the forum's Search Box (atop the forum page) SEVERAL of my past "Char LCD Module" Solutions should reveal.    I have provided the "original" HD44780 spec - the "grandfather" of ALL Char-based, LCD Controllers.    Initialization is most important - and indeed - your choice of 8-bit over 4-bit is (beyond) wise.    Only after 8-bit has succeeded - should 4-bit mode be attempted.

    If you remove those "Plague-Istors" - and then repeat & report your tests - those here are sure to be able to assist further.    (pointless to perform code review NOW - while those "Plague-Istors" continue to, "Inflict pain - upon hapless User-Clients."

    Vendor has repeatedly been advised of this "weakness" - and for (beyond) the past FIVE YEARS - (minus ANY Vendor Correction/Enhanced Warning) posters have "Ascended the LPad's (poorly marked cliff)" - and have, "Descended Rapidly to the depths - far below."     (step cautiously - avoiding the broken bones & bloodshed - of those before you...)

  • Those resistors are a menace.
  • Indeed Peter - and as stated - myself + a few others - have repeatedly urged some (slight) Vendor  Re-Think.     (or  FIRST-THINK - if I may be direct!)

    It was once claimed that the "Plague-Istors" served to heighten compatibility for (long past) MSP users.     And the "2, maybe 3" - who benefited from such compatibility - have (indirectly) inflicted "Pain/Suffering" upon HUNDREDS (perhaps Thousands) here!      (Note that  "not all tormented" by that unwise vendor decision - make the time/effort to "Report their suffering - and failed projects!")

    I have personally suggested that "Plague-Istors" be "bagged" - again for the "2 or 3" (maybe) - who seek that "compatibility."

    Instead - vendor INACTION (that's polite - is it not) lures posters to cliff-top - from which "menacing winds" - insure their bloody plunge!     It has been estimated that (easily) a "100:1" ratio exists - "Hindered vs. Helped" - by a proven, patently unwise vendor decision.     (Cast w/in cliff-side stone - apparently!)

    No one expects "Vendor Perfection!"        Yet "Vendor Correction" - in response to a rather severe & on-going issue - should NOT be AVOIDED!     (and that's the case here - is it not?)

  • Thank you very much, I can't belive that I've been strugling like 2 weeks just for that thing! I just switch the terminals PB6-PB7 to PC4 and PC5 and did some changes in the code.
    Now the LCD is initialize but it does not show in the display what it should. I'm going to work on that, thanks
  • Well it work!
    Thanks very much
    I attach the final code If someone is interested in use it.

    /*
    * Lautaro Dapino
    * 27/03/2018
    */

    #define TARGET_IS_BLIZZARD_RA1
    #include <stdint.h>
    #include "stdlib.h"
    #include <stdbool.h>
    //#include "inc/hw_can.h"
    //#include "inc/hw_ints.h"
    //#include "driverlib/fpu.h"
    //#include "driverlib/can.h"
    //#include "grlib/grlib.h"
    //#include "drivers/cfal96x64x16.h"
    //#include "utils/uartstdio.h"
    //#include "driverlib/interrupt.h"

    //#define TARGET_IS_BLIZZARD_RA1
    #include <stdio.h>
    #include "driverlib/sysctl.h"
    #include "driverlib/gpio.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    //#include "driverlib/rom.h"
    //#include "driverlib/uart.h"
    //#include "driverlib/adc.h"
    //#include "utils/uartstdio.h"
    //#include "driverlib/pin_map.h"
    //#include <inttypes.h> //se utiliza para imprimir los valores uint32_t


    #include "math.h"


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

    //Function Prototypes
    void init_LCD(void); //Function to initialise the LCD
    void LCD_command(unsigned char cmd); //Function to pass command to the LCD
    void LCD_data(unsigned char data); //Function to write character to the LCD
    void LCD_write_string(char *str);//Function to write string to the LCD
    void msdelay (unsigned int time); //Function to generate delay


    /*
    * CONNECTIONS
    * LAUNCHPAD TIVA C
    * TM4C123G
    * Rs E D0 D1 D2 D3 D4 D5 D6 D7 Vss Vdd V0 RW A K
    * PD0 PD1 PB0 PB1 PB2 PB3 PB4 PB5 PC4 PC5 GND +5v resistor GND +5v GND
    */

    // DEFINICION DE PUERTOS
    #define perifericoData SYSCTL_PERIPH_GPIOB
    #define writeData GPIO_PORTB_BASE
    #define B0 GPIO_PIN_0
    #define B1 GPIO_PIN_1
    #define B2 GPIO_PIN_2
    #define B3 GPIO_PIN_3
    #define B4 GPIO_PIN_4
    #define B5 GPIO_PIN_5

    #define perifericoDataC SYSCTL_PERIPH_GPIOC
    #define writeDataC GPIO_PORTC_BASE
    #define B6 GPIO_PIN_4
    #define B7 GPIO_PIN_5


    #define perifericoControl SYSCTL_PERIPH_GPIOD
    #define writeControl GPIO_PORTD_BASE
    #define E GPIO_PIN_0
    #define RS GPIO_PIN_1
    #define controlPins E|RS

    #define perifericoLed SYSCTL_PERIPH_GPIOF
    #define writeLed GPIO_PORTF_BASE
    #define led1 GPIO_PIN_1
    #define led2 GPIO_PIN_2
    #define led3 GPIO_PIN_3
    #define leds led3|led2|led1
    #define cian 0x0C
    #define azul 0x04
    #define rojo 0x02
    #define verde 0x08
    #define off 0x00


    int delayms (int tiempo){
    int resultado = 1000 * (tiempo / (0.0000625*1000));
    return resultado;
    }
    int delayus (int tiempo){
    int resultado = 1000 * (tiempo / (0.0625*1000));
    return resultado;
    }

    //Start of Main Program
    int main(void)
    {
    char var1[] = "hola";//Declare message to be displayed

    /*Set the clocking to directly run from the crystal at 16MHz*/
    SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);

    //Enable ports B C D
    SysCtlPeripheralEnable(perifericoControl);
    SysCtlPeripheralEnable(perifericoData);
    SysCtlPeripheralEnable(perifericoDataC);
    SysCtlPeripheralEnable(perifericoLed);
    /* Set the type of the GPIO Pin */
    SysCtlDelay(8000000);

    GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, B0|B1|B2|B3|B4|B5);
    GPIOPinTypeGPIOOutput(GPIO_PORTC_BASE, B6|B7);
    GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE,E|RS);
    GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE,led3|led2|led1);
    SysCtlDelay(8000000);




    init_LCD(); // call function to initialise of LCD
    SysCtlDelay(8000000);


    LCD_write_string(var1); //Display message on first line

    while (1){ //Loop here
    GPIOPinWrite(writeLed, led3|led2|led1 ,azul);//LED AZUL

    SysCtlDelay(delayms(1000));
    GPIOPinWrite(writeLed, led3|led2|led1 ,off);//LED AZUL
    }
    } //End of Main

    //Function Definitions
    void init_LCD(void) // Function to initialise the LCD
    {
    //16MHz ---- 62.5ns
    SysCtlDelay(8000000); // 550000 ciclos
    GPIOPinWrite(writeControl, RS | E, 0x00); //COLOCO RS Y E en 0 por las dudas Rs = 0 para instrucciones E = 1 cuando se comienza a escribir

    //clear display 0b 0 0 0 0 0 0 0 1
    //return home 0b 0 0 0 0 0 0 1 x
    //entry mode set 0b 0 0 0 0 0 1 I/D S I/D = 1 mueve el cursor a la derecha S = 1 mueve el display
    //display on/off 0b 0 0 0 0 1 D C B D display C cursor B blink
    //cursor or display shift 0b 0 0 0 1 S/C R/L x x S/C = 0 mueve cursor R/L = 1 derecha
    //function set 0b 0 0 1 DL N F x x DL = 1 - 8bits mode N = 1 - 2line display F = 1 - 5x11dots

    GPIOPinWrite(writeLed, leds ,rojo);
    LCD_command(0x38);
    GPIOPinWrite(writeLed, leds ,off);
    SysCtlDelay(delayms(5));

    GPIOPinWrite(writeLed, leds ,rojo);
    LCD_command(0x38);
    GPIOPinWrite(writeLed, leds ,off);
    SysCtlDelay(delayus(110));

    GPIOPinWrite(writeLed, leds ,rojo);
    LCD_command(0x38);
    GPIOPinWrite(writeLed, leds ,off);
    SysCtlDelay(delayus(110));

    GPIOPinWrite(writeLed, leds ,rojo);
    LCD_command(0x38);
    GPIOPinWrite(writeLed, leds ,off);
    SysCtlDelay(delayms(2));

    GPIOPinWrite(writeLed, leds ,rojo);
    LCD_command(0x0F);
    GPIOPinWrite(writeLed, leds ,off);
    SysCtlDelay(delayms(2));

    GPIOPinWrite(writeLed, leds ,rojo);
    LCD_command(0x01);
    GPIOPinWrite(writeLed, leds ,off);
    SysCtlDelay(delayms(2));

    GPIOPinWrite(writeLed, leds ,rojo);
    LCD_command(0x06);
    GPIOPinWrite(writeLed, leds ,off);
    SysCtlDelay(delayms(2));
    }

    void LCD_command(unsigned char cmd) //Function to pass command to the LCD
    {


    GPIOPinWrite(writeData, B5|B4|B3|B2|B1|B0, cmd & 0x3F);
    GPIOPinWrite(writeDataC, B7|B6, (cmd & 0xC0) >> 2);

    GPIOPinWrite(writeControl, RS | E, 0x00);
    SysCtlDelay(delayus(3));

    GPIOPinWrite(writeControl, RS | E, 0x01);//Generate High to low pulse on EN
    SysCtlDelay(delayus(3));
    GPIOPinWrite(writeControl, RS | E, 0x00);
    SysCtlDelay(delayus(110));
    }

    void LCD_data(unsigned char data)//Function to write data to the LCD
    {
    /* Writing Command on Port B*///Send data on LCD data bus
    GPIOPinWrite(writeControl, RS | E, 0x02);//RS = 1 since DATA to LCD
    GPIOPinWrite(writeData, B5|B4|B3|B2|B1|B0 ,data & 0x3F);
    GPIOPinWrite(writeDataC, B7|B6 , (data & 0xC0) >> 2);

    GPIOPinWrite(writeLed, led3|led2|led1 ,verde);//LED VERDE

    SysCtlDelay(delayus(3));


    GPIOPinWrite(writeControl, RS | E, 0x03);//RS = 1 since DATA to LCD
    SysCtlDelay(delayus(3));

    GPIOPinWrite(writeControl, RS | E,0x02);
    GPIOPinWrite(writeLed, led3|led2|led1 ,0x00);//LED
    SysCtlDelay(delayus(110));
    }
    //Function to write string to LCD
    void LCD_write_string(char *str)
    {
    int i = 0;
    while (str[i] != 0)
    {
    LCD_data(str[i]); // sending data on LCD byte by byte
    SysCtlDelay(8000000);
    i++;
    }
    }
  • Thank you - again the (otherwise) excellent '123 LPad - continues to "plague" those who (reasonably) "Do NOT expect "cross-connect" of multiple MCU GPIO.

    Sorry for your "pain/suffering" (perhaps hallowed vendor - will at some point - bag those Plague-Istors.)

    It is good that you persisted - followed the "coaching" - and succeeded.

    Dapino Lautaro said:
    I just switch the terminals PB6-PB7 to PC4 and PC5

    Now this (mixed Port Data Bus: Ports B & C) is NOT the most efficient means to correct the board plague.     You are forced to employ two separate "Port Writes" - to present the 8-bit data to the Lcd.     Instead - by, "Removing R9/R10" ... OR ... by employing 2 other  Port GPIO (for "E" & "RS" ) you would maintain Port B ALONE as the data bus - and drive the 2 control pins from a separate (non plagued) Port/Pins.