Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

LCD HD44780 with Nucleo STM32F446RE Problems

Status
Not open for further replies.

diksha.k

Member level 5
Joined
Aug 3, 2015
Messages
86
Helped
0
Reputation
0
Reaction score
0
Trophy points
6
Activity points
801
Dear Members,
Hello all members,
I am interfacing LCD module in 8bit mode to STM32F446RE Nucleo board the connections are as below:
wiring lcd+nucleo.png


The pin connections(if unclear in diagram):
Control pins:
RS-->PB0
RW-->PB1
E-->PB3
8bit data pins LCD:
D0-D7-->PC0-PC7

Program Lcd.c:




C:
#include "lcd.h"
    #include <stdint.h>
    #include "delay.h"


    GPIO_Handle_t GPIOConfig;
    void lcd_init()
    {
    
        /*
         *
         * Step1: Make Control pins and LCD 8pins as o/p
         * Step2: Initialising sequence as per datasheet
         */
    //Each of this function enable's clock and configures the pin to o/p mode
        LCDControlpins_init(GPIO_PIN_NO_0);
        LCDControlpins_init(GPIO_PIN_NO_1);
        LCDControlpins_init(GPIO_PIN_NO_3);
  //Each of this function enable's clock and configures the pin to o/p mode for PC0-PC7 pins
        for(int x=0;x<=7;x++)
            LCDDatapins_init(x);
    
        /*
         * Init sequence:
         * as per datasheet
         *
         */
        delay_ms(100);              // all delays are 3/more times the delay specified in
                                         datasheet
        send_cmd(0x30);
        delay_ms(7);
        send_cmd(0x30);
        delay_ms(7);
        send_cmd(0x30);
        delay_ms(7);
    
        send_cmd(0x38);        // Sets no of lines= 2 and F font = 8*5 pixel type
        delay_ms(7);
    
        send_cmd(0x08);        //Sets D,C,B off (Display Cursor,Blink)
        delay_ms(7);
    
        send_cmd(0x01);        //clears the entire display
        delay_ms(7);
    
        send_cmd(0x07);     //I/D=1,S=1 sets the increment of cursor from left to right and no shift
                            of the data.
        delay_ms(7);
    
    
    }
    
    void LCDControlpins_init(uint8_t pinno)
    {
        GPIOConfig.pGPIOx=GPIOB;
        GPIOConfig.GPIO_PinConfig.GPIO_PinMode=GPIO_MODE_OUT;
        GPIOConfig.GPIO_PinConfig.GPIO_PinOPType=GPIO_OP_TYPE_PP;
        GPIOConfig.GPIO_PinConfig.GPIO_PinSpeed=GPIO_SPEED_LOW;
    
        switch(pinno)
        {
            case 0:
                GPIOConfig.GPIO_PinConfig.GPIO_PinNumber=GPIO_PIN_NO_0;
                break;
            case 1:
                GPIOConfig.GPIO_PinConfig.GPIO_PinNumber=GPIO_PIN_NO_1;
                break;
            case 3:
                GPIOConfig.GPIO_PinConfig.GPIO_PinNumber=GPIO_PIN_NO_3;
                break;
            default :
                break;
        }
        GPIO_Init(&GPIOConfig);
    }
    
    void LCDDatapins_init(uint8_t pinno)
    {
        GPIOConfig.pGPIOx=GPIOC;
        GPIOConfig.GPIO_PinConfig.GPIO_PinMode=GPIO_MODE_OUT;
        GPIOConfig.GPIO_PinConfig.GPIO_PinOPType=GPIO_OP_TYPE_PP;
        GPIOConfig.GPIO_PinConfig.GPIO_PinSpeed=GPIO_SPEED_LOW;
        GPIOConfig.GPIO_PinConfig.GPIO_PinNumber=pinno;
        GPIO_Init(&GPIOConfig);
    }
    
    void send_cmd(unsigned char cmd)
    {
        /*
         * RS=0,RW=0,EN=0
         */
        GPIO_WriteToOutputPin(GPIOB, GPIO_PIN_NO_0, 0);  //RS as Instruction
        GPIO_WriteToOutputPin(GPIOB, GPIO_PIN_NO_1, 0);  //RW
        GPIO_WriteToOutputPin(GPIOB, GPIO_PIN_NO_3, 0);  //E
        delay_ms(5);  //extra setup time
        GPIO_WriteToOutputPort(GPIOC,(uint16_t)cmd);
        delay_ms(5);  //extra setup time
       //Make E pin High to Low with reasonable wait time (more than time specified in datasheet)
        GPIO_WriteToOutputPin(GPIOB, GPIO_PIN_NO_3, 1);  //E=high
        delay_ms(2);
        GPIO_WriteToOutputPin(GPIOB, GPIO_PIN_NO_3, 0);  //E=low
        delay_ms(2);
    
    }
    
    void send_data(unsigned char data)
    {
        /*
         * Step1: Set function set 0x38 value
         * Step2: Set 0x0e value that is display and cursor on no blink
         * Step3: Set 0x06 that is increment by 1 and shift display
         * Step4: write data
         */
        send_cmd(0x38);delay_ms(7);
        send_cmd(0x0E);delay_ms(7);
        send_cmd(0x06);delay_ms(7);
        GPIO_WriteToOutputPin(GPIOB, GPIO_PIN_NO_0, 1);  //RS as data
        GPIO_WriteToOutputPin(GPIOB, GPIO_PIN_NO_1, 0);  //RW as write
        GPIO_WriteToOutputPin(GPIOB, GPIO_PIN_NO_3, 0);  //E
        delay_ms(5);  //extra setup time
        GPIO_WriteToOutputPort(GPIOC,(uint16_t)data);
        delay_ms(5);  //extra setup time
        GPIO_WriteToOutputPin(GPIOB, GPIO_PIN_NO_3, 1);  //E=high
        delay_ms(2);
        GPIO_WriteToOutputPin(GPIOB, GPIO_PIN_NO_3, 0);  //E=low
        delay_ms(2);
    
    }

