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.

Learning STM32 + LCD Interfacing code not working

thannara123

Advanced Member level 5
Joined
Jan 7, 2010
Messages
1,580
Helped
122
Reputation
244
Reaction score
114
Trophy points
1,353
Location
India
Activity points
10,382
Hello
I am trying to interface 4 bit LCD (16x2 ) with STM32f103 controller its not working whats the wrong with me .The main.c code is attached here with


LCD.C file
C:
#include "lcd.h"
#include "main.h"



extern void Delay_Us (uint16_t us);
void LCD_Strobe(void)
{

  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_11, GPIO_PIN_SET);// LCD Enable PIN to High
  HAL_Delay(1);
  //Delay_Us(100);
  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_11, GPIO_PIN_RESET);// LCD Enable High to Low
  //Delay_Us(100);
  HAL_Delay(1);
 }


void LCD_init(void)
{

  HAL_Delay(40);
  LCD_cmd(0x28);
  HAL_Delay(1);
  LCD_cmd(0x28);
  HAL_Delay(1);
  //Delay_Us(100);
  LCD_cmd(0x28);
  LCD_cmd(0x28);            // Function set (4-bit interface, 2 lines, 5*7Pixels)
  LCD_cmd(0x28);            // Function set (4-bit interface, 2 lines, 5*7Pixels)
//  LCD_cmd(0x0c);            // Make cursorinvisible
//    LCD_Clear();            // Clear screen
 //  LCD_cmd(0x6);            // Set entry Mode(auto increment of cursor)
}

void LCD_cmd(__uint16_t cmd)
{       HAL_GPIO_WritePin(GPIOB,GPIO_PIN_11, GPIO_PIN_RESET);
        cmd = (cmd << 8) ;
        GPIOB->ODR =  (cmd & 0xf000);
        LCD_Strobe();
        cmd = (cmd << 4) ;
     // printf("GPIOB->ODR Value %d \n\r",cmd);
        GPIOB->ODR =  (cmd & 0xf000);
        LCD_Strobe();
}


void LCD_data(__uint16_t LCD_Data)
{
     HAL_GPIO_WritePin(GPIOB,GPIO_PIN_11, GPIO_PIN_SET);
     LCD_Data = (LCD_Data << 8) ;
     GPIOB->ODR = (GPIOB->ODR & 0x0fff) | (LCD_Data & 0xf000);
    // LCD_Data =GPIOB->ODR;
    // printf("GPIOB->ODR Value %d \n\r",LCD_Data);
     LCD_Strobe();
     LCD_Data = (LCD_Data << 4) ;
     GPIOB->ODR = (GPIOB->ODR & 0x0fff) | (LCD_Data & 0xf000);
     LCD_Strobe();

}


void LCD_Clear(void)
{
    LCD_cmd(0x01);
    HAL_Delay(5);
}

void LCD_String(const char *ptr)  // ptr pointing the address of displaying string
{
    while (*ptr)             // check weather the endo of file then exit the loop
    {
        LCD_data(*ptr++);    // Sending data to LCD_data functions
    }
}

lcd.png





Whener i check the GPIOB->ODR value it shows some grabage value how to clear it ? is that the problem
 

Attachments

  • Main.c.txt
    7.5 KB · Views: 67
Last edited:
At first sight seems a bit confusing all the cumulative 4 and 8 bit shifts on the variable LCD_Data inside the LCD functions. Furthermore, this is the funtion argument, you should assignt to a local variable instead of updating it. BTW, it is very bad practice ( in addition to start in capital leter ) to name an argument with the same name of its parent funtion.
 
Sorry The PIN is mistaken corrected
C++:
void LCD_cmd(__uint16_t cmd)
{       HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10, GPIO_PIN_RESET);
        cmd = (cmd << 8) ;
        GPIOB->ODR =  (cmd & 0xf000);
        LCD_Strobe();
        cmd = (cmd << 4) ;
     // printf("GPIOB->ODR Value %d \n\r",cmd);
        GPIOB->ODR =  (cmd & 0xf000);
        LCD_Strobe();
}


void LCD_data(__uint16_t lcd_data)
{
     HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10, GPIO_PIN_SET);
     lcd_data = (lcd_data << 8) ;
     GPIOB->ODR = (GPIOB->ODR & 0x0fff) | (lcd_data & 0xf000);
    // LCD_Data =GPIOB->ODR;
    // printf("GPIOB->ODR Value %d \n\r",LCD_Data);
     LCD_Strobe();
     lcd_data = (lcd_data << 4) ;
     GPIOB->ODR = (GPIOB->ODR & 0x0fff) | (lcd_data & 0xf000);
     LCD_Strobe();

}

