title: displaying Hexadecimal value in LCD
body: <p>I wrote LCD interface program for Atmega328 (Though there are libraries available, I wanted to write from scratch). But have two problems.
  1. Sometimes LCD does not display correctly. Only few strips are seen. I end up in resetting once or twice.
  2. I am unable to display hexadecimal values usingdisplayOneByteHexValue(). However ASCII coversion was correct and I could see that in Atmel Simulator. Below is the code. I am using Atmel Studio 6.2</p>
  
  <pre><code>/*
  * EmbeddedProgram1.c
  *
  * Created: 16-05-2015 08:19:38
  *  Author: Mahesha
  */
  
  
  #ifndef F_CPU
  #define F_CPU 8000000UL
  #endif
  
  #include &lt;avr/io.h&gt;
  #include &lt;util/delay.h&gt;
  
      ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  //Only Change following when changing pin numbers.
  // All Data bits have to be assigned sequentially in same the port . RS and EN must be allocated in the same port
  #define LCDPORT PORTD
  #define LCDDDR DDRD
  // used pins on port appropriate ports
  #define LCD_DB4 2    // PORTD.2
  #define LCD_DB5 3    // PORTD.3
  #define LCD_DB6 4    // PORTD.4
  #define LCD_DB7 5    // PORTD.5
  #define LCD_ENABLE_BIT  6     // PORTD.6 Enable
  #define LCD_RS 7     // PORTD.7 Register Select
  //#define LCD_RW     // R/W is connected to GND permanently
  
  
  #define LCD_DATA_BITS_MASK 0x3C
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  
  #define SET_EIGHT_BIT_MODE() LCDPORT|=((1&lt;&lt;LCD_DB5)|(1&lt;&lt;LCD_DB4))    // Set DB4 and DB5 as 1 for setting eight bit mode.
  #define SET_FOUR_BIT_MODE() LCDPORT|=(1&lt;&lt;LCD_DB5)
  #define SET_INSTRUCTION_MODE() LCDPORT&amp;=~(1&lt;&lt;LCD_RS)      //Function to select command port on LCD RS pin bit 2
  #define SET_DATA_MODE() LCDPORT|=(1&lt;&lt;LCD_RS)         //Function to select data port on LCD
  #define DISABLE_LCD() LCDPORT&amp;=~(1&lt;&lt;LCD_ENABLE_BIT)           //Function to disable LCD P0.18
  #define ENABLE_LCD() LCDPORT|=(1&lt;&lt;LCD_ENABLE_BIT)            //Function to Enable LCD     P0.18
  
  //#define EIGHT_BIT_MODE 0x30                                      // 0 0 1 1 x x x x DB7 to DB0 0f LCD
  #define BUSY_FLAG_WAIT_TIME 20
  #define FOUR_BIT_5_BY_10_2LINE 0x28
  #define LCD_INIT_DELAY 100      // Give a delay of 200 msec after reset. // Datasheet says 10 msec delay.
  
  
  //Commands Finalized
  #define CLEAR_DISPLAY 0x01
  #define CURSOR_HOME 0x02    // return home
  #define ENTRY_MODE_LEFT_TO_RIGHT 0x06              // Cursor direction from Left to right   , Bit 1 of entry mode in LCD
  #define DISPLAY_OFF  0x08        // Blink ON, Cursor ON etc are don't care
  #define CURSOR_OFF_BLINK_OFF   0x0C
  #define CURSOR_OFF_BLINK_ON 0x0D    // blink on Even 0x0D also works. So cursor need not be ON
  #define CURSOR_ON_BLINK_OFF 0x0E    // blink off
  #define CURSOR_ON_BLINK_ON 0x0F
  #define SHIFT_ENTIRE_LEFT 0x18
  #define SHIFT_CURSOR_LEFT 0x10
  #define SHIFT_ENTIRE_RIGHT 0x1C
  #define SHIFT_CURSOR_RIGHT 0x14
  
  // Function prototypes
  void unpackAndSend(char  data);
  void waitForBusyFlagToClear(void);
  void sendLCDPulse(void);
  void displayInRow1(char* data);
  void displayInRow2(char* data);
  void displayInRow1WithPosition(char* data, uint8_t position);
  void displayInRow2WithPosition(char* data, uint8_t position);
  void sendTextToLCD(char *data);
  void displayOneByteHexValue(unsigned char,unsigned char,char);
  void initializeLCD(void);
  
  void CL_delayMS(unsigned int delayMS)
  {
      while(delayMS--)
      {
          _delay_ms(1);
      }
  }
  
  void CL_delayuS(unsigned int delayus)
  {
      while(delayus--)
      {
          _delay_us(1);
      }
  }
  
  
  // writes a char to the LCD
  void writeCharToLCD(unsigned char data)
  {
      SET_DATA_MODE();                  // RS bit has to be 1 for data mode
      unpackAndSend(data);
  
  }
  
  // sendLCD pulse will just enable and disable the EN bit of LCD display.
  void sendLCDPulse(void)
  {
      DISABLE_LCD();
      CL_delayuS(50);
      ENABLE_LCD();
      CL_delayMS(1);
      DISABLE_LCD();
      CL_delayMS(1);
  }
  
  // writes an instruction to the LCD
  void sendLCDCommand(unsigned char inst)
  {
      SET_INSTRUCTION_MODE();
      unpackAndSend(inst);
      waitForBusyFlagToClear();
  
  }
  
  // Unpack and send data will separate two nibbles and send twice.
  void unpackAndSend(char inst)
  {
      char temp=inst;
      DISABLE_LCD();
      // SET_WRITE_MODE();               // If write is permanently disabled, do not use this.
  
      LCDPORT &amp;= (~LCD_DATA_BITS_MASK);   // Clear the data bits
      //sendLCDPulse();
      inst&amp;=0xF0;
      inst=inst&gt;&gt;4;                            // Get the upper nibble
      LCDPORT|=inst&lt;&lt;LCD_DB4;                 //Replace the bits starting from position of bit LCD_DB4 with this new data
      sendLCDPulse();
      LCDPORT &amp;= (~LCD_DATA_BITS_MASK);  // Clear the data bits again
      //sendLCDPulse();
      temp &amp;=0x0f; //send low nibble
      LCDPORT|=temp&lt;&lt;LCD_DB4;
      sendLCDPulse();
  
  }
  
  // waitForBusyFlagToClear functio can wait for the busy bit, But since we are permanently connected R/W pin to ground, we cannot read
  // the flag from LCD. In case busy bit has to be read, implementation has to be changed.
  
  void waitForBusyFlagToClear(void)
  {
      CL_delayMS(BUSY_FLAG_WAIT_TIME);
  }
  
  
  // clear display
  void clearDisplay(void)
  {
      sendLCDCommand (CLEAR_DISPLAY);
  }
  
  // return home
  void returnCursorHome(void)
  {
      sendLCDCommand (CURSOR_HOME);
  }
  
  // LCD off
  void displayOFF(void)
  {
      sendLCDCommand (DISPLAY_OFF);
  }
  
  // LCD on
  void displayONCursorOFF(void)
  {
      sendLCDCommand (CURSOR_OFF_BLINK_OFF);
  }
  
  // cursor on
  void displayONCursorON(void)
  {
      sendLCDCommand (CURSOR_ON_BLINK_OFF);
  }
  
  // blink on
  void cursorOffBlinkOn(void)
  {
      sendLCDCommand (CURSOR_OFF_BLINK_ON);
  }
  
  // blink OFF, but display and cursors are ON
  void cursorOnBlinkOff(void)
  {
      sendLCDCommand (CURSOR_ON_BLINK_OFF);
  }
  
  // All are ON
  void cursorOnBlinkOn(void)
  {
      sendLCDCommand (CURSOR_ON_BLINK_ON);
  }
  
  //go to first line
  void LCDline1 (void)
  
  {
      sendLCDCommand (0b10000000);
  }
  
  //go to second line
  void LCDline2 (void)
  
  {
      sendLCDCommand (0b11000000);
  }
  
  
  // goto position x,y
  // row1 or row2 are the parameters
  // So parameters can be 1 or 2
  void setRowAndColumnPositionOnDisplay (unsigned char rowNumber, unsigned char position)
  {
      unsigned char pos;
  
      if (rowNumber == 1)
      {
          pos = 0x00 + position;
          pos|=0x80;                  // Command to set 1st Row.
      }
  
      else //if (rowNumber == 1)     // Either row 1 or two. We cannot have else option.
      {
          pos = 0x40 + position;
          pos|=0xC0;                // Command to set second row.
      }
      sendLCDCommand (pos);
  }
  
  void displayInRow1(char* data)
  {
      sendLCDCommand(0x80);        // Set DDRAM Address as 0
      sendTextToLCD(data);
  }
  
  void displayInRow1WithPosition(char* data, unsigned char position)
  {
      // The position cannot be more than 15. Display is 16 characters (0-15).
      if(position&gt;15)
      {
          position = 15;
      }
      sendLCDCommand(0x80|position);    // Change the DDRAM address to first line by
      //  keeping D7 high and setting address to 0 onwards
      sendTextToLCD(data);
  }
  
  //////////////////////////////    diaplayInRow2   /////////////////////////////////////////////
  
  void displayInRow2(char* data)
  {
      sendLCDCommand(0xC0);     // Change the DDRAM address to next line 0x40 to 4F
      sendTextToLCD(data);
  }
  
  //////////////////////    diaplayInRow2WithPosition   //////////////////////
  
  void displayInRow2WithPosition(char* data, unsigned char position)
  {
      // The position cannot be more than 15. Display is 16 characters (0-15).
      if(position&gt;15)
      {
          position = 15;
      }
      sendLCDCommand(0xC0|position);    // Change the DDRAM address to second line by
      //keeping Bit D7 high and setting address at 0x40 onwards
      sendTextToLCD(data);
  }
  
  void scrollLcd(char *row1Data,char *row2Data)
  {
  
      while(1)
      {
          sendLCDCommand(SHIFT_CURSOR_LEFT);
          sendLCDCommand(SHIFT_ENTIRE_LEFT);
          CL_delayMS(200);
      }
  }
  
  
  //write text to the LCD
  void sendTextToLCD(char *data)
  {
      while (*data)
      {
          writeCharToLCD(*data);
          data++;
      }
  }
  
  // Function to convert lower nibble to ASCII Value
  //Only lower nibble of the input is considered and higher nibble is lost
  
  char convertLowerNibbleToASCIIValue(char data)
  {
      data&amp;=0x0F;
      if(data&lt;=9)
      {
          return(data+0x30);
      }
      else            // There is no chance for getting more than 0x0F in the lowerNibble Parameter)
      {
          return(data+0x37);
      }
  }
  
  // Function to convert Higher nibble to ASCII Value
  //Only higher nibble of the input is considered and lower nibble is lost
  char convertHigherNibbleToASCIIValue(char data)
  {
      data&gt;&gt;=4;
      if(data&lt;=9)
      {
          return(data+0x30);
      }
      else            // There is no chance for getting more than 0x0F in the lowerNibble Parameter)
      {
          return(data+0x37);
      }
  }
  
  void displayOneByteHexValue(unsigned char rowNum, unsigned char pos, char data)
  {
      char temp;
      setRowAndColumnPositionOnDisplay(rowNum,pos);
      temp = convertHigherNibbleToASCIIValue(data);
      sendTextToLCD(&amp;temp);
      temp = convertLowerNibbleToASCIIValue(data);
      sendTextToLCD(&amp;temp);
  
  }
  
  // init LCD
  
  void initializeLCD(void)
  {
      // Set the direction of port pins connected to LCD display as output ports.
      // We are permanently connecting R/W pin to ground. So there is no read instruction in this case..
      LCDDDR |= (1&lt;&lt;LCD_DB4)|(1&lt;&lt;LCD_DB5)|(1&lt;&lt;LCD_DB6)|(1&lt;&lt;LCD_DB7)|(1&lt;&lt;LCD_RS)|(1&lt;&lt;LCD_ENABLE_BIT);
  
      //After reset, data sheet suggests some delay.
      CL_delayMS(LCD_INIT_DELAY);
  
      // Note some sites says three times 8 bit mode setting commands need to be sent.
      // But it is observed that even without this, LCD works fine. So 1st Command, 2nd Command and 3rd Commands can be deleted below.
      //ENABLE_LCD();
      // 1st Command
      SET_EIGHT_BIT_MODE();
      //sendLCDPulse();    // Do not delete this. Need to further analyse. If pulse if sent it is not working
      //CL_delayMS(5);     // Do not use this delay since delay is not acurate, Either use _delay_ms or use timers
      _delay_ms(5);
  
      // Second Command
      SET_EIGHT_BIT_MODE();
      //sendLCDPulse();
      _delay_us(100);
      //CL_delayuS(100);   // Do not use this delay since delay is not acurate, Either use _delay_ms or use timers
  
      // third Command
      SET_EIGHT_BIT_MODE();
      //sendLCDPulse();
      //CL_delayuS(100);   // Do not use this delay since delay is not acurate, Either use _delay_ms or use timers
      _delay_us(37);
      // Finally Set four bit mode
      SET_FOUR_BIT_MODE();
      //sendLCDPulse();
      CL_delayuS(100);
  
      // First time when 4 bit mode command is sent, only one higher nibble was sent since
      // only 4 bits are connected from MPU to LCD. Since D0 to D3 of LCD are not connected,
      // their values depend on how the pins are connected in LCD module (May be grounded, may kept open etc)
      //So again send function set command to set 2 line display mode mode and 5x7 character mode. But now two write operations to LCD is made
      // inside the function sendLCDCommand.
      sendLCDCommand (FOUR_BIT_5_BY_10_2LINE);
  
      //turn on display and cursor OFF, Blink OFF (sent two times using below command)
      sendLCDCommand (CURSOR_OFF_BLINK_OFF);
  
      //clr display
      sendLCDCommand (CLEAR_DISPLAY);
  
      // Set Entry mode left to right
      sendLCDCommand (ENTRY_MODE_LEFT_TO_RIGHT);
  }
  
  
  
  void LCDProgramCallFromMain(char *row1Data, char *row2Data)
  {
      initializeLCD();
      setRowAndColumnPositionOnDisplay (1,0);
      sendTextToLCD (row1Data);   
      displayOneByteHexValue(2,0,0xF4);
  
      //setRowAndColumnPositionOnDisplay (2,5);
      //displayInRow1(row1Data);
  }
  
  
  int main(void)
  {
      LCDProgramCallFromMain("Hello", "Welcome to cloude");
      while(1)
      {
  
  
      }
  }
  </code></pre>
  
  <p>Below is the image of the display I am getting. Not able to makeout where the problem is.
  <img src="https://i.stack.imgur.com/3Y8Y2.jpg" alt="Result"></p>