cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 16x2 lcd driver

megahercas6
Senior
Posted on November 08, 2011 at 21:15

does any one has working 4b mode driver code for HD44780 lcd ?

can't find anything
9 REPLIES 9
singamicro
Associate II
Posted on November 10, 2011 at 11:48

Please see if this is useful.

http://singamicro-63-stm32l152-k1.blogspot.com/p/lcd-page-32.html

Regards.

donald2
Associate II
Posted on November 11, 2011 at 13:26

That code uses a for() loop for timing, and doesn't describe what the assumptions are.  It's both wrong and uninformative.

The command set for a HD44780-compatible display is very simple, but there are many ways to hook up the hardware and different ways to handle the slow timing.  Trying to use generic code results in more complexity than just writing code for your specific configuration.

The only slightly tricky part is the initial command sequence to switch from byte mode (the power-up default) to nibble mode, but that's well explained in every datasheet and article I've seen.

More challenging is structuring your code to meet the application requirements and slow timing of the display.  Simple projects often just do a busy-wait, but if you wanted to waste most of your processing time you wouldn't be using a STM32.

The reference I've used in the past was

http://home.iae.nl/users/pouweha/lcd/lcd.shtml

It's still there, but their web server page generation is currently a little borked.

megahercas6
Senior
Posted on November 18, 2011 at 11:51

since i found a way to turn on and off led, i rewrite LCD program from my last project (it was for MSP430)

and soon  enough i was able to drive lcd :)

ok, first file is lcd.h

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

#include ''stm32f4xx.h''

#define     LCM_OUT               GPIOB->ODR

// connect RW leg to GND, and power supply rails to +5V and gnd

// Define symbolic LCM - MCU pin mappings

// We've set DATA PIN TO 4,5,6,7 for easy translation

//

#define     LCM_PIN_RS            GPIO_Pin_0          // P1.0

#define     LCM_PIN_EN            GPIO_Pin_1          // P1.1

#define     LCM_PIN_D7            GPIO_Pin_7          // P1.7

#define     LCM_PIN_D6            GPIO_Pin_6          // P1.6

#define     LCM_PIN_D5            GPIO_Pin_5          // P1.5

#define     LCM_PIN_D4            GPIO_Pin_4          // P1.4

GPIO_InitTypeDef  GPIO_InitStructure;

#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

void __delay_cycles(int a)

{

    int i = 0;

    int f = 0;

    while(f<a)

    {

            while(i<60)

                {i++;}

        f++;

    }

}

void PulseLcm()

{

    LCM_OUT &= ~LCM_PIN_EN;

    __delay_cycles(220);

    LCM_OUT |= LCM_PIN_EN;

    __delay_cycles(220);

    LCM_OUT &= (~LCM_PIN_EN);

    __delay_cycles(220);

}

void SendByte(char ByteToSend, int IsData)

{

    LCM_OUT &= (~LCM_PIN_MASK);

    LCM_OUT |= (ByteToSend & 0xF0);

    if (IsData == TRUE)

    {

        LCM_OUT |= LCM_PIN_RS;

    }

    else

    {

        LCM_OUT &= ~LCM_PIN_RS;

    }

    PulseLcm();

    LCM_OUT &= (~LCM_PIN_MASK);

    LCM_OUT |= ((ByteToSend & 0x0F) << 4);

    if (IsData == TRUE)

    {

        LCM_OUT |= LCM_PIN_RS;

    }

    else

    {

        LCM_OUT &= ~LCM_PIN_RS;

    }

    PulseLcm();

}

void Cursor(char Row, char Col)

{

    char address;

    if (Row == 0)

    {

        address = 0;

    }

    else

    {

        address = 0x40;

    }

    address |= Col;

    SendByte(0x80 | address, FALSE);

}

void ClearLcmScreen()

{

    SendByte(0x01, FALSE);

    SendByte(0x02, FALSE);

}

void InitializeLcm(void)

{

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

    GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0 | GPIO_Pin_1| GPIO_Pin_4 | GPIO_Pin_5| GPIO_Pin_6| GPIO_Pin_7;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

    GPIO_Init(GPIOB, &GPIO_InitStructure);

    LCM_OUT &= ~(LCM_PIN_MASK);

    __delay_cycles(32000);

    __delay_cycles(32000);

    __delay_cycles(32000);

    LCM_OUT &= ~LCM_PIN_RS;

    LCM_OUT &= ~LCM_PIN_EN;

    LCM_OUT = 0x20;

    PulseLcm();

    SendByte(0x28, FALSE);

    SendByte(0x0E, FALSE);

    SendByte(0x06, FALSE);

}

void PrintStr(char *Text)

{

    char *c;

    c = Text;

    while ((c != 0) && (*c != 0))

    {

        SendByte(*c, TRUE);

        c++;

    }

}

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

and main.c

#include ''stm32f4xx.h''

#include ''lcd.h''

int main(void)

{

    int a = 0;

            while(a<100)

            {

                __delay_cycles(32000);

                a++;

            }

    InitializeLcm();

    __delay_cycles(32000);

    ClearLcmScreen();

    __delay_cycles(32000);

    Cursor(0,0);

    PrintStr(''  STM32F407VGT  '');

    Cursor(1,0);

    __delay_cycles(32000);

    PrintStr(''Hello  World  !!'');

      while(1);

}

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

in define you can set port and legs to drive it, same change must be done in GPIOinit part of program

if code is not working, use more delay :)

now working to print integer and maybe float.

http://img193.imageshack.us/img193/8003/p1010869r.jpg

megahercas6
Senior
Posted on November 20, 2011 at 17:17

if any one know how to use sprintf function so i can print int, float and others, please post it here

dackley
Associate II
Posted on December 06, 2011 at 12:20

This looks like a great initial example for the STM32F4 Discovery board.

I tried compiling it using Atollic's TrueStudio and I seem to be missing some necessary header files. I'd appreciate any help you can give me to get it working using Atollic. Thanks
dackley
Associate II
Posted on December 06, 2011 at 12:59

The C library standard describes the sprintf function as follows:

Synopsis

int sprintf(char *s, const char *format, ...);

Description

The sprintf function is equivalent to fprintf, except that the argument s specifies an array into which the generated output is to be written, rather than to a stream. A null character is written at the end of the characters written, it is not counted as part of the returned sum.

Returns

The sprintf function returns the number of characters written in the array, not counting the terminating null character.
megahercas6
Senior
Posted on December 07, 2011 at 20:27

look close.

first file is lcd.h

second part of code is main.c

main code is near the end, and first part is lcd.h

glory_man
Associate II
Posted on December 09, 2011 at 08:45

Fine code. But...

It does't work in Release configuration with gcc optimization levels -O1, -O2, -O3. It seems like lcd doesn't configured.

I can use it only with  -Os (optimize for size). :)

I think delay-functions optimized by compiler.

donald2
Associate II
Posted on December 10, 2011 at 02:01

That's the same problem that I pointed out in the code above.  Software timing loops are unpredictable and unreliable.

The LCD modules have a Busy indication, available on data line D7 by reading.  Which implies an extra STM32 pin for driving the R/W signal, although it can often be shared.

If you aren't going to use the Busy signal, at least use a reliable timing base for a blind delay.

The STM32 has a SysTick timer for this type of timing, or you can set up a down counter for an interrupt.