But itsnot working
--- Updated ---

At first sight seems a bit confusing all the cumulative 4 and 8 bit shifts on the variable LCD_Data inside the LCD functions.
Sir,The 16 bit first left sfiht 8 bit to get the higher Nibbile and the again next 4 left shift to write the lower nibble.
PIN 15 -D7,
PIN 14 -D6,
PIN 13 -D5
,PIN 12 -D4
PIN 11 -EN,
PIN 10 -RS,


,
 
Last edited:
Hello!

To help everybody (including yourself), you could consider avoiding hard code.
For example, when you write:
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10, GPIO_PIN_RESET);
we (and probably you) can't figure out what is port B and what is pin 10. Therefore,
we have to go to your schematic, to know that pin 10 goes to RS.
Beside this, in your schematic, signals E and RS cross twice which makes it difficult to read.

So how to solve that?
Use #define as follows:

Code:
#define LCD_RS GPIO_PIN_10
#define LCD_E GPIO_PIN_11
#define LCD_CTRL GPIOB

Then your code becomes:
Code:
HAL_GPIO_WritePin(LCD_CTRL , LCD_RS, GPIO_PIN_RESET);

Doing this, you don't have to check every now and then what pins 10 and 11 are.

I'm aware that for such a simple circuit, that's not very crucial. But if you read your code
in 3 months, you will have to check again what it was.
That said, your colde looks like it _could_ work, but there are so many things that could
go wrong.
- Did you send the opcode to configure the LCD in 4 bit mode?
- Did you verify that when you use GPIO_WRITE on either E or RS, it effectly changes status
on your hardware?
- Is your stropbe pulse wide enough for the LCD you're using?
etc, etc...

Dora.
 
To understand why your code isn't working, perform single stepping in debugger. Check all pin levels against expected values.
--- Updated ---

Apparently we need to check any single line of your code.

I wondered what else could be wrong and found that the first init instructions are already wrong. Please review example code, e.g. Hitachi hd44780 data sheet. First instruction(s) are 4-bit rather than 8-bit writes. I suggest to perform complete "initialization by instruction" that doesn't depend on successful LCD hardware reset, see below:

1696226010835.jpeg
 
Last edited:
Hello again!

By the way, in this post, you were saying that the hardware works in simulation, not in real hard. If it doesn't, it could explain why the LCD code doesn't work. Does it work now? In this case you could report that it works. Even better, if you also say thanks guys, it would be wonderful.

Dora.
 
To understand why your code isn't working, perform single stepping in debugger. Check all pin levels against expected values.
--- Updated ---

Apparently we need to check any single line of your code.

I wondered what else could be wrong and found that the first init instructions are already wrong. Please review example code, e.g. Hitachi hd44780 data sheet. First instruction(s) are 4-bit rather than 8-bit writes. I suggest to perform complete "initialization by instruction" that doesn't depend on successful LCD hardware reset, see below:

The Initilization I wrote the above is not correct i changed it before posting Sorry for the mistake ,
I used the same initilization earlier on PIC ,,AVR micrcontroller ,that worked one i used here as follows
C:
void LCD_init()
{
 
  __delay_ms(50);  
    LCD_cmd(0x28);
    LCD_cmd(0x28);
    LCD_cmd(0x0C);
    LCD_cmd(0x06);
    LCD_cmd(0x01);  
}

while debugging the value is wrong ,
By the by the project is not worked yet , But I have learned much more from experts thankyou
.This forum gives me a greatfull encourage to do project , am not efficinet I Know , (Expireance makes better Think so)
my passion is electronics .
Due to some of my personal problem I wasnt do electronics earler (some of years )
Now I gets more time and comfort to do so i try to start from stm32

Thanks all
(Earlier forum moderatores told that there is no require to say thanks or some like comment that i avoided that )
 
Earlier forum moderatores told that there is no require to say thanks or some like comment that i avoided that
Not true.
You should not do a post containing only "Thank you" and nothing else..

Instead we modrators encourage to be polite and thankful. But since the forum software provides other options to be thankful there is no use to increase the number of posts per thread just to say "thank you".

Klaus
 
Everything works good as expected in debug mode but not outputing :(

C++:
/*
 * lcd.c

 */
#include "stm32f1xx_hal.h"
#include "lcd.h"
#include "main.h"



extern void Delay_Us (uint16_t us);
void lcd_Strobe(void)
{

    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_11, GPIO_PIN_SET);// LCD Enable PIN to High
    HAL_Delay(1);
    //Delay_Us(100);
    HAL_GPIO_WritePin(GPIOB,EN_Pin, RESET);// LCD Enable High to Low
    //Delay_Us(100);PIO_PIN_11
    HAL_Delay(1);
 }