Program lcd.h


C:
#ifndef LCD_H_
    #define LCD_H_
    #include <stdint.h>
    #include "STM32fxx_gpio.h"
    void LCDControlpins_init(uint8_t);
    void LCDDatapins_init(uint8_t );
    void send_cmd(unsigned char );
    void send_data(unsigned char );
    void lcd_init(void);
    #define RS    0
    #define RW    1
    #define E    3
    
    
    #endif /* LCD_H_ */


The code for delay.c file using SYSTICK & polling method:



Code:
#include "delay.h"
        typedef struct
                {
                    uint32_t CSR;
                    uint32_t RVR;
                    uint32_t CVR;
                    uint32_t CALIB;
                }SYST_t;
        
        SYST_t *SYSTick = (SYST_t*)0xE000E010;
        
        //Initialise systick timer
        void systickinit()
        {
            SYSTick->CSR|=(1<<2);  //take processor as clock source for timer
        }
        
        //delay function for 1us delay
        void delay_us(uint32_t blinktime)
        {
        
            systickinit();
            for(int i=0;i<blinktime;i++)
            {
            SYSTick->RVR = 16;  //reload value for 1us
            SYSTick->CSR|=(1<<0);//enable the timer countdown
            while(!(SYSTick->CSR & (1<<16) )); //count down flag until set
            //SYSTick->CSR &=~(1<<16);  //reset the countdown flag
            SYSTick->CSR&=~(1<<0); //disable the timer
        
            }
        }
        
        void delay_ms(uint32_t blinktime)
        {
                blinktime*=1000;
                    delay_us(blinktime);
        }
        
        void delay(uint32_t count)            //provides for loopdelyin ms
        {
                int i,j;
                count=count*1000;
                for(i=0;i<count;i++)
                for(j=0;j<16;j++);        //gives 1us delay
        }

delay.h file:


