2023-08-07 11:08 AM - edited 2023-08-07 11:13 AM
I don't understand how to use these two display modes:
Read Busy Flag and Address Counter
Read Data from RAM
Datasheet LCD2004A
I can describe how writing to DDRAM works.
First, I put the cursor on the display where I want to write the character:
LCD_SendCommand(0x02); //Return Cursor Home
And in this place I write a symbol:
LCD_SendData('F');
And I don’t understand what it does and what principle of operation for these two modes.
Read Busy Flag and Address Counter
Read Data from RAM
I think if you tell me the algorithm of work, then I can write the code itself.
On the Internet, I could not find a description that I would understand.
Solved! Go to Solution.
2023-08-08 10:32 AM - edited 2023-08-08 10:51 AM
Hello
yes you probably must also write read address.
But you must also add this
EN(1);
after setting RS and RW to enable display to write value to bus.
Then after reading the value set En to zero, just like in your write command or data- functions. Check display controller manual to find out correct signaling for read operation (page 8).
BR J.T
2023-08-07 12:00 PM
The display appears to have a controller similar to the classic HD44780. The HD44780 documentation states, "When the busy flag is 1, the HD44780U is in the internal operation mode, and the next instruction will not
be accepted. When RS = 0 and R/W = 1 (Table 1), the busy flag is output to DB7. The next instruction
must be written after ensuring that the busy flag is 0."
After initialization of the display, you could check the busy flag after sending a command to make sure the controller is ready to accept data.
Often, people just ensure that there are appropriate delays between subsequent commands / sending data, like the flowchart in your data sheet shows. Then you may not need to read from the display at all.
2023-08-07 12:05 PM
Hello
When you write data or command to display, display R/W pin must be low which is write mode.
If you want to read, you must somehow set R/W pin high during read operation. Check your connections where the R/W pin is connected, and try to figure out how it happens.
Then you can perform read operation, RS pin high reads data from display ram and RS pin low reads busy flag and address counter.
If you need further advice, please share your connection diagram how display is connected to MCU and maybe also code for writing to LCD.
Br J.T
2023-08-07 01:14 PM - edited 2023-08-07 02:32 PM
//DB0->GPIOE0
//DB1->GPIOE1
//DB2->GPIOE2
//DB3->GPIOE3
//DB4->GPIOE4
//DB5->GPIOE5
//DB6->GPIOE6
//DB7->GPIOE7
//RS->GPIOC13
//RW->GPIOC14
//EN->GPIOC15
#define DB0(a) GPIOE->ODR = (GPIOE->ODR & (~(1 << GPIO_ODR_OD0_Pos))) | (a << GPIO_ODR_OD0_Pos)
#define DB1(a) GPIOE->ODR = (GPIOE->ODR & (~(1 << GPIO_ODR_OD1_Pos))) | (a << GPIO_ODR_OD1_Pos)
#define DB2(a) GPIOE->ODR = (GPIOE->ODR & (~(1 << GPIO_ODR_OD2_Pos))) | (a << GPIO_ODR_OD2_Pos)
#define DB3(a) GPIOE->ODR = (GPIOE->ODR & (~(1 << GPIO_ODR_OD3_Pos))) | (a << GPIO_ODR_OD3_Pos)
#define DB4(a) GPIOE->ODR = (GPIOE->ODR & (~(1 << GPIO_ODR_OD4_Pos))) | (a << GPIO_ODR_OD4_Pos)
#define DB5(a) GPIOE->ODR = (GPIOE->ODR & (~(1 << GPIO_ODR_OD5_Pos))) | (a << GPIO_ODR_OD5_Pos)
#define DB6(a) GPIOE->ODR = (GPIOE->ODR & (~(1 << GPIO_ODR_OD6_Pos))) | (a << GPIO_ODR_OD6_Pos)
#define DB7(a) GPIOE->ODR = (GPIOE->ODR & (~(1 << GPIO_ODR_OD7_Pos))) | (a << GPIO_ODR_OD7_Pos)
#define RS(a) GPIOC->ODR = (GPIOC->ODR & (~(1 << GPIO_ODR_OD13_Pos))) | (a << GPIO_ODR_OD13_Pos)
#define RW(a) GPIOC->ODR = (GPIOC->ODR & (~(1 << GPIO_ODR_OD14_Pos))) | (a << GPIO_ODR_OD14_Pos)
#define EN(a) GPIOC->ODR = (GPIOC->ODR & (~(1 << GPIO_ODR_OD15_Pos))) | (a << GPIO_ODR_OD15_Pos)
void LCD_Set_Data(uint8_t data)
{
if(data&0x1<<0){DB0(1);} else{DB0(0);}
if(data&0x1<<1){DB1(1);} else{DB1(0);}
if(data&0x1<<2){DB2(1);} else{DB2(0);}
if(data&0x1<<3){DB3(1);} else{DB3(0);}
if(data&0x1<<4){DB4(1);} else{DB4(0);}
if(data&0x1<<5){DB5(1);} else{DB5(0);}
if(data&0x1<<6){DB6(1);} else{DB6(0);}
if(data&0x1<<7){DB7(1);} else{DB7(0);}
}
void LCD_SendCommand(uint8_t data)
{
RS(0);
LCD_Set_Data(data);
EN(1);
HAL_Delay(10);
EN(0);
}
void LCD_SendData(uint8_t data)
{
RS(1);
LCD_Set_Data(data);
EN(1);
HAL_Delay(10);
EN(0);
}
void LCD_ini()
{
HAL_Delay(10);
LCD_SendCommand(0x30);
HAL_Delay(10);
LCD_SendCommand(0x30);
HAL_Delay(10);
LCD_SendCommand(0x30);
HAL_Delay(10);
LCD_SendCommand(0x38); //8 bit, 4 Lines, 5x8 dots
HAL_Delay(10);
LCD_SendCommand(0xF); //Display On, Cursor On, Blinking Cursor On
HAL_Delay(10);
LCD_SendCommand(0x1); //Clear Display
HAL_Delay(10);
LCD_SendCommand(0x6); //Cursor Direction (Incremental, Decremental), SHIFT
HAL_Delay(10);
LCD_SendCommand(0x2); //Return Cursor Home
HAL_Delay(10);
}
int main(void)
{
LCD_ini();
}
RS(a), RW(a), EN(a) are activated and deactivated as follows
EN(1)
EN(0)
Send any command LCD_SendCommand(0x30);
The RS bit in LCD_SendCommand is already set to 0.
As in the LCD_SendData function, the RS bit is set to 1.
-------------------------------------------------------------------
How the bits should be set when reading, is indicated on the diagram. I understand this.
I don't understand how it's done. What is it for?
I have to specify the address on the display where the data will be read from? And data will be read from this address?
Will the display output voltage to the pins with the character code specified at this address?
2023-08-07 04:34 PM - edited 2023-08-07 04:46 PM
I have to do it:
RW(1);
RS(1);
LCD_SendData(0x8A);
But what does it give me? I don't understand.
Where is the data being read from?
And where is the read information now?)
The display pins now contain the latest information written to the display.
I don't understand how to use read information from RAM.
2023-08-07 07:36 PM
Interesting, I have a project that uses a color display (ILI9341 controller) of 320x240 pixels, and I use the reading function to print the display screen (320x240x3 bytes - RGB565). Since there are many pixels and the memory of the MCU is limited, it is easier to read the display.
But I believe that the display of this type of HD44780 controller is so simple that it doesn't seem very useful to read the display. Even most projects with this type of display even leave the Read/Write pin always configured via hardware to operate in writing mode. What is the intent of reading the display? :thinking_face:
2023-08-07 09:57 PM
>What is the intent of reading the display?
I just want to understand how it's done. Intention - learning)
2023-08-08 08:41 AM
Hello
Learning things is allways good.
To perfrom read operation from display, you must configurate your datalines to input (use GPIOE->MODER mode register and clear relevant bits to zero) and then after reading, configurate datalines back to output by setting the same bits.
For reading the input states, use GPIOE->IDR register and read every bit and place values to variable.
Here you can see better explanation about reading GPIO pin states
https://controllerstech.com/stm32-gpio-input-configuration/
And then your controller reference manual gives exact information about registers.
BR J.T
2023-08-08 09:19 AM
Yes, you'd need to reverse the output / input sense of the GPIO pins at the peripheral too.
Generally you don't need to read the content of the screen, you can hold a copy host side.
Why would you want to read? Generally this facilitates an ability to read and modify content, say scroll a line of text, horizontally / vertically or plot individual pixels, or change a character when they are "block graphics". Think Teletext where 64 characters described six pixels in a 2x3 array. Check the font tables for the display in question. In the day of 8-bit micro-controllers you might not want to carry a local memory copy about, these days it's probably faster and more practical to hold a copy, and repaint the entire line/screen buffer.
2023-08-08 10:12 AM - edited 2023-08-08 10:15 AM
Yes, thank you, something already happened.
The display began to give out up to 5 volts to its outputs.
As I expected it to be.
But unfortunately all the display pins from DB0 to DB7 output a logical one.
Should there be a ASCII character code on the display pins?
int main(void)
{
LCD_ini(); //Display initialization
uint8_t str[]={"Hello World"};
for(uint8_t i=0; str[i]!=0; i++) //Sending "Hello World" to the display
{
LCD_SendData(str[i]);
}
//--------------------------------------------------------------------
GPIOE->MODER=0; //Enable input on port E
RS(1); //Enable RS
RW(1); //Enable RW
}
What else is missing.
//Enabling GPIOE for output at the end of the code, I think I don't need it right now.
I think I need to add to the code what display address I want to read.
But I can't do it.