void LCD_init(void)
{

  HAL_Delay(20);
  lcd_cmd(0x30);
  HAL_Delay(20);
  lcd_cmd(0x30);
  HAL_Delay(20);
  //Delay_Us(100);
  lcd_cmd(0x28);
  HAL_Delay(20);
   lcd_cmd(0x28);            // Function set (4-bit interface, 2 lines, 5*7Pixels)
   lcd_cmd(0x28);            // Function set (4-bit interface, 2 lines, 5*7Pixels)
   lcd_cmd(0x0c);            // Make cursorinvisible
   lcd_Clear();            // Clear screen
   lcd_cmd(0x6);            // Set entry Mode(auto increment of cursor)
}

void lcd_cmd(__uint16_t cmd)
{       GPIOB->ODR =0;
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10, GPIO_PIN_RESET);
        cmd = (cmd << 8) ;
        GPIOB->ODR =  (cmd & 0xf000);
        lcd_Strobe();
        cmd = (cmd << 4) ;
        GPIOB->ODR =  (cmd & 0xf000);
        lcd_Strobe();
        GPIOB->ODR =0;
}


void lcd_data(__uint16_t lcd_data)
{     GPIOB->ODR =0x0000;
    // HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10, GPIO_PIN_SET);
     lcd_data = (lcd_data << 8) ;
     GPIOB->ODR =  (lcd_data& 0xf000)|0x400;
     lcd_Strobe();
     GPIOB->ODR =0;
     lcd_data = (lcd_data << 4) ;
     GPIOB->ODR =  (lcd_data & 0xf000)|0x400;
     lcd_Strobe();
     GPIOB->ODR =0;
}


void lcd_Clear(void)
{
    lcd_cmd(0x01);
    HAL_Delay(5);
}

void lcd_String(const char *ptr)  // ptr pointing the address of displaying string
{
    while (*ptr)             // check weather the endo of file then exit the loop
    {
        lcd_data(*ptr++);    // Sending data to LCD_data functions
    }
}
whats wrong ?
 
Last edited:
Init procedure still not correct.
C:
void lcd_init(void)
{

  HAL_Delay(50);
  lcd_cmd(0x30);
  HAL_Delay(20);
  lcd_cmd(0x30);
  HAL_Delay(20); // for 4bit
  //Delay_Us(100);
  HAL_Delay(10);
  lcd_cmd(0x28); // Function set --> DL=0 (4 bit mode), N = 1 (2 line display) F = 0 (5x8 characters)
  HAL_Delay(1);

   lcd_cmd(0x0c);            // Make cursorinvisible
   lcd_Clear();            // Clear screen
   lcd_cmd(0x6);            // Set entry Mode(auto increment of cursor)
}
--- Updated ---

You may get help from this video.

Thanks ,I am doing this project as learning purpose , .Now I tired with this one :cry:
 
I wonder where you got the initialization sequence. As said it's different from manufacturer suggestions.

I reviewed arbitrary codes found searching for "hd44780 4 bit initialization", all start with sending a 4- bit command. Then either continue with normal command procedure (simplified) method or send three more 4-bit commands (initialization by instruction as quote above).
 
I changed that codeas shown below
C:
void lcd_init(void)
{

  HAL_Delay(100);
  lcd_cmd(0x03);
  HAL_Delay(1);
  lcd_cmd(0x03);
  HAL_Delay(1);
  lcd_cmd(0x03);
  HAL_Delay(1);
  lcd_cmd(0x02); // Function set --> DL=0 (4 bit mode), N = 1 (2 line display) F = 0 (5x8 characters)
  HAL_Delay(1);
  lcd_cmd(0x02);
  lcd_cmd(0x08);
  HAL_Delay(1);
  lcd_cmd(0x00);
  lcd_cmd(0x01);
  HAL_Delay(3);
  lcd_cmd(0x00);

   lcd_cmd(0x0c);            // Make cursorinvisible
   lcd_Clear();            // Clear screen
   lcd_cmd(0x6);            // Set entry Mode(auto increment of cursor)
}

I tried out some of LCD Initilization code which have been working other microcontroller.
And A few of code changed and looked again and again


as per your view
Do you see something wrong in functions lcd_data and lcd_command ?
In debug menu i got correct 4 bit data from after each shift to the ODR-> port .
I am using external 8Mhz crystal and by using PLL ,achivied 72Mhz to the APB2 bus .

Is strobe function time in between the High to Low pulse may couse error ?