Code:
#ifndef DELAY_H_
    #define DELAY_H_
    #include <stdint.h>
    
    void delay_us(uint32_t blinktime);
    void delay_ms(uint32_t blinktime);
    void delay(uint32_t count);
    void systickinit(void);
    typedef struct
    {
        uint32_t CSR;
        uint32_t RVR;
        uint32_t CVR;
        uint32_t CALIB;
    }SYST;
    
    
    #endif /* DELAY_H_ */

The main.c:


Code:
#include "STM32fxx_gpio.h"
    #include "lcd.h"
    int main(void)
    {
        lcd_init();
        send_data('H');
        send_data('E');
        for(;;);
    }

The header file for gpio API's are in below github links:
STM32xx Specific driver.h
https://github.com/niekiran/Masteri...e/stm32f4xx_drivers/drivers/inc/stm32f407xx.h

Gpiodriver.c:
https://github.com/niekiran/Masteri...drivers/drivers/src/stm32f407xx_gpio_driver.c

Gpiodriver.h :
https://github.com/niekiran/Masteri...drivers/drivers/inc/stm32f407xx_gpio_driver.h


Dear members,
I have pasted all my codes.. The GPIO.h,.c files are 100percent working fine I have checked with other peripheral projects. The delay function also works correctly tested for led blink..
Now I am stuck in LCD program only..
My main aim is to just display 1 character I have gone through datasheet and forums and have taken everyone's suggestions accurately, I still can't figure out what's wrong with my program.
I have tried this LCD board for Arduino program it works there.
Also, I have checked voltage specifications and all pins connected are 5v Tolerant as per the stm32 datasheet.
Please can someone figure out what I may be doing wrong.
Your suggestions may help me..
I would be grateful..
 

From your code isn't quite clear whether you are making first access to the LCD in 4-bit mode or not.
In some display controllers it is the default configuration mode.

Dear andre,
Thank you for your response..

in lcd_init() the code snippet where I am enabling 8bit data mode is below:
Code:
 void lcd_init()
    {
 
        delay_ms(100);           
        send_cmd(0x30);        //sets data length = 8 bit mode
        delay_ms(7);
        send_cmd(0x30);
        delay_ms(7);
        send_cmd(0x30);
        delay_ms(7);  
  
    }


--- Updated ---

datasheet send_cmd(0x30); delay_ms(7); send_cmd(0x30);
This is the command to enable 8bits data mode for LCD
 
Last edited:

There are some general things, simple yet important to re-check:
Also, I have checked voltage specifications and all pins connected are 5v Tolerant as per the stm32 datasheet.
Please can someone figure out what I may be doing wrong.
Supply pins of stm32 are not 5V tolerant. Only IO pins are tolerant. If you are giving 5V to STM32 directly, you are lucky that its working fine. Instead, if you are giving 3.3V itself, Your circuit diagram shows STM32 Vdd and LCD Vdd are connected to same DC voltage.

I just googled one of the lcd1602 module datasheet, and it says 4.7V minimum Vdd. So I suggest that you use a 5V supply to LCD and use a 3.3V regulator for STM32.
1650987722585.png


2. wiring : loose contact or mis-connection like PB2 instead of PB3. Check individually E, RS pins by making high. if it's actually 3.3V coming out. Try adjusting contrast pot.



2. Add delay_ms(2000) before lcd_init() in main.c. This gives lcd hardware time to initialize.
 

Attachments

  • 1650988113478.png
    1650988113478.png
    3.6 KB · Views: 110

There are some general things, simple yet important to re-check:

Supply pins of stm32 are not 5V tolerant. Only IO pins are tolerant. If you are giving 5V to STM32 directly, you are lucky that its working fine. Instead, if you are giving 3.3V itself, Your circuit diagram shows STM32 Vdd and LCD Vdd are connected to same DC voltage.

I just googled one of the lcd1602 module datasheet, and it says 4.7V minimum Vdd. So I suggest that you use a 5V supply to LCD and use a 3.3V regulator for STM32.
View attachment 175760

