Me 8 You 4 ( LCD PIC Interface With C)

Discussion in 'Embedded Systems and Microcontrollers' started by walid el masry, Aug 29, 2009.

  1. walid el masry

    Thread Starter Active Member

    Mar 31, 2009
    132
    0
    i have written C code to interface 16x2 LCD with PIC16f876 using Mikroc compiler and with help of the RICKEY'S WORLD tutorial at

    http://www.8051projects.net/lcd-interfacing/

    which was very helpful and i was successful with 8 bit programing mode and thats is the result

    Code ( (Unknown Language)):
    1.  
    2. [B]/*LCD 8 bit example[/B]
    3. [B]rs => Register Select [Command : Data][/B]
    4. [B]     0 => Command[/B]
    5. [B]     1 => Data[/B]
    6. [B]rw => Read/Write [Write : Read][/B]
    7. [B]     0 => Write[/B]
    8. [B]     1 => Read[/B]
    9. [B]en => Enable signal [High to Low][/B]
    10. [B]*/[/B]
    11. [B]#define LCD_data PORTB[/B]
    12. [B]#define LCD_rs   PORTC.B0[/B]
    13. [B]#define LCD_rw   PORTC.B1[/B]
    14. [B]#define LCD_en   PORTC.B2[/B]
    15. [B]#define LCD_D7   PORTB.B7[/B]
    16. [B]void LCD_busy() {[/B]
    17. [B]  delay_ms(5);//it is very important to return to the manual for it[/B]
    18. [B]}[/B]
    19. [B]void LCD_write_command () {[/B]
    20. [B]  LCD_rs   = 0;        //Selected command register[/B]
    21. [B]  LCD_rw   = 0;        //We are writing in data register[/B]
    22. [B]  LCD_en   = 1;        //Enable H->L[/B]
    23. [B]  LCD_en   = 0;[/B]
    24. [B]  LCD_busy();          //Wait for LCD to process the command[/B]
    25. [B]}[/B]
    26. [B]void LCD_clear_display () {[/B]
    27. [B]  LCD_data = 0x01;     //Clear LCD[/B]
    28. [B]  LCD_write_command();[/B]
    29. [B]}[/B]
    30. [B]void LCD_return_home () {[/B]
    31. [B]  LCD_data = 0x02;     //Return LCD to Home[/B]
    32. [B]  LCD_write_command();[/B]
    33. [B]}[/B]
    34. [B]void LCD_entry_mode_set (unsigned int ID,unsigned int S) {[/B]
    35. [B]  /*[/B]
    36. [B]  ID => [Decrement : Increment][/B]
    37. [B]        0 => Decrement[/B]
    38. [B]        1 => Increment[/B]
    39. [B]  S  => accompanies display shift[/B]
    40. [B]        0 => OFF[/B]
    41. [B]        1 => ON[/B]
    42. [B]  */[/B]
    43. [B]  LCD_data = 0x00;[/B]
    44. [B]  ID = ID << 1;[/B]
    45. [B]  LCD_data = LCD_data + 0x04 + ID + S;[/B]
    46. [B]  LCD_write_command();[/B]
    47. [B]}[/B]
    48. [B]void LCD_display_control (unsigned int D,unsigned int C,unsigned int B) {[/B]
    49. [B]  /*[/B]
    50. [B]  D  => Display ON/OFF[/B]
    51. [B]        0 => OFF[/B]
    52. [B]        1 => ON[/B]
    53. [B]  C  => Cursor ON/OFF[/B]
    54. [B]        0 => OFF[/B]
    55. [B]        1 => ON[/B]
    56. [B]  B  => Blink the character at the cursor position[/B]
    57. [B]        0 => OFF[/B]
    58. [B]        1 => ON[/B]
    59. [B]  */[/B]
    60. [B]  LCD_data = 0x00;[/B]
    61. [B]  C = C << 1;[/B]
    62. [B]  D = D << 2;[/B]
    63. [B]  LCD_data = LCD_data + 0x08 + D + C + B;[/B]
    64. [B]  LCD_write_command();[/B]
    65. [B]}[/B]
    66. [B]void LCD_cursor_display_shift (unsigned int SC,unsigned int RL) {[/B]
    67. [B]  /*[/B]
    68. [B]  Moves the cursor and shifts the display without changing the DDRAM contents[/B]
    69. [B]  SC  => [Cursor : Display][/B]
    70. [B]        0 => Cursor[/B]
    71. [B]        1 => Display[/B]
    72. [B]  RL  => [Left : Right][/B]
    73. [B]        0 => Left[/B]
    74. [B]        1 => Right[/B]
    75. [B]  */[/B]
    76. [B]  LCD_data = 0x00;[/B]
    77. [B]  RL = RL << 2;[/B]
    78. [B]  SC = SC << 3;[/B]
    79. [B]  LCD_data = LCD_data + 0x10 + SC + RL;[/B]
    80. [B]  LCD_write_command();[/B]
    81. [B]}[/B]
    82. [B]void LCD_function_set (unsigned int DL,unsigned int N,unsigned int F) {[/B]
    83. [B]  /*[/B]
    84. [B]  DL  => Data Width [4 bit : 8 bit][/B]
    85. [B]        0 => 4 bit[/B]
    86. [B]        1 => 8 bit[/B]
    87. [B]  N  => Number of lines in display[1 : 2][/B]
    88. [B]        0 => 1 Line[/B]
    89. [B]        1 => 2 Lines[/B]
    90. [B]  F  => Character font[5x7 : 5x10][/B]
    91. [B]        0 => 5x7[/B]
    92. [B]        1 => 5x10[/B]
    93. [B]  */[/B]
    94. [B]  LCD_data = 0x00;[/B]
    95. [B]  F = F << 2;[/B]
    96. [B]  N = N << 3;[/B]
    97. [B]  DL = DL << 4;[/B]
    98. [B]  LCD_data = LCD_data + 0x20 + DL + N + F;[/B]
    99. [B]  LCD_write_command();[/B]
    100. [B]}[/B]
    101. [B]void LCD_cgram_address (unsigned int cgadrs) {[/B]
    102. [B]  /*[/B]
    103. [B]  cgadrs => CGRAM Address Binary 6 bit[/B]
    104. [B]  i didn't use it yet[/B]
    105. [B]  */[/B]
    106. [B]  LCD_data = 0x00;[/B]
    107. [B]  LCD_data = cgadrs;[/B]
    108. [B]  LCD_write_command();[/B]
    109. [B]}[/B]
    110. [B]void LCD_ddram_address (unsigned int ddadrs) {[/B]
    111. [B]  /*[/B]
    112. [B]  ddadrs => DDRAM Address Binary 7 bit[/B]
    113. [B]            Line 1 Column 1[/B]
    114. [B]            Binary Address : 0B10000000[/B]
    115. [B]            HEX Address     : 0X80[/B]
    116.  
    117. [B]            Line 1 Column 16[/B]
    118. [B]            Binary Address : 0B10001111[/B]
    119. [B]            HEX Address     : 0X8F[/B]
    120.  
    121. [B]            Line 2 Column 1[/B]
    122. [B]            Binary Address : 0B11000000[/B]
    123. [B]            HEX Address     : 0XC0[/B]
    124.  
    125. [B]            Line 2 Column 16[/B]
    126. [B]            Binary Address : 0B11001111[/B]
    127. [B]            HEX Address     : 0XCF[/B]
    128. [B]            [][][][][][][][][][][][][][][][][/B]
    129. [B]            [][][][][][][][][][][][][][][][][/B]
    130. [B]                 C1    C2    C3    C4    C5    C6    C7    C8    C9    C10   C11   C12   C13   C14   C15   C16[/B]
    131. [B]            L1 [0X80][0X81][0X82][0X83][0X84][0X85][0X86][0X87][0X88][0X89][0X8A][0X8B][0X8C][0X8D][0X8E][0X8F][/B]
    132. [B]            L2 [0XC0][0XC1][0XC2][0XC3][0XC4][0XC5][0XC6][0XC7][0XC8][0XC9][0XCA][0XCB][0XCC][0XCD][0XCE][0XCF][/B]
    133. [B]  */[/B]
    134. [B]  LCD_data = 0x00;[/B]
    135. [B]  LCD_data = ddadrs;[/B]
    136. [B]  LCD_write_command();[/B]
    137. [B]}[/B]
    138. [B]void LCD_write_data(unsigned int output) {[/B]
    139. [B]  LCD_data = output;     //[/B]
    140. [B]  LCD_rs   = 1;        //Selected data register[/B]
    141. [B]  LCD_rw   = 0;        //We are writing in data register[/B]
    142. [B]  LCD_en   = 1;        //Enable H->L[/B]
    143. [B]  LCD_en   = 0;[/B]
    144. [B]  LCD_busy();[/B]
    145. [B]}[/B]
    146. [B]/*void LCD_write_string(unsigned char output) {[/B]
    147. [B]  LCD_data = output;     //Entry mode, auto increment with no shift[/B]
    148. [B]  LCD_rs   = 1;        //Selected data register[/B]
    149. [B]  LCD_rw   = 0;        //We are writing in data register[/B]
    150. [B]  LCD_en   = 1;        //Enable H->L[/B]
    151. [B]  LCD_en   = 0;[/B]
    152. [B]  LCD_busy();[/B]
    153. [B]}*/[/B]
    154. [B]void LCD_init() {[/B]
    155. [B]  LCD_function_set (1,1,0);//Function set: 2 Line, 8-bit, 5x7 dots[/B]
    156. [B]  LCD_display_control (1,1,1);//Display on, Curson blinking command[/B]
    157. [B]  LCD_clear_display();[/B]
    158. [B]  LCD_entry_mode_set (1,0);//Entry mode, auto increment with no shift[/B]
    159. [B]  LCD_ddram_address(0X80);//Line 1 Column 1[/B]
    160. [B]}[/B]
    161. [B]void main() {[/B]
    162. [B]  TRISB = 0x00;[/B]
    163. [B]  TRISC = 0x00;[/B]
    164. [B]  LCD_init();[/B]
    165. [B]  LCD_ddram_address(0X83);[/B]
    166. [B]  //"All"[/B]
    167. [B]  LCD_write_data(0x41);//'A'[/B]
    168. [B]  LCD_write_data(0x6C);//'l'[/B]
    169. [B]  LCD_write_data(0x6C);//'l'[/B]
    170. [B]  //space[/B]
    171. [B]  LCD_write_data(0x20);//space[/B]
    172. [B]  //"About"[/B]
    173. [B]  LCD_write_data(0x41);//'A'[/B]
    174. [B]  LCD_write_data(0x62);//'b'[/B]
    175. [B]  LCD_write_data(0x6F);//'o'[/B]
    176. [B]  LCD_write_data(0x75);//'u'[/B]
    177. [B]  LCD_write_data(0x74);//'t'[/B]
    178. [B]  LCD_ddram_address(0XC4);[/B]
    179. [B]  //"Circuits"[/B]
    180. [B]  LCD_write_data(0x43);//'C'[/B]
    181. [B]  LCD_write_data(0x69);//'i'[/B]
    182. [B]  LCD_write_data(0x72);//'r'[/B]
    183. [B]  LCD_write_data(0x63);//'c'[/B]
    184. [B]  LCD_write_data(0x75);//'u'[/B]
    185. [B]  LCD_write_data(0x69);//'i'[/B]
    186. [B]  LCD_write_data(0x74);//'t'[/B]
    187. [B]  LCD_write_data(0x73);//'s'[/B]
    188. [B]}[/B]
    189.  
     
    • lcdb.jpg
      lcdb.jpg
      File size:
      174.3 KB
      Views:
      93
    Last edited by a moderator: Aug 29, 2009
  2. walid el masry

    Thread Starter Active Member

    Mar 31, 2009
    132
    0
    but i tried very well in 4 bit mode but the is some thing wrong as i checked it many times
    here is the code

    Code ( (Unknown Language)):
    1.  
    2. /*LCD 4 bit example
    3.   rs => Register Select [Command : Data]
    4.         0 => Command
    5.         1 => Data
    6.   rw => Read/Write [Write : Read]
    7.         0 => Write
    8.         1 => Read
    9.   en => Enable signal [High to Low]
    10. */
    11. #define LCD_data PORTB
    12. #define LCD_rs   PORTB.B2
    13. #define LCD_en   PORTB.B3
    14. //************************************
    15.  
    16. //************************************
    17. void LCD_reset () {
    18.      LCD_data = 0XFC;
    19.      delay_ms(20);
    20.      LCD_data = 0X34;//Data = 34H, EN = 1, RS = 0, First Init
    21.      LCD_data = 0X30;//Data = 30H, EN = 0, RS = 0
    22.      delay_ms(10);
    23.      LCD_data = 0X34;//Data = 34H, EN = 1, RS = 0, Second Init
    24.      LCD_data = 0X30;//Data = 30H, EN = 0, RS = 0
    25.      delay_ms(1);
    26.      LCD_data = 0X34;//Data = 34H, EN = 1, RS = 0, Third Init
    27.      LCD_data = 0X30;//Data = 30H, EN = 0, RS = 0
    28.      delay_ms(1);
    29.      LCD_data = 0X44;//Data = 44H, EN = 1, RS = 0, Select Data width (4bit)
    30.      LCD_data = 0X40;//Data = 40H, EN = 0, RS = 0
    31.      delay_ms(1);
    32. }
    33. void LCD_write_command () {
    34.      unsigned int temp;
    35.      temp = LCD_data;
    36.      LCD_data = temp & 0XF0;
    37.      LCD_rs   = 0;        //Selected command register
    38.      LCD_en   = 1;        //Enable H->L
    39.      LCD_en   = 0;
    40.      LCD_data = (temp << 4) & 0XF0;
    41.      LCD_rs   = 0;        //Selected command register
    42.      LCD_en   = 1;        //Enable H->L
    43.      LCD_en   = 0;
    44.      delay_ms(1);
    45. }
    46. void LCD_clear_display () {
    47.      LCD_data = 0x01;     //Clear LCD
    48.      LCD_write_command();
    49. }
    50. void LCD_return_home () {
    51.      LCD_data = 0x02;     //Return LCD to Home
    52.      LCD_write_command();
    53. }
    54. void LCD_entry_mode_set (unsigned int ID,unsigned int S) {
    55.      /*
    56.      ID => [Decrement : Increment]
    57.            0 => Decrement
    58.            1 => Increment
    59.      S  => accompanies display shift
    60.            0 => OFF
    61.            1 => ON
    62.      */
    63.      LCD_data = 0x00;
    64.      ID = ID << 1;
    65.      LCD_data = LCD_data + 0x04 + ID + S;
    66.      LCD_write_command();
    67. }
    68. void LCD_display_control (unsigned int D,unsigned int C,unsigned int B) {
    69.      /*
    70.      D  => Display ON/OFF
    71.            0 => OFF
    72.            1 => ON
    73.      C  => Cursor ON/OFF
    74.            0 => OFF
    75.            1 => ON
    76.      B  => Blink the character at the cursor position
    77.            0 => OFF
    78.            1 => ON
    79.      */
    80.      LCD_data = 0x00;
    81.      C = C << 1;
    82.      D = D << 2;
    83.      LCD_data = LCD_data + 0x08 + D + C + B;
    84.      LCD_write_command();
    85. }
    86. void LCD_cursor_display_shift (unsigned int SC,unsigned int RL) {
    87.      /*
    88.      Moves the cursor and shifts the display without changing the DDRAM contents
    89.      SC  => [Cursor : Display]
    90.            0 => Cursor
    91.            1 => Display
    92.      RL  => [Left : Right]
    93.            0 => Left
    94.            1 => Right
    95.      */
    96.      LCD_data = 0x00;
    97.      RL = RL << 2;
    98.      SC = SC << 3;
    99.      LCD_data = LCD_data + 0x10 + SC + RL;
    100.      LCD_write_command();
    101. }
    102. void LCD_function_set (unsigned int DL,unsigned int N,unsigned int F) {
    103.      /*
    104.      DL  => Data Width [4 bit : 8 bit]
    105.            0 => 4 bit
    106.            1 => 8 bit
    107.      N  => Number of lines in display[1 : 2]
    108.            0 => 1 Line
    109.            1 => 2 Lines
    110.      F  => Character font[5x7 : 5x10]
    111.            0 => 5x7
    112.            1 => 5x10
    113.      */
    114.      LCD_data = 0x00;
    115.      F = F << 2;
    116.      N = N << 3;
    117.      DL = DL << 4;
    118.      LCD_data = LCD_data + 0x20 + DL + N + F;
    119.      LCD_write_command();
    120. }
    121. void LCD_cgram_address (unsigned int cgadrs) {
    122.      /*
    123.      cgadrs => CGRAM Address Binary 6 bit
    124.      i didn't use it yet
    125.      */
    126.      LCD_data = 0x00;
    127.      LCD_data = cgadrs;
    128.      LCD_write_command();
    129. }
    130. void LCD_ddram_address (unsigned int ddadrs) {
    131.      /*
    132.      ddadrs => DDRAM Address Binary 7 bit
    133.                Line 1 Column 1
    134.                Binary Address : 0B10000000
    135.                HEX Address     : 0X80
    136.  
    137.                Line 1 Column 16
    138.                Binary Address : 0B10001111
    139.                HEX Address     : 0X8F
    140.  
    141.                Line 2 Column 1
    142.                Binary Address : 0B11000000
    143.                HEX Address     : 0XC0
    144.  
    145.                Line 2 Column 16
    146.                Binary Address : 0B11001111
    147.                HEX Address     : 0XCF
    148.                [][][][][][][][][][][][][][][][]
    149.                [][][][][][][][][][][][][][][][]
    150.                     C1    C2    C3    C4    C5    C6    C7    C8    C9    C10   C11   C12   C13   C14   C15   C16
    151.                L1 [0X80][0X81][0X82][0X83][0X84][0X85][0X86][0X87][0X88][0X89][0X8A][0X8B][0X8C][0X8D][0X8E][0X8F]
    152.                L2 [0XC0][0XC1][0XC2][0XC3][0XC4][0XC5][0XC6][0XC7][0XC8][0XC9][0XCA][0XCB][0XCC][0XCD][0XCE][0XCF]
    153.      */
    154.      LCD_data = 0x00;
    155.      LCD_data = ddadrs;
    156.      LCD_write_command();
    157. }
    158. void LCD_write_data(unsigned int output) {
    159.      /*
    160.      output => Data to be written
    161.      */
    162.      unsigned int output;//
    163.      output = LCD_data;
    164.      LCD_data = output & 0XF0;
    165.      LCD_rs   = 1;        //Selected data register
    166.      LCD_en   = 1;        //Enable H->L
    167.      LCD_en   = 0;
    168.      LCD_data = (output << 4) & 0XF0;
    169.      LCD_rs   = 1;        //Selected data register
    170.      LCD_en   = 1;        //Enable H->L
    171.      LCD_en   = 0;
    172.      delay_ms(1);
    173. }
    174. void LCD_init ()
    175. {
    176.      LCD_reset();         // Call LCD reset
    177.      LCD_function_set (0,1,0);//Function set: 2 Line, 4-bit, 5x7 dots
    178.      LCD_display_control (1,1,1);//Display on, Curson blinking command.
    179.      LCD_clear_display();
    180.      LCD_entry_mode_set (1,0);//Entry mode, auto increment with no shift
    181.      LCD_ddram_address(0X80);//Line 1 Column 1
    182.  }
    183. void main() {
    184.      TRISB = 0x00;
    185.      LCD_init();
    186.      LCD_write_data(0xff);//'A'
    187. }
    188.  
    and the result is that the LCD switched on with no data on it
    SOS PLZ :D :D
     
  3. walid el masry

    Thread Starter Active Member

    Mar 31, 2009
    132
    0
    here is the instruction set i written in my code

    Code ( (Unknown Language)):
    1.  
    2. --------------------------------------------------------
    3. LCD_clear_display ();
    4. --------------------------------------------------------
    5. LCD_return_home ();
    6. --------------------------------------------------------
    7. LCD_entry_mode_set (unsigned int ID,unsigned int S);
    8.      ID => [Decrement : Increment]
    9.            0 => Decrement
    10.            1 => Increment
    11.      S  => accompanies display shift
    12.            0 => OFF
    13.            1 => ON
    14. --------------------------------------------------------
    15. LCD_display_control (unsigned int D,unsigned int C,unsigned int B);
    16.      D  => Display ON/OFF
    17.            0 => OFF
    18.            1 => ON
    19.      C  => Cursor ON/OFF
    20.            0 => OFF
    21.            1 => ON
    22.      B  => Blink the character at the cursor position
    23.            0 => OFF
    24.            1 => ON
    25. --------------------------------------------------------
    26. LCD_cursor_display_shift (unsigned int SC,unsigned int RL);
    27.      Moves the cursor and shifts the display without changing the DDRAM contents
    28.      SC  => [Cursor : Display]
    29.            0 => Cursor
    30.            1 => Display
    31.      RL  => [Left : Right]
    32.            0 => Left
    33.            1 => Right
    34. --------------------------------------------------------
    35. LCD_function_set (unsigned int DL,unsigned int N,unsigned int F)
    36.      DL  => Data Width [4 bit : 8 bit]
    37.            0 => 4 bit
    38.            1 => 8 bit
    39.      N  => Number of lines in display[1 : 2]
    40.            0 => 1 Line
    41.            1 => 2 Lines
    42.      F  => Character font[5x7 : 5x10]
    43.            0 => 5x7
    44.            1 => 5x10
    45. --------------------------------------------------------
    46. LCD_cgram_address (unsigned int cgadrs);
    47.      cgadrs => CGRAM Address Binary 6 bit
    48.      i didn't use it yet
    49. --------------------------------------------------------
    50. LCD_ddram_address (unsigned int ddadrs);
    51.      ddadrs => DDRAM Address Binary 7 bit
    52.                Line 1 Column 1
    53.                Binary Address : 0B10000000
    54.                HEX Address     : 0X80
    55.  
    56.                Line 1 Column 16
    57.                Binary Address : 0B10001111
    58.                HEX Address     : 0X8F
    59.  
    60.                Line 2 Column 1
    61.                Binary Address : 0B11000000
    62.                HEX Address     : 0XC0
    63.  
    64.                Line 2 Column 16
    65.                Binary Address : 0B11001111
    66.                HEX Address     : 0XCF
    67.                [][][][][][][][][][][][][][][][]
    68.                [][][][][][][][][][][][][][][][]
    69.                     C1    C2    C3    C4    C5    C6    C7    C8    C9    C10   C11   C12   C13   C14   C15   C16
    70.                L1 [0X80][0X81][0X82][0X83][0X84][0X85][0X86][0X87][0X88][0X89][0X8A][0X8B][0X8C][0X8D][0X8E][0X8F]
    71.                L2 [0XC0][0XC1][0XC2][0XC3][0XC4][0XC5][0XC6][0XC7][0XC8][0XC9][0XCA][0XCB][0XCC][0XCD][0XCE][0XCF]
    72. --------------------------------------------------------
    73. LCD_write_data(unsigned int output);
    74.      output => Data to be written
    75. --------------------------------------------------------
    76.  
    and the manual LCD commands

    [​IMG]
     
  4. rjenkins

    AAC Fanatic!

    Nov 6, 2005
    1,015
    69
    Do you have the correct four data lines of the LCD connected to the high half of Port B?

    If they are OK, it could be timing - the LCD 'E' pulse must be 450nS minimum, unless you are using a very low CPU clock you may have to add some NOPs between setting E High & Low again.

    You could also try the '8 Bit' program, just substituting the 4 bit LCD Write Command & Write Data routines substituted for the 8 bit versions, with any required tweaks and the different init values.

    That gives you a lot less code to debug!
     
  5. walid el masry

    Thread Starter Active Member

    Mar 31, 2009
    132
    0
    iam sorry i forgot to include the connection

    thats it

    [​IMG]
     
  6. rjenkins

    AAC Fanatic!

    Nov 6, 2005
    1,015
    69
    I've used the LM016 in 8 bit mode, but never 4 bit.

    In the data sheet for the HD44780 controller chip, it says the Busy line *must* be checked after each write.

    I wonder if it needs transitions on the R/W line to sync the High & Low nibbles of the data transfer..

    I woudl try single-stepping your code in the simulator and check each value sent out of the data port against the LCD controller data sheet to make sure it is sending the right commands.

    HD44780 Data:
    http://users.ece.gatech.edu/~hamblen/UP3/HD44780u.pdf
     
  7. walid el masry

    Thread Starter Active Member

    Mar 31, 2009
    132
    0
    you are correct about the buzy flag but i have the option to check it or to wait for the correct delay of time and send another data or command and i have to say that i have already programed it in 4 bit mode but in assembly for the same chip but it just not working and iam wery sure about the code for 8 bit mode and have tested it successfully and it doesn't need a big modification to work in 4 bit mode just the
    LCD_write_command & LCD_write_data that i have to change it and i tested them also
    successfully away from the code and they take the higher nibbles and send it then enable signal then the same for the lower nibbles and wait for the time which suppose the lcd will not buzy after it but it just not working :( :(
     
  8. rjenkins

    AAC Fanatic!

    Nov 6, 2005
    1,015
    69
    I don't know as a fact, but the only thing I can think of is it *needs* a transition on the R/W line to synchronise when in 4 bit mode.

    If you look at the timing diagrams for 4 bit mode, the R/W transitions are always between the pairs of H/L nibble transfers.

    Until it sees such a transition, how does it sync high and low nibbles??
    - the ONLY key appears to be that the High half is first after any R/W change.
     
  9. walid el masry

    Thread Starter Active Member

    Mar 31, 2009
    132
    0
    if you mean with the transition of R/W the changing in the state from H to L i guess its not a big deal cause it is just about to read the buzy flag not to synchronise between the higher and lower nibbles which controlled by the enable signal after sending each nibble it goes fro H to L which synchronise between them , see this from the manual you give me at the page 23

    [​IMG]

    there is no need to change the state of R/W from L to H just to read the buzy flag
     
  10. walid el masry

    Thread Starter Active Member

    Mar 31, 2009
    132
    0
    [​IMG]

    what i have done in the code is that write a functions to handle every instruction and you just need to enter the value of the parameters as you like and then put them in the LCD_data and then let the functions
    LCD_write_command() or the LCD_write_data() write them to the LCD and it was successful in the 8 bit mode so the thing i need to change is the way i send the command or the data to the LCD and as we know in 4 bit mode we take the higher nibble and send it then enable signal then lower nibble then enable signal then wait the buzy flag or check it by reading it so lets test the concept of my code there

    Code ( (Unknown Language)):
    1.  
    2. [B][B]void LCD_write_command () {
    3.      unsigned int temp;
    4.      temp = LCD_data;//take a temp copy of the output of each function which will be send to LCD
    5.      LCD_data = temp & 0XF0;//mask the higher nibble
    6.      LCD_rs   = 0;        //Selected command register
    7.      LCD_en   = 1;        //Enable H->L
    8.      LCD_en   = 0;
    9.      //****1
    10.      LCD_data = (temp << 4) & 0XF0;//swap lower nibble with the higher and mask it
    11.      LCD_rs   = 0;        //Selected command register
    12.      LCD_en   = 1;        //Enable H->L
    13.      LCD_en   = 0;
    14.      delay_ms(1);//****2
    15. }
    16. [/B][/B]
    17.  
    and to be sure if the program working i tried to blink the LCD_data or the PORTB after

    Code ( (Unknown Language)):
    1.  
    2. [B][B][B][B]LCD_write_data(0xff);//'A'[/B][/B][/B][/B]
    3.  
    in

    Code ( (Unknown Language)):
    1.  
    2. [B][B]void main() {
    3.      TRISB = 0x00;
    4.      LCD_init();
    5.      LCD_write_data(0xff);//'A'
    6. }[/B][/B]
    7.  
    and the program reached it normally , i can't know that is the wrong but i guess it is the timing and i guess it will be at the point
    ****1 or ****2 or both of them , what do you think
     
  11. walid el masry

    Thread Starter Active Member

    Mar 31, 2009
    132
    0
    i forgot , or in the timing of the initialization sequence of the 4 bit mode

    Code ( (Unknown Language)):
    1.  
    Code ( (Unknown Language)):
    1.  
    2.     [B][B]void LCD_reset () {
    3.      LCD_data = 0XFC;
    4.      delay_ms(20);
    5.      LCD_data = 0X34;//Data = 34H, EN = 1, RS = 0, First Init
    6.      LCD_data = 0X30;//Data = 30H, EN = 0, RS = 0
    7.      delay_ms(10);
    8.      LCD_data = 0X34;//Data = 34H, EN = 1, RS = 0, Second Init
    9.      LCD_data = 0X30;//Data = 30H, EN = 0, RS = 0
    10.      delay_ms(1);
    11.      LCD_data = 0X34;//Data = 34H, EN = 1, RS = 0, Third Init
    12.      LCD_data = 0X30;//Data = 30H, EN = 0, RS = 0
    13.      delay_ms(1);
    14.      LCD_data = 0X44;//Data = 44H, EN = 1, RS = 0, Select Data width (4bit)
    15.      LCD_data = 0X40;//Data = 40H, EN = 0, RS = 0
    16.      delay_ms(1);
    17. }
    18. [/B]
    19. [/B]
     
  12. THE_RB

    AAC Fanatic!

    Feb 11, 2008
    5,435
    1,305
    1. You do know that the MikroC compiler you are using already has a full set of 8bit and 4bit LCD functions, you don't need to write your own?

    2. Since you have written your own, you might want to post your code on the MikroE forum, people are often asking for LCD code because the MikroC built in code requires the use of specific port pins and they want to use LCD with different pins.
     
  13. rjenkins

    AAC Fanatic!

    Nov 6, 2005
    1,015
    69
    We are at cross purposes; I do not mean you must USE the busy signal, I mean that the transition of the R/W line could be needed.

    Think about the data and control pattern as seen by the LCD Controller; every nibble sent has an E pulse.

    How does the controller know which is the Low data and which is the High data?

    It's not E, so it must be one of the other control lines that only changes between Byte transfers & resets the internal state machine so it uses the next transfer as a High nibble.


    Re. other timing, depending on the exact type of controller chip, the minimum E cycle time (from one rising edge to the next) is either 1uS or 500nS and the minimum E pulse width or separation is half of that.

    What clock speed is your PIC running at?
    (Also, what compiler are you using?)

    Edit: Sorry, you mentioned MikroC compiler..
     
    Last edited: Aug 30, 2009
  14. rjenkins

    AAC Fanatic!

    Nov 6, 2005
    1,015
    69
    I've just checked the driver routines supplied with my C compiler (CCS).
    There is an LCD module included and it is for Four bit operating mode.

    They have a few 'delay_cycles(1)' scattered about, most of which are not actually required. The possibly critical differences between their timings and yours are:
    A: Use of busy check loop before each byte write sequence (so toggling R/W).
    B: A 'delay_us(2)' between setting E high and low at each transfer.

    That's way longer than required, but some delay may be required to get the minimum E pulse width of 500 or 250nS.
     
  15. walid el masry

    Thread Starter Active Member

    Mar 31, 2009
    132
    0
    i tried checking the busy and as i expected it works for the 8 bit mode :D

    and here is the code

    Code ( (Unknown Language)):
    1.  
    2. void LCD_busy() {
    3.      //delay is in case you don't want to check the buzy flag
    4.      //delay_ms(5);//it is very important to return to the manual for it
    5.      //in case of chicking the buzy flag
    6.      LCD_D7 = 1;           //Make D7th bit of LCD as i/p
    7.      LCD_en = 1;           //Make port pin as o/p
    8.      LCD_rs = 0;
    9.      LCD_rw = 1;
    10.      while (LCD_D7) {
    11.            LCD_en = 0;
    12.            LCD_en = 1;
    13.      }
    14. }
    15.  
    it works but i have to ask is that true the i can change the state of pin or port while running from output to input specially for PIC ?

    and unfortunately the 4 bit mode still not working after modification
    let's see it

    [​IMG]

    see the code but 1st i i should mention that when testing on 8 bit or 4 bit it gives me in Proteus

    Code ( (Unknown Language)):
    1.  
    2. Logic connection(s) detected on net #
    3.  
    and also that

    Code ( (Unknown Language)):
    1.  
    2. Controller received command whilst busy
    3.  
    and

    Code ( (Unknown Language)):
    1.  
    2. [HD44780] Attempted to read after writing a single nibble
    3. &
    4. [HD44780] Attempted to write after reading a single nibble
    5.  
    and that is the code for write commad

    Code ( (Unknown Language)):
    1.  
    2. void LCD_write_command () {
    3.      unsigned int temp;
    4.      temp = LCD_data;
    5.      LCD_data = temp & 0XF0;
    6.      LCD_rs   = 0;        //Selected command register
    7.      LCD_rw   = 0;        //we are writing
    8.      LCD_en   = 1;        //Enable H->L
    9.      LCD_en   = 0;
    10.      LCD_data = (temp << 4) & 0XF0;
    11.      LCD_en   = 1;        //Enable H->L
    12.      LCD_en   = 0;
    13.      LCD_D7   = 1;           //Make D7th bit of LCD as i/p
    14.      LCD_en   = 1;           //Make port pin as o/p
    15.      LCD_rs = 0;
    16.      LCD_rw   = 1;        //we are reading
    17.      while(LCD_D7){          //read busy flag again and again till it becomes 0
    18.            LCD_en   = 0;     //Enable H->L
    19.            LCD_en   = 1;
    20.      }
    21. }
    22.  
    and writing data

    Code ( (Unknown Language)):
    1.  
    2. void LCD_write_data(unsigned int output) {
    3.      /*
    4.      output => Data to be written
    5.      */
    6.      output = LCD_data;
    7.      LCD_data = output & 0XF0;
    8.      LCD_rs   = 1;        //Selected data register
    9.      LCD_rw   = 0;        //we are writing
    10.      LCD_en   = 1;        //Enable H->L
    11.      LCD_en   = 0;
    12.      LCD_data = (output << 4) & 0XF0;
    13.      LCD_en   = 1;        //Enable H->L
    14.      LCD_en   = 0;
    15.      LCD_D7   = 1;           //Make D7th bit of LCD as i/p
    16.      LCD_en   = 1;           //Make port pin as o/p
    17.      LCD_rs = 1;
    18.      LCD_rw   = 1;        //we are reading
    19.      while(LCD_D7){          //read busy flag again and again till it becomes 0
    20.            LCD_en   = 0;     //Enable H->L
    21.            LCD_en   = 1;
    22.      }
    23. }
    24.  
    :confused:
     
  16. rjenkins

    AAC Fanatic!

    Nov 6, 2005
    1,015
    69
    In 4 bit mode, EVERY 'transaction' with the LCD must be 8 bit (2x4 bits) including reading the busy flag; see the timing diagram (Figure 9) in the data sheet link I posted earlier.
    (But you can discard the low nibble when just checking Busy).

    LCD_D7 = 1; will not work, it just sets the pin High rather than make it an input.

    You should change the TRIS register to change pins between input and output, eg.
    You should have

    TRISB = 0x00; to set all as output,
    and
    TRISB = 0xF0; to set high nibble as input and low still output.

    The Busy flag is part of the address register, when you do a read you are reading data on all data lines, so all the data lines at the PIC end must be set to the matching direction before E is active to avoid conflicts or damage.
     
  17. walid el masry

    Thread Starter Active Member

    Mar 31, 2009
    132
    0
    iam 100 % with you

    i belive it will never work but the problem is that it works and that what make me ask in the last post

    and from the testing of the code i add to my question

    good thinking and logically also but without TRIS thats what mde me crazy and also it works for the 8 bit :D :(
     
  18. walid el masry

    Thread Starter Active Member

    Mar 31, 2009
    132
    0
    btw for THE_RB i have already registered on MikroE forum and posted the code there at mikroC PRO for PIC General section
     
  19. rjenkins

    AAC Fanatic!

    Nov 6, 2005
    1,015
    69
    Just noticed something rather wrong;
    you are using 'LCD_Data' as a temporary store at the start of the routines (temp = LCD_Data and output = LCD_Data; ) but LCD_Data also appears to be you output port, the low half of which is the LCD control lines.

    Any time you write to LCD_Data it sets ALL EIGHT pins to the values in that byte, including the control pins.

    This is almost certainly messing up the 'nibble sync' with the LCD as every time you set up to write a byte/character with bit 3 set, it activates E before the LCD_write_xxx routines are called.
     
  20. walid el masry

    Thread Starter Active Member

    Mar 31, 2009
    132
    0
    i will try it now still online PLZ :)
     
Loading...