Go Down

Topic: How does arduino control a 16x2 or 20x 4 LCD display? (Read 1 time) previous topic - next topic

kurtselva

Thanks for the reply guys. Really helped me understand more.

Anyway, I was looking at the Liquidcrystal library code as follows:
Code: [Select]
#ifndef LiquidCrystal_h
#define LiquidCrystal_h

#include <inttypes.h>
#include "Print.h"

// commands
#define LCD_CLEARDISPLAY 0x01
#define LCD_RETURNHOME 0x02
#define LCD_ENTRYMODESET 0x04
#define LCD_DISPLAYCONTROL 0x08
#define LCD_CURSORSHIFT 0x10
#define LCD_FUNCTIONSET 0x20
#define LCD_SETCGRAMADDR 0x40
#define LCD_SETDDRAMADDR 0x80

// flags for display entry mode
#define LCD_ENTRYRIGHT 0x00
#define LCD_ENTRYLEFT 0x02
#define LCD_ENTRYSHIFTINCREMENT 0x01
#define LCD_ENTRYSHIFTDECREMENT 0x00

// flags for display on/off control
#define LCD_DISPLAYON 0x04
#define LCD_DISPLAYOFF 0x00
#define LCD_CURSORON 0x02
#define LCD_CURSOROFF 0x00
#define LCD_BLINKON 0x01
#define LCD_BLINKOFF 0x00

// flags for display/cursor shift
#define LCD_DISPLAYMOVE 0x08
#define LCD_CURSORMOVE 0x00
#define LCD_MOVERIGHT 0x04
#define LCD_MOVELEFT 0x00

// flags for function set
#define LCD_8BITMODE 0x10
#define LCD_4BITMODE 0x00
#define LCD_2LINE 0x08
#define LCD_1LINE 0x00
#define LCD_5x10DOTS 0x04
#define LCD_5x8DOTS 0x00

class LiquidCrystal : public Print {
public:
  LiquidCrystal(uint8_t rs, uint8_t enable,
                uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
                uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
  LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable,
                uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
                uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
  LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable,
                uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3);
  LiquidCrystal(uint8_t rs, uint8_t enable,
                uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3);

  void init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable,
            uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
            uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
   
  void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS);

  void clear();
  void home();

  void noDisplay();
  void display();
  void noBlink();
  void blink();
  void noCursor();
  void cursor();
  void scrollDisplayLeft();
  void scrollDisplayRight();
  void leftToRight();
  void rightToLeft();
  void autoscroll();
  void noAutoscroll();

  void createChar(uint8_t, uint8_t[]);
  void setCursor(uint8_t, uint8_t);
  virtual void write(uint8_t);
  void command(uint8_t);
private:
  void send(uint8_t, uint8_t);
  void write4bits(uint8_t);
  void write8bits(uint8_t);
  void pulseEnable();

  uint8_t _rs_pin; // LOW: command.  HIGH: character.
  uint8_t _rw_pin; // LOW: write to LCD.  HIGH: read from LCD.
  uint8_t _enable_pin; // activated by a HIGH pulse.
  uint8_t _data_pins[8];

  uint8_t _displayfunction;
  uint8_t _displaycontrol;
  uint8_t _displaymode;

  uint8_t _initialized;

  uint8_t _numlines,_currline;
};

#endif


May I know what do all the "0 x 01", "0 x 02" etc etc mean?
And what does the "uint8_t rs" etc etc mean?

floresta

#6
Feb 25, 2013, 07:16 pm Last Edit: Feb 25, 2013, 07:33 pm by floresta Reason: 1
Quote
May I know what do all the "0 x 01", "0 x 02" etc etc mean?

Those are sometimes referred to as 'magic numbers' because they appear to only have some mysterious relationship with the real world.

To understand them you have to convert them to binary and then you will have a better chance of finding out how they relate to the information in the datasheet.

Let's start with this batch where I have added the binary values as comments:

Code: [Select]
// commands
#define LCD_CLEARDISPLAY 0x01   // 0 0 0 0 0 0 0 1
#define LCD_RETURNHOME 0x02     // 0 0 0 0 0 0 1 0
#define LCD_ENTRYMODESET 0x04   // 0 0 0 0 0 1 0 0
#define LCD_DISPLAYCONTROL 0x08 // 0 0 0 0 1 0 0 0
#define LCD_CURSORSHIFT 0x10    // 0 0 0 1 0 0 0 0
#define LCD_FUNCTIONSET 0x20    // 0 0 1 0 0 0 0 0
#define LCD_SETCGRAMADDR 0x40   // 0 1 0 0 0 0 0 0
#define LCD_SETDDRAMADDR 0x80   // 1 0 0 0 0 0 0 0


Now compare this with the command set (Table 6) in the datasheet and you will see that each of the commands in that table starts out (reading left to right) with a bunch of 0s to the left of the first '1' and the first '1' is associated with a different data byte for each command.
Here is a list of those commands with the location of the leftmost '1' identified.