2. wiring : loose contact or mis-connection like PB2 instead of PB3. Check individually E, RS pins by making high. if it's actually 3.3V coming out. Try adjusting contrast pot.



2. Add delay_ms(2000) before lcd_init() in main.c. This gives lcd hardware time to initialize.
Dear Vishvesh,
thank you for reply..
I would explain my pin connections again:
STM & arduino both powered via laptop port.( I would have connected the external DC supply but,I don't have it )
LCD VCC-->5V supply pin from arduino
LCD VEE-->Gnd pin from arduino (The GND pin of STM board and arduino connected together)

I have introduced 2second delay as you mentioned as soon as lcd powers up.
The contrast is not controlled by potentiometer.
I am using analogwrite(pin,150) as value to contrast (this value I got when I dumped working programs and tested LCD on Arduino it worked fine on arduino).

Please let me know are the pin connections fine now?
 

At a glance on the GPIO_WriteToOutputPort() funtion on Github, seems like the whole port is being addressed, not the upper 4 bits. Think of using ready-to-use LCD drivers instead of doing from scratch by yourself.
 

Please let me know are the pin connections fine now?
Yeah! seems alright. But ensure that you powerON (I mean connecting USB cable of) arduino first and then stm nucleo board, this way you don't miss initialization signals. I checked schematic of nucleo board. Please use PB4 instead of PB3. PB3 seems to have connected to debugger mcu pins and we don't know if its affecting anything. This would be final test from HW point.

From SW point, as andre suggested, it's better to use ready code available for LCD1602 (there are many tutorials, that you can quickly adapt for nucleo board (this for example)) and test if it works. Then it will be easy to debug what's the issue in your code.

1650992193858.png



I am using analogwrite(pin,150) as value to contrast (this value I got when I dumped working programs and tested LCD on Arduino it worked fine on arduino).
Analogwrite() is basically pwm from arduino. I didnot know we can control contrast by providing pwm. good to know that it works!
 

At a glance on the GPIO_WriteToOutputPort() funtion on Github, seems like the whole port is being addressed, not the upper 4 bits. Think of using ready-to-use LCD drivers instead of doing from scratch by yourself.

Hi ,

I used this link :
and got the correct output as per the pin numbers suggested in the video.. Originally I was using PC0-PC6 so, I changed the pin numbers

My Pin connection Video Pin connection
RS= PC0 PB5
EN= PC2 PB4
R/W= GND GND
D7= PC6 PA6
D6= PC5 PA7
D5= PC4 PB6
D4= PC3 PC7

The LCD displays correctly for video pin connection but, when I change the pin connection over my pin connection, everything is fine until I use pins PC2,PC3,PC4.. (En,D4,D5)

I checked the schematic I don't see any issue in using PC2,3,4 then why is it causing the issue?
your help and advice is appreciated..
 

strange! It should have worked for these pins as well.

One thing I could think of is changing GPIOConfig.GPIO_PinConfig.GPIO_PinSpeed=GPIO_SPEED_LOW to GPOI_SPEED_HIGH or GPIO_SPEED_FAST.

I remember, Long ago I faced similar issue with ST gpio pins and this change resolved.
--- Updated ---

Also the following code is not a good metod to use for a delay. Use a timer or systick tracking for providing delay. Such for loops may be optimized by compiler and you won't get delay as you expect.

Code:
        void delay(uint32_t count)            //provides for loopdelyin ms
        {
                int i,j;
                count=count*1000;
                for(i=0;i<count;i++)
                for(j=0;j<16;j++);        //gives 1us delay
        }

Here you can at-least add volatile int i,j to be on safer side for now.
 
Last edited:

Hi
I am using analogwrite(pin,150) as value to contrast (this value I got when I dumped working programs and tested LCD on Arduino it worked fine on arduino).
I doubt that this properly works without filter. The VSS is not made for PWM.
For sure a DVM may read a meaningful voltage, but still it is square wave an not DC.

I recomend to try with a pot.

Also I recommend to use a scope or a logic analyzer to check signals on the LCD.

Klaus
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top