Skip to content

Instantly share code, notes, and snippets.

@mirzakhany
Created November 16, 2016 13:22
Show Gist options
  • Select an option

  • Save mirzakhany/5a39a2337bfe1cf4ec2c30d77d4dcea1 to your computer and use it in GitHub Desktop.

Select an option

Save mirzakhany/5a39a2337bfe1cf4ec2c30d77d4dcea1 to your computer and use it in GitHub Desktop.

Revisions

  1. Mohsen created this gist Nov 16, 2016.
    303 changes: 303 additions & 0 deletions lcd.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,303 @@
    /*
    File: lcd.c
    Version: 0.1.0
    Date: Feb. 25, 2006
    C header file for HD44780 LCD module using a 74HCT164 serial in, parallel
    out out shift register to operate the LCD in 8-bit mode. Example schematic
    usuing a Powertip PC-1202A LCD available at http://www.micahcarrick.com
    Uses the avr-libc library for gcc (avr-gcc).
    ****************************************************************************
    Copyright (C) 2006 Micah Carrick <[email protected]>
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    ****************************************************************************
    */

    #include "lcd.h"
    #include <inttypes.h>
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/pgmspace.h>

    /*
    * Turns the backlight on or off. The LCD_BACKLIGHT_PIN should be defined as
    * the pin connected to the backlight control of the LCD.
    *
    * Parameters:
    * backlight_on 0=off, 1=on
    */
    void
    lcd_backlight(int backlight_on)
    {
    if (backlight_on)
    {
    /* LCD Backlight on */
    LCD_PORT |= _BV(LCD_BACKLIGHT_PIN);
    } else {
    /* LCD Backlight off */
    LCD_PORT &= ~_BV(LCD_BACKLIGHT_PIN);
    }
    }

    /*
    * Initializes the LCD. Should be called during the initialization of the
    * program.
    *
    * Parameters:
    * set_function See LCD_FUNCTION_* definitions in lcd.h
    * set_entry_mode See LCD_CMD_ENTRY_* definitions in lcd.h
    * on See LCD_CMD_ON_* definitions in lcd.h
    */
    void
    lcd_initialize(uint8_t set_function, uint8_t set_entry_mode, uint8_t on)
    {
    DDR(LCD_PORT) |=(1<<LCD_ENABLE_PIN);
    DDR(LCD_PORT) |=(1<<LCD_RSDS_PIN);
    DDR(LCD_PORT) |=(1<<LCD_CLOCK_PIN);
    DDR(LCD_PORT) |=(1<<LCD_BACKLIGHT_PIN);
    /* 20ms delay while LCD powers on */
    _delay_ms(16);

    /* Write 0x30 to LCD and wait 5 mS for the instruction to complete */
    lcd_load_byte(0x30);
    lcd_send_cmd();
    _delay_ms(5);

    /* Write 0x30 to LCD and wait 160 uS for instruction to complete */
    lcd_load_byte(0x30);
    lcd_send_cmd();
    _delay_us(120);

    /* Write 0x30 AGAIN to LCD and wait 160 uS */
    lcd_load_byte(0x30);
    lcd_send_cmd();
    _delay_us(120);

    /* Set function and wait 40uS */
    lcd_load_byte(set_function);
    lcd_send_cmd();

    /* Turn off the display and wait 40uS */
    lcd_load_byte(LCD_CMD_OFF);
    lcd_send_cmd();

    /* Clear display and wait 1.64mS */
    lcd_load_byte(LCD_CMD_CLEAR);
    lcd_send_cmd();
    _delay_ms(2);

    /* Set entry mode and wait 40uS */
    lcd_load_byte(set_entry_mode);
    lcd_send_cmd();

    /* Turn display back on and wait 40uS */
    lcd_load_byte(on);
    lcd_send_cmd();
    };

    /*
    * Loads a byte into the shift register (74'164). Does NOT load into the LCD.
    *
    * Parameters:
    * out_byte The byte to load into the '164.
    */
    void
    lcd_load_byte(uint8_t out_byte)
    {
    /* make sure clock is low */
    LCD_PORT &= ~_BV(LCD_CLOCK_PIN);

    int i;
    for(i=0; i<8; i++)
    {
    /* loop through bits */

    if (out_byte & 0x80)
    {
    /* this bit is high */
    LCD_PORT |=_BV(LCD_RSDS_PIN);
    }
    else
    {
    /* this bit is low */
    LCD_PORT &= ~_BV(LCD_RSDS_PIN);
    }
    out_byte = out_byte << 1;

    /* pulse the the shift register clock */
    LCD_PORT |= _BV(LCD_CLOCK_PIN);
    LCD_PORT &= ~_BV(LCD_CLOCK_PIN);
    }
    }

    /*
    * Loads the byte in the '164 shift register into the LCD as a command. The
    * '164 should already be loaded with the data using lcd_load_byte().
    */
    void
    lcd_send_cmd(void)
    {
    /* Data in '164 is a command, so RS must be low (0) */
    LCD_PORT &= ~_BV(LCD_RSDS_PIN);
    lcd_strobe_E();
    _delay_us(40);
    }

    /*
    * Loads the byte in the '164 shift register into the LCD as a character. The
    * '164 should already be loaded with the data using lcd_load_byte().
    */
    void
    lcd_send_char(void)
    {
    /* Data in '164 is a character, so RS must be high (1) */
    LCD_PORT |= _BV(LCD_RSDS_PIN);
    lcd_strobe_E();
    _delay_us(40);
    }

    /*
    * Loads the byte into the shift register and then sends it to the LCD as a char
    * Parameters:
    * c The byte (character) to display
    */
    void
    lcd_putc(const char c)
    {
    lcd_load_byte(c);
    lcd_send_char();
    }
    /*************************************************************************
    Display string without auto linefeed
    Input: string to be displayed
    Returns: none
    *************************************************************************/
    void lcd_puts(const char *s)
    /* print string on lcd (no auto linefeed) */
    {
    register char c;

    while ( (c = *s++) ) {
    lcd_putc(c);
    }

    }/* lcd_puts */


    /*************************************************************************
    Display string from program memory without auto linefeed
    Input: string from program memory be be displayed
    Returns: none
    *************************************************************************/
    void lcd_puts_p(const char *progmem_s)
    /* print string from program memory on lcd (no auto linefeed) */
    {
    register char c;

    while ( (c = pgm_read_byte(progmem_s++)) ) {
    lcd_putc(c);
    }

    }/* lcd_puts_p */
    /*************************************************************************
    Set cursor to specified position
    Input: x horizontal position (0: left most position)
    y vertical position (0: first line)
    Returns: none
    *************************************************************************/
    void lcd_gotoxy(uint8_t x, uint8_t y)
    {
    if ( y==0 )
    lcd_load_byte(LCD_LINE_1+x);
    else
    lcd_load_byte(LCD_LINE_2+x);

    lcd_send_cmd();
    }

    void lcd_clrscr(void){

    lcd_load_byte(1);
    lcd_send_cmd();
    }

    /*
    * Strobes the E signal on the LCD to "accept" the byte in the '164. The RS
    * line determines wheter the byte is a character or a command.
    */
    void
    lcd_strobe_E(void)
    {
    /* strobe E signal */
    LCD_PORT |= _BV(LCD_ENABLE_PIN);
    _delay_us(450);
    LCD_PORT &= ~_BV(LCD_ENABLE_PIN);
    }

    /*
    * Moves the cursor to the home position.
    */
    void
    lcd_cursor_home()
    {
    lcd_load_byte(LCD_CMD_HOME);
    lcd_send_cmd();
    }

    /*
    * Moves the cursor to the specified position.
    * Parameters:
    * line Line (row)
    * pos Position on that line (column)
    */
    void
    lcd_move_cursor(uint8_t line, uint8_t pos)
    {
    lcd_load_byte(line+pos);
    lcd_send_cmd();
    }

    /*
    * Moves the cursor a number of spaces to the right
    * Parameters:
    * spaces Number of spaces to move
    */
    void
    lcd_inc_cursor(uint8_t spaces)
    {
    while (spaces--)
    {
    lcd_load_byte(LCD_CMD_CURSOR_RIGHT);
    lcd_send_cmd();
    }
    }

    /*
    * Moves the cursor a number of spaces to the left
    * Parameters:
    * spaces Number of spaces to move
    */
    void
    lcd_dec_cursor(uint8_t spaces)
    {
    while (spaces--)
    {
    lcd_load_byte(LCD_CMD_CURSOR_LEFT);
    lcd_send_cmd();
    }
    }
    94 changes: 94 additions & 0 deletions lcd.h
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,94 @@
    /*
    File: lcd.h
    Version: 0.1.0
    Date: Feb. 25, 2006
    C header file for HD44780 LCD module using a 74HCT164 serial in, parallel
    out out shift register to operate the LCD in 8-bit mode. Example schematic
    usuing a Powertip PC-1202A LCD available at http://www.micahcarrick.com
    Uses the avr-libc library for gcc (avr-gcc).
    ****************************************************************************
    Copyright (C) 2006 Micah Carrick <[email protected]>
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    ****************************************************************************
    */
    #ifndef _LCD_H
    #define _LCD_H

    #include <inttypes.h>

    /* AVR port and pins connected to '164 and/or LCD */
    #define LCD_PORT PORTD
    #define LCD_ENABLE_PIN 4
    #define LCD_RSDS_PIN 5
    #define LCD_CLOCK_PIN 6
    #define LCD_BACKLIGHT_PIN 7

    /* number of columns on the display */
    #define LCD_COLS 16
    #define LCD_LINES 2

    /* LCD commands */
    #define LCD_CLR 0x00
    #define LCD_CMD_HOME 0x02 /* cursor home */
    #define LCD_CMD_ENTRY_DEC 0x04 /* decrement, no shift */
    #define LCD_CMD_ENTRY_DEC_SHIFT 0x05 /* decrement with shift */
    #define LCD_CMD_ENTRY_INC 0x06 /* increment, no shift */
    #define LCD_CMD_ENTRY_INC_SHIFT 0x07 /* increment with shift */
    #define LCD_CMD_CLEAR 0x01 /* clear, cursor home */
    #define LCD_CMD_OFF 0x08 /* display off */
    #define LCD_CMD_ON 0x0C /* display on, cursor off */
    #define LCD_CMD_ON_BLINK 0x0D /* display on, cursor off, blink char */
    #define LCD_CMD_ON_CURSOR 0x0E /* display on, cursor on */
    #define LCD_CMD_ON_CURSOR_BLINK 0x0F /* display on, cursor on, blink char */
    #define LCD_CMD_CURSOR_LEFT 0x10 /* decrement cursor (left) */
    #define LCD_CMD_CURSOR_RIGHT 0x14 /* increment cursor (right) */
    #define LCD_CMD_SHIFT_LEFT 0x18 /* shift (left) */
    #define LCD_CMD_SHIFT_RIGHT 0x1C /* shift (right)*/

    #define LCD_LINE_1 0x80 /* bit 7 is always set: 0x80 = 0x00 */
    #define LCD_LINE_2 0xC0 /* 2nd line at position 40 */

    /* function set: (always 8-bit with the shift-register circuit I'm using */
    #define LCD_FUNCTION_8x1 0x30 /* 5x7 characters, single line display */
    #define LCD_FUNCTION_8x2 0x38 /* 5x7 characters, 2 line display */

    /* F_CPU is used by delay routines from util/delay.h. May already be defined */
    #ifndef F_CPU
    #define F_CPU 8000000UL /* 8 MHz CPU clock */
    #endif

    #define DDR(x) (*(&x - 1))
    /* functions */
    void lcd_backlight(int);
    void lcd_initialize(uint8_t, uint8_t, uint8_t);
    void lcd_load_byte(uint8_t);
    void lcd_send_cmd(void);
    void lcd_send_char(void);
    void lcd_strobe_E(void);
    void lcd_cursor_home();
    void lcd_move_cursor(uint8_t, uint8_t);
    void lcd_inc_cursor(uint8_t);
    void lcd_dec_cursor(uint8_t);
    void lcd_clrscr(void);
    void lcd_putc(const char c);
    void lcd_puts(const char *s);
    void lcd_puts_p(const char *progmem_s);
    void lcd_gotoxy(uint8_t x, uint8_t y);

    #endif
    24 changes: 24 additions & 0 deletions main.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,24 @@
    #include <avr/io.h>
    #include <util/delay.h>
    #include "lcd.h"

    int main(void){
    //DDRD=0xF0;

    lcd_initialize(LCD_FUNCTION_8x2, LCD_CMD_ENTRY_INC, LCD_CMD_ON);

    lcd_puts("hello word !");
    lcd_gotoxy(0,1);
    lcd_puts("serial lcd lib");

    _delay_ms(700);
    lcd_clrscr();
    lcd_puts("bym");
    lcd_gotoxy(0,1);
    lcd_puts("www.ellab.ir");

    while(1){

    }
    return 0;
    }