Clear display ............. DB0
Return home ............... DB1
Entry mode set ............ DB2
Display on/off ............ DB3
Cursor or display shift ... DB4
Function set .............. DB5
Set CGRAM address ......... DB6
Set DDRAM address ......... DB7


Now compare the two lists and you should be able to tell where the 'magic numbers' came from.


Don

kurtselva


Quote
May I know what do all the "0 x 01", "0 x 02" etc etc mean?

Those are sometimes referred to as 'magic numbers' because they appear to only have some mysterious relationship with the real world.

To understand them you have to convert them to binary and then you will have a better chance of finding out how they relate to the information in the datasheet.

Let's start with this batch where I have added the binary values as comments:

Code: [Select]
// commands
#define LCD_CLEARDISPLAY 0x01   // 0 0 0 0 0 0 0 1
#define LCD_RETURNHOME 0x02     // 0 0 0 0 0 0 1 0
#define LCD_ENTRYMODESET 0x04   // 0 0 0 0 0 1 0 0
#define LCD_DISPLAYCONTROL 0x08 // 0 0 0 0 1 0 0 0
#define LCD_CURSORSHIFT 0x10    // 0 0 0 1 0 0 0 0
#define LCD_FUNCTIONSET 0x20    // 0 0 1 0 0 0 0 0
#define LCD_SETCGRAMADDR 0x40   // 0 1 0 0 0 0 0 0
#define LCD_SETDDRAMADDR 0x80   // 1 0 0 0 0 0 0 0


Now compare this with the command set (Table 6) in the datasheet and you will see that each of the commands in that table starts out (reading left to right) with a bunch of 0s to the left of the first '1' and the first '1' is associated with a different data byte for each command.
Here is a list of those commands with the location of the leftmost '1' identified.

Clear display ............. DB0
Return home ............... DB1
Entry mode set ............ DB2
Display on/off ............ DB3
Cursor or display shift ... DB4
Function set .............. DB5
Set CGRAM address ......... DB6
Set DDRAM address ......... DB7


Now compare the two lists and you should be able to tell where the 'magic numbers' came from.


Don



Oooohh now that makes a lot of sense.

But only the last 2 digits ( those 02,01 etc) are the hexadecimal value right? Then what does the 0 x in front signify?

And say I am using 4 bit data transfer mode.. So does that mean the D0-D3 are always low?

kurtselva

Code: [Select]
#ifndef LiquidCrystal_h
#define LiquidCrystal_h

#include <inttypes.h>
#include "Print.h"

class LiquidCrystal : public Print {
public:
  LiquidCrystal(uint8_t rs, uint8_t enable,
                uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
                uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
  LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable,
                uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
                uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
  LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable,
                uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3);
  LiquidCrystal(uint8_t rs, uint8_t enable,
                uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3);

  void init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable,
            uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
            uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
   
  void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS);

  void clear();
  void home();

  void noDisplay();
  void display();
  void noBlink();
  void blink();
  void noCursor();
  void cursor();
  void scrollDisplayLeft();
  void scrollDisplayRight();
  void leftToRight();
  void rightToLeft();
  void autoscroll();
  void noAutoscroll();

  void createChar(uint8_t, uint8_t[]);
  void setCursor(uint8_t, uint8_t);
  virtual void write(uint8_t);
  void command(uint8_t);
private:
  void send(uint8_t, uint8_t);
  void write4bits(uint8_t);
  void write8bits(uint8_t);
  void pulseEnable();

  uint8_t _rs_pin; // LOW: command.  HIGH: character.
  uint8_t _rw_pin; // LOW: write to LCD.  HIGH: read from LCD.
  uint8_t _enable_pin; // activated by a HIGH pulse.
  uint8_t _data_pins[8];

  uint8_t _displayfunction;
  uint8_t _displaycontrol;
  uint8_t _displaymode;

  uint8_t _initialized;

  uint8_t _numlines,_currline;
};

#endif




And would be grateful if someone could explain to me what the remaining codes(as shown above) are doing..

floresta

Quote
But only the last 2 digits ( those 02,01 etc) are the hexadecimal value right? Then what does the 0 x in front signify?

The 0x tells the C compiler which number system you are using.  For example the number 01 represents the same quantity in binary, decimal, and hex but the number 10 is different in all three systems.

Quote
And say I am using 4 bit data transfer mode.. So does that mean the D0-D3 are always low?

They are usually left floating but tying them low isn't a bad idea.  The LCD controller ignores those four bits when it is in the 4-bit mode.

Quote
And would be grateful if someone could explain to me what the remaining codes(as shown above) are doing..

That is precisely the purpose for comments in a program.  Without comments it is difficult for anyone not intimately familiar with the program and/or the device being controlled to figure out what is going on.  This includes the original programmer after the passage of time.

Unfortunately there are only three comments in the code fragment that you have posted.  Those three are intended to remind the programmer what each pin does, which isn't a bad idea except that the third one (about the Enable pin) is incorrect.

I am not a C programmer but it looks to me that the stuff you have quoted in the post just above consists of instructions to the C compiler, not instructions to the LCD controller.

Don

Go Up