Programming LCD to 8051

Discussion in 'Embedded Systems and Microcontrollers' started by Parth786, Jan 19, 2018.

  1. Parth786

    Thread Starter Active Member

    Jun 19, 2017
    642
    45
    The 16×2 LCD has command register is use to hold the commands. The 16×2 LCD module has a set of commands each meant for doing a particular job with the display.

    http://pdf1.alldatasheet.com/datasheet-pdf/view/127934/ETC1/JHD162A.html

    Initializing LCD:
    Basic command to initialize LCD to the 8051

    The common steps needs for initializing the LCD display
    • Send 38H to the 8 bit data line for initialization
    • Send 0FH for making LCD ON, cursor ON and cursor blinking ON.
    • Send 06H for incrementing cursor position.
    • Send 01H for clearing the display and return the cursor.
    Code (C):
    1. void LCD_initializing(void)
    2. {
    3.     LCD_Command(0x38);
    4.     Delay(20);
    5.     LCD_Command(0x0f);
    6.     Delay(20);
    7.     LCD_Command(0x01);
    8.     Delay(20);
    9.     LCD_Command(0x81);
    10.     Delay(20);
    11. }
    I don't understand two things. Why do we need to give delay between two commands?. How much delay need to give ?
     
  2. be80be

    AAC Fanatic!

    Jul 5, 2008
    1,898
    394
    Last edited: Jan 19, 2018
    Parth786 likes this.
  3. Parth786

    Thread Starter Active Member

    Jun 19, 2017
    642
    45
    Sorry but I am not getting exact time in datasheet there are different time values I think minimum is 20 ms in page number 3 and there is not brief explanation for delay. I want to understand why we give delay between two commands.
     
  4. Raymond Genovese

    Well-Known Member

    Mar 5, 2016
    1,643
    990
    When you are sending commands to the LCD, you are actually sending commands to another microprocessor that is controlling the LCD.

    These commands take time to execute. For example,"Send 01H for clearing the display and return the cursor."

    While the LCD controller is executing a command like that, you (the 8051) has to wait or subsequent commands will not be accepted and executed by the LCD controller.

    I don't know from memory about the JHD162A but it probably uses some variant of the HD44780. A more thorough data sheet on the controller itself will typically provide minimum wait times for various commands. I think that you are seeing those minimum times represented in the software fragments/examples.

    Take a look at table 6 in this PDF for the HD4478 as an example.

    Make sense?
     
    Last edited: Jan 19, 2018
    Brian Griffin likes this.
  5. be80be

    AAC Fanatic!

    Jul 5, 2008
    1,898
    394
    It is like the HD44780
    The first link i posted has code for it and list the time needed.
    Code (Text):
    1.  
    2. Example
    3. #include <reg51.h>
    4. #include <intrins.h>
    5. LCD 的
    6. 21*/
    7. RS
    8. sbit rw=0xa1;
    9. /*P2.1 LCD 的R/W 22*/
    10. LCD 的
    11. 25*/
    12. sbit cs=0xa4;
    13. /*P2.4
    14. E
    15. sfr lcdbus=0x80;
    16. /*p0LCD 数据 D0=P0.0*/
    17. unsigned int sys10mscounter;
    18. unsigned char syslimitcounter;
    19. char path1[8]={0x00,0x1f,0x00,0x1f,0x00,0x1f,0x00,0x1f};/*自定义符号
    20. sbit dc=0xa0;
    21. /*P2.0
    22. char path2[8]={0x1f,0x00,0x1f,0x00,0x1f,0x00,0x1f,0x00};/*自定义符号
    23. char pats1[8]={0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15};/*自定义符号
    24. char pats2[8]={0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a};/*自定义符号
    25. 横1*/
    26. 2*/
    27. 竖1*/
    28. 2*/
    29. void soft_nop(){}
    30. void soft_10ms()/***********12MHZ 提供10MS 软件延时************/
    31. {
    32. register int i;
    33. for(i=0;i<711;i++);
    34. }
    35. void soft_20ms()/***********12MHZ 提供20MS 软件延时************/
    36. {
    37. soft_10ms();
    38. soft_10ms();
    39. }
    40. void hard_10ms(unsigned int delaytime) /*基于10MS 的硬件延时*/
    41. {
    42. sys10mscounter=delaytime;
    43. while(sys10mscounter);
    44. }
    45. unsigned char data lcdcounter;
    46. bit lcdusing1,lcdusing2;
    47. bit lcd_checkbusy()/*检查LCD 忙*/
    48. {
    49. register lcdstate;
    50. dc=0;
    51. /*dc=1为数据,=0 为命令.*/
    52. rw=1;
    53. /*rw=1为读,=0 为写.*/
    54. cs=1;
    55. /*cs=1选通.*/
    56. soft_nop();
    57. lcdstate=lcdbus;
    58. cs=0;
    59. return((bit)(lcdstate&0x80));
    60. }
    61. void lcd_wrcmd(unsigned char lcdcmd) /*写LCD 命令*/
    62. {
    63. lcdusing1=1;
    64. while(lcd_checkbusy());
    65. lcdbus=lcdcmd;
    66. dc=0;
    67. /*dc=1为数据,=0 为命令.*/
    68. rw=0;
    69. cs=1;
    70. soft_nop();
    71. /*rw=1为读,=0 为写.*/
    72. /*cs=1选通.*/
    73. cs=0;
    74. lcdbus=0xff;
    75. lcdusing1=0;
    76. }
    77. void lcd_moveto(char position) /*移动光标到指定位.0-79*/
    78. { register cmd=0x80;
    79. lcdcounter=position;
    80. if (position > 59)
    81. position += 0x18;
    82. else
    83. {
    84. if (position > 39)position -= 0x14;
    85. else
    86. {
    87. if (position > 19)position += 0x2c;
    88. }
    89. }
    90. cmd=cmd|position;
    91. lcd_wrcmd(cmd); } void lcd_wrdata(char lcddata) /*在当前显示位置显示数据*/ { char i;
    92. lcdusing2=1;
    93. while(lcd_checkbusy());
    94. if(lcdcounter==20){
    95. lcd_moveto(20);
    96. while(lcd_checkbusy());
    97. }
    98. if(lcdcounter==40){
    99. lcd_moveto(40);
    100. while(lcd_checkbusy());
    101. }
    102. if(lcdcounter==60){
    103. lcd_moveto(60);
    104. while(lcd_checkbusy());
    105. }
    106. if(lcdcounter==80){
    107. lcd_moveto(0);
    108. while(lcd_checkbusy());
    109. lcdcounter=0;
    110. } /*为通用而如此*/
    111. lcdcounter++;
    112. lcdbus=lcddata;
    113. dc=1; /*dc=1为数据,=0 为命令.*/
    114. rw=0; /*rw=1为读,=0 为写.*/
    115. cs=1; /*cs=1选通.*/
    116. soft_nop();
    117. cs=0;
    118. lcdbus=0xff;
    119. lcdusing2=0; } void lcd_string(char *strpoint) /*在当前显示位置显示LCD 字符串*/
    120. { register i=0;
    121. while(strpoint[i]!=0){
    122. cd_wrdata(strpoint[i]);
    123. i++;
    124. }
    125. } void lcd_init()/*初始化*/
    126. {
    127. lcd_wrcmd(0x38);
    128. lcd_wrcmd(0x0c);
    129. lcd_wrcmd(0x06);
    130. lcd_wrcmd(0x01);
    131. lcdcounter=0;
    132. /*设置8 位格式,2 行,5*7*/
    133. /*整体显示,关光标,不闪烁*/
    134. /*设定输入方式,增量不移位*/
    135. /*清除显示*/
    136. }
    137. void lcd_cls()/*清除显示*/ { lcd_wrcmd(0x01);
    138. lcdcounter=0; } void timer0(void) interrupt 1 /*T0 中断*/ { TH0=0xd8; /*12M,10ms*/
    139. TL0=0xf6;
    140. TR0=1;
    141. if(sys10mscounter!=0)sys10mscounter--; /*定时器10ms*/
    142. if(syslimitcounter!=0)syslimitcounter--; /*定时器10ms*/
    143. }
    144. main()
    145. {
    146. unsigned char j;
    147. IE=0;P0=0xff;P1=0xff;P2=0xff;P3=0xff; /*初始化T*/
    148. lcd_init();soft_20ms();
    149. TMOD=0x51;
    150. TH0=0xd8; /*12M,10ms*/
    151. TL0=0xf6;
    152. TR0=1;ET0=1;EA=1;
    153. while(1)
    154. {
    155. /*全黑横一横二竖一竖二U Q ABCD... */
    156. lcd_init(); /*全黑*/
    157. for(j=0;j<80;j++){lcd_wrdata(0xff);}
    158. hard_10ms(50);
    159. lcd_init(); /*横一可参考自行设计符号*/
    160. lcd_wrcmd(0x40);
    161. for(j=0;j<8;j++)lcd_wrdata(path1[j]);
    162. for(j=0;j<100;j++)lcd_wrdata(0);
    163. hard_10ms(50);
    164. lcd_init(); /*横二*/
    165. lcd_wrcmd(0x40);
    166. for(j=0;j<8;j++)lcd_wrdata(path2[j]);
    167. for(j=0;j<100;j++)lcd_wrdata(0);
    168. hard_10ms(50);
    169. lcd_init(); /*竖一*/
    170. lcd_wrcmd(0x40);
    171. for(j=0;j<8;j++)lcd_wrdata(pats1[j]);
    172. for(j=0;j<100;j++)lcd_wrdata(0);
    173. hard_10ms(50);
    174. lcd_init(); /*竖二*/
    175. lcd_wrcmd(0x40);
    176. for(j=0;j<8;j++)lcd_wrdata(pats2[j]);
    177. for(j=0;j<100;j++)lcd_wrdata(0);
    178. hard_10ms(50);
    179. lcd_init();
    180. lcd_string("UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
    181. UUUUUUUUUUUUUUUUUUUUUUUU
    182. UUUUU"); hard_10ms(50); lcd_init();
    183. lcd_string("QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
    184. QQQQQQQQQQQQQQQQQQQQQQQQ
    185. QQQQQ"); hard_10ms(50); lcd_init();
    186. lcd_string("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwx
    187. yz0123456789+-!
    188. #$%&?"); hard_10ms(50); }
    189. }
    190.  
    Think I got it all
     
    Last edited: Jan 19, 2018
  6. be80be

    AAC Fanatic!

    Jul 5, 2008
    1,898
    394
    I did it from scratch for a 16f505 lot's of fun there I just used the datasheet took me week to get it right but I was learning xc8.
    And mplab-x
     
  7. Parth786

    Thread Starter Active Member

    Jun 19, 2017
    642
    45
    these are basics steps
    • STEP1: Initialization of LCD.
    • STEP2: Sending command to LCD.
    • STEP3: Writing the data to LCD.
    Code (C):
    1.  
    2. /* Function to send command instruction to LCD */
    3. void LCD_Command(unsigned char cmd)
    4. {
    5.     port = cmd;
    6.     RS = 0;
    7.     RW = 0;
    8.     EN = 1;
    9.     Delay(2);
    10.     EN = 0;
    11. }
    12.  
    13. /*Function to send display dato LCD */
    14. void LCD_Data(unsigned char Data)
    15. {
    16.     port = Data;
    17.     RS = 1;
    18.     RW = 0;
    19.     EN = 1;
    20.     Delay(2);
    21.     EN = 0;
    22. }
    23.  
    24. /* function for delay */
    25. void Delay(unsigned int wait)
    26.     {
    27.             unsigned i , j ;
    28.             for( i = 0; i < wait; i++ )
    29.             for( j = 0; j < 1200; j++);
    30.     }
    31.  
    32. /* Function to prepare the LCD */
    33. void LCD_init()
    34. {
    35.     LCD_Command(0x38);
    36.     Delay(20);
    37.     LCD_Command(0x0f);
    38.     Delay(20);
    39.     LCD_Command(0x01);
    40.     Delay(20);
    41.     LCD_Command(0x81);
    42.     Delay(20);
    43. }
    I have still doubt on delay.I am not finding exact reason to use of delay
     
  8. Raymond Genovese

    Well-Known Member

    Mar 5, 2016
    1,643
    990
    Sorry, but I disagree. The data sheet that you linked to is the same document as the datasheet linked to by the TS. I am not referring to the AC electrical characteristics (Table 12 in either of the two links).

    I am referring to the controller's instruction execution times, again, as given in table 6 of the HD4478 document that I linked.

    Maybe, I missed it but I do not see any controller instruction execution times in the document that the TS linked or that you linked.

    That was my point and integral to the explanation.
     
    Brian Griffin likes this.
  9. be80be

    AAC Fanatic!

    Jul 5, 2008
    1,898
    394
    Nope you talking about the same thing I posted pic of the timing
    but i posted the wrong one i fixed it
    Raymond Genovese thanks for pointing that out.
    JHD162A data sheet just a little different
    But the HD4478 will work with it from what google said LOL
    Here about the same.
    The data sheet for HD4478 is easier to read
    Screenshot from 2018-01-19 15-10-18.png
     
    Last edited: Jan 19, 2018
  10. Parth786

    Thread Starter Active Member

    Jun 19, 2017
    642
    45
    I am struggling in embedded program. I can write simple array string program but I am having problem in embedded program with basics
    Code (C):
    1. #include<stdio.h>
    2. int main (void)
    3. {
    4.     int i;
    5.     char array[15] =  {"Hello Friends"};
    6.     for(i = 0; i < 15;  i++)
    7.     {
    8.          printf("print array element : %c \n", array[i]);
    9.     }
    10.     return 0;
    11.  
    12. }
    I get following output of this program
    print array element : H
    print array element : e
    print array element : l
    print array element : l
    print array element : o
    print array element :
    print array element : F
    print array element : r
    print array element : i
    print array element : e
    print array element : n
    print array element : d
    print array element : s
    print array element :
    print array element :

    I want to use same basic knowledge in embedded c programming
    Code (C):
    1. #include<reg51.h>
    2.  
    3. #define port P1           /* Data pins connected to port P1 */
    4.  
    5. sbit RS = P2^0;           /* RS pin connected to pin 0 of port P2 */
    6. sbit RW = P2^1;           /* RW pin connected to pin 1 of port P2 */
    7. sbit EN = P2^2;           /* EN pin connected to pin 2 of port P2 */
    8.  
    9. /* Function to send command to LCD */
    10. void LCD_Command(unsigned char cmd)
    11. {
    12.     port = cmd;
    13.     RS = 0;
    14.     RW = 0;
    15.     EN = 1;
    16.     Delay(2);
    17.     EN = 0;
    18. }
    19. /*Function to send data to LCD */
    20. void LCD_Data(unsigned char Data)
    21. {
    22.     port = Data;
    23.     RS = 1;
    24.     RW = 0;
    25.     EN = 1;
    26.     Delay(2);
    27.     EN = 0;
    28. }
    29.  
    30. /* function for delay */
    31.     void Delay(unsigned int wait)
    32. {
    33.     unsigned i,j ;
    34.     for(i = 0; i < wait; i++)
    35.     for(j = 0; j < 1200; j++);
    36. }
    37.  
    38. /* Function to prepare the LCD */
    39. void LCD_init()
    40. {
    41.     LCD_Command(0x38);
    42.     Delay(20);
    43.     LCD_Command(0x0f);
    44.     Delay(20);
    45.     LCD_Command(0x01);
    46.     Delay(20);
    47.     LCD_Command(0x81);
    48.     Delay(20);
    49. }
    50.  
    51. void string (void)
    52. {
    53.      unsigned int i=0;
    54.  
    55.     unsigned char string[15]= "Hello Friend's";
    56.  
    57.      for(i=0; i<15; i++)
    58.     {
    59.  
    60.     }
    61.  
    62. }
    63. void main(void)
    64. {
    65.   LCD_init();
    66.     while (1)
    67.     {
    68.           string ();
    69.     }
    70. }
    Have you noticed that in my embedded program I am facing problem in string function. I don't understand how to make this function for proper working. so please help me
     
    Last edited: Jan 20, 2018
  11. Raymond Genovese

    Well-Known Member

    Mar 5, 2016
    1,643
    990
    @Parth786 could you at least acknowledge the responses referencing your questions "I don't understand two things. Why do we need to give delay between two commands?. How much delay need to give ?" in your original post?

    What I am noticing is that you seem to be jumping into the next thing without so much as a peep with regard to your question and the attempts at answering your question. Not sure, but maybe that basic way of responding (or skipping the responding) could be adding to you "struggles" - yes?
     
  12. Parth786

    Thread Starter Active Member

    Jun 19, 2017
    642
    45
    @Raymond Genovese
    When a first topic completed then I started another I wanted to write a program for lcd from the beginning.But I had doubt on delay.I got the answer in your post #4 that command need some time to execute. so I didn't go in too deep and I started new question

    Post #7 and Post #10 are more important for me then original question. I think these can be clear more basics. I have mention both program c and embedded c and I was waiting for further response
     
  13. Raymond Genovese

    Well-Known Member

    Mar 5, 2016
    1,643
    990
    OK fair enough and I am glad that you acknowledged the efforts of folks to answer the question that you originally asked.

    Your post #7 still asks about the delays, so that is still confusing as to whether you are understanding that your last line in post #7 is
    "I have still doubt on delay.I am not finding exact reason to use of delay"

    I don't understand what you are actually asking about in post #10 - should it be in another thread? Could you be a little clearer about your question in post #10? Do you not want to send a LF or CR/LF after every character printed?

    If that is your question, then take a look at your printf statement and remove the '/n' in:
    printf("print array element : %c \n", array);
    and see what the output looks like.
     
  14. Parth786

    Thread Starter Active Member

    Jun 19, 2017
    642
    45
    Actually I don't understand when to start a new thread. My thread has been locked by moderator two times and the reason was same topics
    So there is fear, this shouldn't happen again. That's why I continued here only
     
    GopherT likes this.
Loading...