I am struggiling to catchout the error i was doing
 
Hi,

Why don't you use the 8 bit mode? It's much easier to understand and thus better to start with.

Others already tried to explain that you need to start with 4 bit commands.
But your lcd_cmd alway sends 2 x 4 bits instead of 1 x 4 bits.
Your lcd_cmd is not suitable for the first 4 commands where the lcdController still is in 8 bit mode.
--> see the 4 bits mode flowchart in the document you refer to.

"2 x 4 bits mode" clearly starts after the 0x3, 0x3, 0x3, 0x2 (high nibble each) sequence.

You need two different functions, like:
* lcd_cmd8 ... called with 0x30, 0x30, 0x30, 0x20 in sequence
* lcd_cmd4

Klaus
 
Hello!

By the by the project is not worked yet

Not sure if this was a reply to my question. Which project?
LCD or LED blinking?
Could you reply _clearly_ to the questions?
-> Does your earlier led blinker work, yes or no?

You should not do a post containing only "Thank you" and nothing else..

Exactly. And even more. The purpose of this kind of discussion is to
also help other. Otherwise we will endless reply to LCD not working
posts. So what you could consider replying is:

I found what's wrong. Bit xx of register yy wasn't set. I corrected
with the following instruction [some code] and now the LED is blinking.
Thanks for your help.

By the way; what does the LCD do when you turn the contrast potentiometer?
-> If it's not tuned, it will not display anything even if the init code is right.

But I have learned much more from experts
whats wrong ?

I'm not an expert, but you haven't learned enough:

- You haven't commented the code or written self-explanatory code as adviced earlier

Without looking at the documentation, can you tell me what (for instance)
LCD_cmd(0x30); does? No? Me neither.

- Commenting the code is one method. Self-commented code is better.

Example:
Instead of: lcd_cmd(0x28); // Function set (4-bit interface, 2 lines, 5*7Pixels)
LCD_DS.png

Why not
lcd_cmd(LCD_4BITS | LCD_2LINES | LCD_5X8); // You don't need comments here, they are in the code.

Of course you have to #define these codes.

lcd_cmd(0x28);
HAL_Delay(20);
lcd_cmd(0x28); // Function set (4-bit interface, 2 lines, 5*7Pixels)
lcd_cmd(0x28); // Function set (4-bit interface, 2 lines, 5*7Pixels)

Either you are using a very old LCD, almost deaf, so that you have to tell it 3 times
the same thing, or there is an issue. Do you have a technical reason for sending 3 times the same code?

Now some more advice: You want help? Then help us by applying our advices. If you don't,
you may consider using an Arduino with its predefined libraries.

Best regards,

Dora.
 
Hello!



Not sure if this was a reply to my question. Which project?
LCD or LED blinking?
Could you reply _clearly_ to the questions?
-> Does your earlier led blinker work, yes or no?

Sir LED Blinking is working I updated the thread as you mentioned at that time sorry ,I didnt mentioned here
Link
Exactly. And even more. The purpose of this kind of discussion is to
also help other. Otherwise we will endless reply to LCD not working
posts. So what you could consider replying is:

I found what's wrong. Bit xx of register yy wasn't set. I corrected
with the following instruction [some code] and now the LED is blinking.
Thanks for your help.

By the way; what does the LCD do when you turn the contrast potentiometer?
-> If it's not tuned, it will not display anything even if the init code is right.

Sir , I looked it int proteus , tried by connecting VEE also ,its because of previous projects worked fine without VEE .
I tried in real hardware also but nothing displaying .

According to valuble forum memberes , I triyed a few of code used as initilization nothing worked ,

I'm not an expert, but you haven't learned enough:

- You haven't commented the code or written self-explanatory code as adviced earlier

Without looking at the documentation, can you tell me what (for instance)
LCD_cmd(0x30); does? No? Me neither.

- Commenting the code is one method. Self-commented code is better.

Example:
Instead of: lcd_cmd(0x28); // Function set (4-bit interface, 2 lines, 5*7Pixels)
View attachment 185262
Why not
lcd_cmd(LCD_4BITS | LCD_2LINES | LCD_5X8); // You don't need comments here, they are in the code.

Of course you have to #define these codes.



Either you are using a very old LCD, almost deaf, so that you have to tell it 3 times
the same thing, or there is an issue. Do you have a technical reason for sending 3 times the same code?

Now some more advice: You want help? Then help us by applying our advices. If you don't,
you may consider using an Arduino with its predefined libraries.

Best regards,

Dora.

Sir
I will defanitly do comment out the code . will be post soon
 

LaTeX Commands Quick-Menu:

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top