LCD 20x4 HD44780 Controller

Discussion in 'Embedded Systems and Microcontrollers' started by Nektarios, Feb 19, 2015.

  1. Nektarios

    Thread Starter New Member

    Feb 19, 2015
    2
    0
    Hello!

    I would like to ask your help with my lcd-program!
    I have searched enough to find a code from a lcd library for a LCD 20x4, but i couldnt to adjust it to my Project.
    I use 4-bit Logic for the lcd-data. I program an atmega32 with avrstudio4.

    The functions which i use are:

    Code (Text):
    1.  
    2. /************************************************
    3.  LCD CONNECTIONS
    4. *************************************************/
    5. #define LCD   PORTC   //Port PC0-PC3 are connected to D4-D7
    6. #define RS  PORTC5
    7. #define RW  PORTC6
    8. #define E  PORTC7   //Position of enable
    9. #define SET(x)  (LCD|=(1<<x))
    10. #define RESET(x) (LCD&=(~(1<<x)))
    11.  

    Code (Text):
    1.  
    2.  
    3. void LCDByte(uint8_t c,uint8_t isdata)
    4. {
    5. //Sends a byte to the LCD in 4bit mode
    6. //cmd=0 for data
    7. //cmd=1 for command
    8. uint8_t hn,ln;  //Nibbles
    9. uint8_t temp;
    10. hn=c>>4;  //hn had the 4 most significal bits of c
    11. ln=(c & 0x0F);  //hn had the 4 less significal bits of c
    12. if(isdata==0)
    13.   RESET(RS);  //if is comand
    14. else
    15.   SET(RS);  //if is data
    16. _delay_us(0.500);  //tAS
    17. //Send high nibble
    18. SET(E);
    19. temp=(LCD & 0XF0)|(hn);
    20. LCD=temp;
    21. _delay_us(1);  //tEH
    22. //Now data lines are stable pull E low for transmission
    23. RESET(E);
    24. _delay_us(1);
    25. //Send the lower nibble
    26. SET(E);
    27. temp=(LCD & 0XF0)|(ln);
    28. LCD=temp;
    29. _delay_us(1);  //tEH
    30. //SEND
    31. RESET(E);
    32. _delay_ms(2);  //tEL
    33. }
    34. //***************************
    35. void InitLCD()
    36. {
    37. //After power on Wait for LCD to Initialize
    38. _delay_ms(30);
    39. //Set IO Ports
    40. DDRC=0xFF;  //<<<<<<<<<<<<<<<<<!!!!!!!!!!!!!!!!must set the correct port
    41. LCD=0X00;
    42. //Set 4-bit mode
    43. _delay_us(1);  //tAS
    44. SET(E);
    45. LCD|=(0b00000010);  // 4 bits interface data length
    46. _delay_us(1);
    47. RESET(E);
    48. _delay_us(1);
    49. //Wait for LCD to execute the Functionset Command
    50. _delay_ms(10);  //[B] Forgot this delay
    51. //Now the LCD is in 4-bit mode
    52. LCDByte(0b00001111,0); //Display On
    53. LCDByte(0b00101000,0); //function set 4-bit,2 line 5x7 dot format
    54. }
    55.  
    56.  
    Code (Text):
    1.  
    2.  
    3. void LCDGotoXY(uint8_t x,uint8_t y)
    4. {
    5.   if(x<40)
    6.   {
    7.   switch(y)
    8.   {
    9.   // Line 1
    10.   case 0: x|=0x80; break;  //1000 0000
    11.   // Line 2
    12.   case 1: x|=0xC0; break;  //1100 0000
    13.   // Line 3
    14.   case 2: x|=0x94; break;  //1001 0100
    15.   // Line 4
    16.   case 3: x|=0xD4; break;  //1101 0100
    17.   }
    18.   //LCDCmd(x);
    19.   LCDByte(x,0);
    20.   }
    21.  
    22. }
    23.  

    Code (Text):
    1.  
    2.  
    3. void LCDWriteString(const char *msg)
    4. {
    5.  while(*msg!='\0')
    6.  {
    7.  //Custom Char Support
    8.  if(*msg=='%')
    9.  {
    10.  msg++;
    11.  int8_t cc=*msg-'0';
    12.  if(cc>=0 && cc<=7)
    13.  {
    14.  LCDData(cc);
    15.  }
    16.  else
    17.  {
    18.  LCDData('%');
    19.  LCDData(*msg);
    20.  }
    21.  }
    22.  else
    23.  {
    24.  LCDData(*msg);
    25.  }
    26.  msg++;
    27.  }
    28. }
    29.  

    So my problem is, that if i put the values 0x80-0xc0-0x94-0xd4 in the function LCDGotoXY() the Lines 3&4 dont work ok!
    After the 4th character (line3 & line4) the display has problem.

    I had also used the
    0x00
    0x40
    0x14
    0x54
    but still not working for my code!


    Can someone, who knows how to calculate correct these values (and i can use these functions), help me!!

    thanks in advance!



    (sorry for my bad english) :) :)
     
  2. MrChips

    Moderator

    Oct 2, 2009
    12,449
    3,363
    Don't OR your x values. Use ADD.

    Code (Text):
    1.  
    2. void LCDGotoXY(uint8_t x,uint8_t y)
    3. {
    4. if(x<40)
    5. {
    6. switch(y)
    7. {
    8. // Line 1
    9. case 0: x +=0x80; break; //1000 0000
    10. // Line 2
    11. case 1: x +=0xC0; break; //1100 0000
    12. // Line 3
    13. case 2: x +=0x94; break; //1001 0100
    14. // Line 4
    15. case 3: x +=0xD4; break; //1101 0100
    16. }
    17. //LCDCmd(x);
    18. LCDByte(x,0);
    19. }
    20.  
    21. }
    22.  
     
  3. Nektarios

    Thread Starter New Member

    Feb 19, 2015
    2
    0
    MrChips you are right!
    Now it is fine!!
    Thank you, thank you very much!!!

    I present the full code together in case someone else has the same problem!!


    file=lcd.h
    Code (Text):
    1.  
    2. #define F_CPU 16000000L
    3. #include <avr/io.h>
    4. #include <util/delay.h>
    5.  
    6. #ifndef _LCD_H
    7.  #define _LCD_H
    8. /************************************************
    9.  LCD CONNECTIONS
    10. *************************************************/
    11. #define LCD   PORTC   //Port PC0-PC3 are connected to D4-D7
    12. #define RS  PORTC5
    13. #define RW  PORTC6
    14. #define E  PORTC7   //Position of enable
    15. #define SET(x)  (LCD|=(1<<x))
    16. #define RESET(x) (LCD&=(~(1<<x)))
    17. //The prototyping is necessary for the definiton of LCDWriteStringXY()
    18. void LCDGotoXY(uint8_t x,uint8_t y);
    19. void LCDWriteString(const char *msg);
    20.  
    21.  
    22. //**********************LCD*****************************
    23. void LCDByte(uint8_t c,uint8_t isdata)
    24. {
    25.  //Sends a byte to the LCD in 4bit mode
    26.  //cmd=0 for data
    27.  //cmd=1 for command
    28.  uint8_t hn,ln; //Nibbles
    29.  uint8_t temp;
    30.  hn=c>>4; //hn had the 4 most significal bits of c
    31.  ln=(c & 0x0F); //hn had the 4 less significal bits of c
    32.  if(isdata==0)
    33.  RESET(RS); //if is comand
    34.  else
    35.  SET(RS);  //if is data
    36.  _delay_us(0.500); //tAS
    37.  //Send high nibble
    38.  SET(E);
    39.  temp=(LCD & 0XF0)|(hn);
    40.  LCD=temp;
    41.  _delay_us(1); //tEH
    42.  //Now data lines are stable pull E low for transmission
    43.  RESET(E);
    44.  _delay_us(1);
    45.  //Send the lower nibble
    46.  SET(E);
    47.  temp=(LCD & 0XF0)|(ln);
    48.  LCD=temp;
    49.  _delay_us(1); //tEH
    50.  //SEND
    51.  RESET(E);
    52.  _delay_ms(2); //tEL
    53. }
    54. //***************************
    55. void InitLCD()
    56. {
    57.  //After power on Wait for LCD to Initialize
    58.  _delay_ms(30);
    59.  //Set IO Ports
    60.  DDRC=0xFF;  //<<<<<<<<<<<<<<<<<!!!!!!!!!!!!!!!!must set the correct port
    61.  LCD=0X00;
    62.  //Set 4-bit mode
    63.  _delay_us(1); //tAS
    64.  SET(E);
    65.  LCD|=(0b00000010);  // 4 bits interface data length
    66.  _delay_us(1);
    67.  RESET(E);
    68.  _delay_us(1);
    69.  
    70.  //Wait for LCD to execute the Functionset Command
    71.  _delay_ms(10);  //[B] Forgot this delay
    72.  //Now the LCD is in 4-bit mode
    73.  LCDByte(0b00001111,0); //Display On
    74.  LCDByte(0b00101000,0); //function set 4-bit,2 line 5x7 dot format
    75. }
    76.  
    77. //***************************
    78. void LCDGotoXY(uint8_t x,uint8_t y)
    79. {  
    80.   if(x<40)
    81.   {
    82.   switch(y)
    83.   {
    84.  // Line 1
    85.  case 0: x +=0x80; break; //1000 0000
    86.  // Line 2
    87.  case 1: x +=0xC0; break; //1100 0000
    88.  // Line 3
    89.  case 2: x +=0x94; break; //1001 0100
    90.  // Line 4
    91.  case 3: x +=0xD4; break; //1101 0100
    92.   }
    93.   //LCDCmd(0x80|x); //(x);
    94.   LCDByte(x,0);
    95.   }
    96.  
    97. }
    98. //***************************
    99. void LCDWriteString(const char *msg)
    100. {
    101.  while(*msg!='\0')
    102.  {
    103.  //Custom Char Support
    104.  if(*msg=='%')
    105.  {
    106.  msg++;
    107.  int8_t cc=*msg-'0';
    108.  if(cc>=0 && cc<=7)
    109.  {
    110.  LCDData(cc);
    111.  }
    112.  else
    113.  {
    114.  LCDData('%');
    115.  LCDData(*msg);
    116.  }
    117.  }
    118.  else
    119.  {
    120.  LCDData(*msg);
    121.  }
    122.  msg++;
    123.  }
    124. }
    125. //***************************
    126. void LCDWriteStringXY(const char *msg, uint8_t x, uint8_t y)
    127. {
    128.  //Call the function for the cursor movement
    129.  LCDGotoXY(x,y);
    130.  //Call the function for write the message
    131.  LCDWriteString(msg);
    132. }
    133. //***************************
    134. void LCDWriteInt(int val)
    135. {
    136.   if(val<0)
    137.   {
    138.    LCDByte('-',1);
    139.    val=(-val);
    140.   }
    141.   char str[5]={0,0,0,0,0};
    142.   int i=4,j=0;
    143.   while(val)
    144.   {
    145.    str[i]=val%10;
    146.    val=val/10;
    147.    i--;
    148.   }
    149.  
    150.   while(str[j]==0) j++;
    151.  
    152.   for(i=j;i<5;i++)
    153.   {
    154.    LCDByte(48+str[i],1);
    155.   }
    156. }
    157. //***************************
    158. void LCDWriteIntXY(int val, uint8_t x, uint8_t y)
    159. {
    160.  //Call the function for the cursor movement
    161.  LCDGotoXY(x,y);
    162.  //Call the function for write the integer
    163.  LCDWriteInt(val);
    164. }
    165.  
    166. //**********************LCD_end*******************************
    167.  
    168. #endif
    169.  

    file=main.c
    Code (Text):
    1.  
    2. #define F_CPU 16000000L
    3. #include <avr/io.h>
    4. #include <util/delay.h>
    5. #include "lcd.h"
    6.  
    7. int main()
    8. {
    9. int c=0;
    10. while(1)
    11. {
    12.  
    13.  LCDWriteIntXY(1,c,0);
    14.  LCDWriteIntXY(2,c,1);
    15.  LCDWriteIntXY(3,c,2);
    16.  LCDWriteIntXY(4,c,3);
    17.  _delay_ms(1000);
    18.  LCDByte(0b00000001,0);
    19.  if(c>=19){ c=0; }
    20.  else {c++; }
    21. }
    22.  
    23. }
    24.  
     
Loading...