Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

Atmega8, LCD EA DIP204-4 , C

Rafał_ 25 Aug 2010 15:39 2522 13
  • #1
    Rafał_
    Level 10  
    Witam wszystkich , mam problem z obsługą wyświetlacza LED EA DIP204-4NLED :

    http://www.lcd-module.de/eng/pdf/doma/dip204-4e.pdf

    Po podłączeniu go pod uP Atmega8 i wgraniu oprogramowania ze strony pana Radosława http://radzio.dxp.p mam czarne krateczki i nie wiem czym to jest spowodowane :/ Nie jestem orłem jeśli chodzi o programowanie dlatego proszę o pomoc , co sprawdzić , gdzie może być błąd ... z góry thx za pomoc ;)

    a o to kod :

    Code:
    //-------------------------------------------------------------------------------------------------
    
    // Wyświetlacz alfanumeryczny ze sterownikiem HD44780
    // Sterowanie w trybie 4-bitowym bez odczytu flagi zajętości
    // z dowolnym przypisaniem sygnałów sterujących
    // Plik : HD44780.c   
    // Mikrokontroler : Atmel AVR
    // Kompilator : avr-gcc
    // Autor : Radosław Kwiecień
    // Źródło : http://radzio.dxp.pl/hd44780/
    // Data : 24.03.2007
    //-------------------------------------------------------------------------------------------------

    #include "HD44780.h"
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja wystawiająca półbajt na magistralę danych
    //
    //-------------------------------------------------------------------------------------------------
    void _LCD_OutNibble(unsigned char nibbleToWrite)
    {
    if(nibbleToWrite & 0x01)
       LCD_DB4_PORT |= LCD_DB4;
    else
       LCD_DB4_PORT  &= ~LCD_DB4;

    if(nibbleToWrite & 0x02)
       LCD_DB5_PORT |= LCD_DB5;
    else
       LCD_DB5_PORT  &= ~LCD_DB5;

    if(nibbleToWrite & 0x04)
       LCD_DB6_PORT |= LCD_DB6;
    else
       LCD_DB6_PORT  &= ~LCD_DB6;

    if(nibbleToWrite & 0x08)
       LCD_DB7_PORT |= LCD_DB7;
    else
       LCD_DB7_PORT  &= ~LCD_DB7;
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja zapisu bajtu do wyświetacza (bez rozróżnienia instrukcja/dane).
    //
    //-------------------------------------------------------------------------------------------------
    void _LCD_Write(unsigned char dataToWrite)
    {
    LCD_E_PORT |= LCD_E;
    _LCD_OutNibble(dataToWrite >> 4);
    LCD_E_PORT &= ~LCD_E;
    LCD_E_PORT |= LCD_E;
    _LCD_OutNibble(dataToWrite);
    LCD_E_PORT &= ~LCD_E;
    _delay_us(50);
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja zapisu rozkazu do wyświetlacza
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_WriteCommand(unsigned char commandToWrite)
    {
    LCD_RS_PORT &= ~LCD_RS;
    _LCD_Write(commandToWrite);
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja zapisu danych do pamięci wyświetlacza
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_WriteData(unsigned char dataToWrite)
    {
    LCD_RS_PORT |= LCD_RS;
    _LCD_Write(dataToWrite);
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja wyświetlenia napisu na wyswietlaczu.
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_WriteText(char * text)
    {
    while(*text)
      LCD_WriteData(*text++);
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja ustawienia współrzędnych ekranowych
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_GoTo(unsigned char x, unsigned char y)
    {
    LCD_WriteCommand(HD44780_DDRAM_SET | (x + (0x40 * y)));
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja czyszczenia ekranu wyświetlacza.
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_Clear(void)
    {
    LCD_WriteCommand(HD44780_CLEAR);
    _delay_ms(2);
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja przywrócenia początkowych współrzędnych wyświetlacza.
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_Home(void)
    {
    LCD_WriteCommand(HD44780_HOME);
    _delay_ms(2);
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Procedura inicjalizacji kontrolera HD44780.
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_Initalize(void)
    {
    unsigned char i;
    LCD_DB4_DIR |= LCD_DB4; // Konfiguracja kierunku pracy wyprowadzeń
    LCD_DB5_DIR |= LCD_DB5; //
    LCD_DB6_DIR |= LCD_DB6; //
    LCD_DB7_DIR |= LCD_DB7; //
    LCD_E_DIR    |= LCD_E;   //
    LCD_RS_DIR    |= LCD_RS;  //
    _delay_ms(15); // oczekiwanie na ustalibizowanie się napiecia zasilajacego
    LCD_RS_PORT &= ~LCD_RS; // wyzerowanie linii RS
    LCD_E_PORT &= ~LCD_E;  // wyzerowanie linii E

    for(i = 0; i < 3; i++) // trzykrotne powtórzenie bloku instrukcji
      {
      LCD_E_PORT |= LCD_E; //  E = 1
      _LCD_OutNibble(0x03); // tryb 8-bitowy
      LCD_E_PORT &= ~LCD_E; // E = 0
      _delay_ms(5); // czekaj 5ms
      }

    LCD_E_PORT |= LCD_E; // E = 1
    _LCD_OutNibble(0x02); // tryb 4-bitowy
    LCD_E_PORT &= ~LCD_E; // E = 0

    _delay_ms(1); // czekaj 1ms
    LCD_WriteCommand(HD44780_FUNCTION_SET | HD44780_FONT5x7 | HD44780_TWO_LINE | HD44780_4_BIT); // interfejs 4-bity, 2-linie, znak 5x7
    LCD_WriteCommand(HD44780_DISPLAY_ONOFF | HD44780_DISPLAY_OFF); // wyłączenie wyswietlacza
    LCD_WriteCommand(HD44780_CLEAR); // czyszczenie zawartosći pamieci DDRAM
    _delay_ms(2);
    LCD_WriteCommand(HD44780_ENTRY_MODE | HD44780_EM_SHIFT_CURSOR | HD44780_EM_INCREMENT);// inkrementaja adresu i przesuwanie kursora
    LCD_WriteCommand(HD44780_DISPLAY_ONOFF | HD44780_DISPLAY_ON | HD44780_CURSOR_OFF | HD44780_CURSOR_NOBLINK); // włącz LCD, bez kursora i mrugania
    }



    //-------------------------------------------------------------------------------------------------
    //
    // Koniec pliku HD44780.c
    //
    //-------------------------------------------------------------------------------------------------

    Code:
    //-------------------------------------------------------------------------------------------------
    
    // Wyświetlacz alfanumeryczny ze sterownikiem HD44780
    // Sterowanie w trybie 4-bitowym bez odczytu flagi zajętości
    // z dowolnym przypisaniem sygnałów sterujących
    // Plik : HD44780.c   
    // Mikrokontroler : Atmel AVR
    // Kompilator : avr-gcc
    // Autor : Radosław Kwiecień
    // Źródło : http://radzio.dxp.pl/hd44780/
    // Data : 24.03.2007
    //-------------------------------------------------------------------------------------------------

    #include "HD44780.h"
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja wystawiająca półbajt na magistralę danych
    //
    //-------------------------------------------------------------------------------------------------
    void _LCD_OutNibble(unsigned char nibbleToWrite)
    {
    if(nibbleToWrite & 0x01)
       LCD_DB4_PORT |= LCD_DB4;
    else
       LCD_DB4_PORT  &= ~LCD_DB4;

    if(nibbleToWrite & 0x02)
       LCD_DB5_PORT |= LCD_DB5;
    else
       LCD_DB5_PORT  &= ~LCD_DB5;

    if(nibbleToWrite & 0x04)
       LCD_DB6_PORT |= LCD_DB6;
    else
       LCD_DB6_PORT  &= ~LCD_DB6;

    if(nibbleToWrite & 0x08)
       LCD_DB7_PORT |= LCD_DB7;
    else
       LCD_DB7_PORT  &= ~LCD_DB7;
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja zapisu bajtu do wyświetacza (bez rozróżnienia instrukcja/dane).
    //
    //-------------------------------------------------------------------------------------------------
    void _LCD_Write(unsigned char dataToWrite)
    {
    LCD_E_PORT |= LCD_E;
    _LCD_OutNibble(dataToWrite >> 4);
    LCD_E_PORT &= ~LCD_E;
    LCD_E_PORT |= LCD_E;
    _LCD_OutNibble(dataToWrite);
    LCD_E_PORT &= ~LCD_E;
    _delay_us(50);
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja zapisu rozkazu do wyświetlacza
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_WriteCommand(unsigned char commandToWrite)
    {
    LCD_RS_PORT &= ~LCD_RS;
    _LCD_Write(commandToWrite);
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja zapisu danych do pamięci wyświetlacza
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_WriteData(unsigned char dataToWrite)
    {
    LCD_RS_PORT |= LCD_RS;
    _LCD_Write(dataToWrite);
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja wyświetlenia napisu na wyswietlaczu.
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_WriteText(char * text)
    {
    while(*text)
      LCD_WriteData(*text++);
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja ustawienia współrzędnych ekranowych
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_GoTo(unsigned char x, unsigned char y)
    {
    LCD_WriteCommand(HD44780_DDRAM_SET | (x + (0x40 * y)));
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja czyszczenia ekranu wyświetlacza.
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_Clear(void)
    {
    LCD_WriteCommand(HD44780_CLEAR);
    _delay_ms(2);
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja przywrócenia początkowych współrzędnych wyświetlacza.
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_Home(void)
    {
    LCD_WriteCommand(HD44780_HOME);
    _delay_ms(2);
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Procedura inicjalizacji kontrolera HD44780.
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_Initalize(void)
    {
    unsigned char i;
    LCD_DB4_DIR |= LCD_DB4; // Konfiguracja kierunku pracy wyprowadzeń
    LCD_DB5_DIR |= LCD_DB5; //
    LCD_DB6_DIR |= LCD_DB6; //
    LCD_DB7_DIR |= LCD_DB7; //
    LCD_E_DIR    |= LCD_E;   //
    LCD_RS_DIR    |= LCD_RS;  //
    _delay_ms(15); // oczekiwanie na ustalibizowanie się napiecia zasilajacego
    LCD_RS_PORT &= ~LCD_RS; // wyzerowanie linii RS
    LCD_E_PORT &= ~LCD_E;  // wyzerowanie linii E

    for(i = 0; i < 3; i++) // trzykrotne powtórzenie bloku instrukcji
      {
      LCD_E_PORT |= LCD_E; //  E = 1
      _LCD_OutNibble(0x03); // tryb 8-bitowy
      LCD_E_PORT &= ~LCD_E; // E = 0
      _delay_ms(5); // czekaj 5ms
      }

    LCD_E_PORT |= LCD_E; // E = 1
    _LCD_OutNibble(0x02); // tryb 4-bitowy
    LCD_E_PORT &= ~LCD_E; // E = 0

    _delay_ms(1); // czekaj 1ms
    LCD_WriteCommand(HD44780_FUNCTION_SET | HD44780_FONT5x7 | HD44780_TWO_LINE | HD44780_4_BIT); // interfejs 4-bity, 2-linie, znak 5x7
    LCD_WriteCommand(HD44780_DISPLAY_ONOFF | HD44780_DISPLAY_OFF); // wyłączenie wyswietlacza
    LCD_WriteCommand(HD44780_CLEAR); // czyszczenie zawartosći pamieci DDRAM
    _delay_ms(2);
    LCD_WriteCommand(HD44780_ENTRY_MODE | HD44780_EM_SHIFT_CURSOR | HD44780_EM_INCREMENT);// inkrementaja adresu i przesuwanie kursora
    LCD_WriteCommand(HD44780_DISPLAY_ONOFF | HD44780_DISPLAY_ON | HD44780_CURSOR_OFF | HD44780_CURSOR_NOBLINK); // włącz LCD, bez kursora i mrugania
    }

    //-------------------------------------------------------------------------------------------------
    //
    // Koniec pliku HD44780.c
    //
    //-------------------------------------------------------------------------------------------------

    Code:
    #include <avr/io.h>
    
    #include "HD44780.h"
    #include <avr/signal.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>



    int main(void)
    {


    void LCD_Initalize(void);
    void LCD_Home(void);
    void LCD_Clear(void);

    while(1)
    {


    LCD_WriteText("sialalalala");
    _delay_ms(1000);
     
    }
     
     
     
     return 0;
    }
  • #2
    tadzik85
    Level 38  
    podłączyłeś go 4-bitową szyna danych r/w do masy?
  • #3
    Rafał_
    Level 10  
    tak

    r/w do masy
    RS - PD2
    E - PD3

    i szynę danych
    DB4 - PD4
    DB5 - PD5
    DB6 - PD6
    DB7 - PD7
  • #4
    tadzik85
    Level 38  
    Nie inicjujesz wyświetlacza teraz zauważyłem. W main zamiast wywoływać funkcje deklarujesz je ponownie.

    Czarne kwadraty sygnalizują ze wyświetlacz nie jest zainicjowany.
  • #5
    Rafał_
    Level 10  
    poprawiłem , przeprogramowałem i dalej nic ;/ podłączyłem sobie kontrast wyświetlacz pod 5 V mogę tak zrobić ? czy muszę zrobić jakiś dzielnik rezystorowy ?
  • #6
    tadzik85
    Level 38  
    Najlepiej potencjometr. W każdym egzemplarzu kontrast kontrastowi nie równy
  • #7
    Rafał_
    Level 10  
    ok to zrobię dzielnik napięcia , dzięki wielkie za pomoc , posiedzę nad tym jeszcze , gdyby ktoś zauważył jakiś błąd będę wdzięczny ... pozdrawiam
  • #8
    janbernat
    Level 38  
    A w pliku nagłówkowym do wyświetlacza jest coś takiego:
    Code:

    // Konfiguracja sygnałów sterujących wyświetlaczem.
    // Można zmienić stosownie do potrzeb.
    //
    //-------------------------------------------------------------------------------------------------
    #define LCD_RS_DIR      DDRD
    #define LCD_RS_PORT    PORTD
    #define LCD_RS_PIN      PIND
    #define LCD_RS         (1 << PD0)

    #define LCD_RW_DIR      DDRD
    #define LCD_RW_PORT      PORTD
    #define LCD_RW_PIN      PIND
    #define LCD_RW         (1 << PD6)

    #define LCD_E_DIR      DDRD
    #define LCD_E_PORT      PORTD
    #define LCD_E_PIN      PIND
    #define LCD_E         (1 << PD1)

    #define LCD_DB4_DIR      DDRD
    #define LCD_DB4_PORT   PORTD
    #define LCD_DB4_PIN      PIND
    #define LCD_DB4         (1 << PD2)

    #define LCD_DB5_DIR      DDRD
    #define LCD_DB5_PORT   PORTD
    #define LCD_DB5_PIN      PIND
    #define LCD_DB5         (1 << PD3)

    #define LCD_DB6_DIR      DDRD
    #define LCD_DB6_PORT   PORTD
    #define LCD_DB6_PIN      PIND
    #define LCD_DB6         (1 << PD4)

    #define LCD_DB7_DIR      DDRD
    #define LCD_DB7_PORT   PORTD
    #define LCD_DB7_PIN      PIND
    #define LCD_DB7         (1 << PD5)

    Oczywiście to są moje ustawienia- a w Twoim pliku powinny być inne.
  • #9
    Rafał_
    Level 10  
    u mnie niby są takie ustawienia
    Code:
    //-------------------------------------------------------------------------------------------------
    
    // Wyświetlacz alfanumeryczny ze sterownikiem HD44780
    // Sterowanie w trybie 4-bitowym bez odczytu flagi zajętości
    // z dowolnym przypisaniem sygnałów sterujących
    // Plik : HD44780.h   
    // Mikrokontroler : Atmel AVR
    // Kompilator : avr-gcc
    // Autor : Radosław Kwiecień
    // Źródło : http://radzio.dxp.pl/hd44780/
    // Data : 24.03.2007
    //-------------------------------------------------------------------------------------------------

    #include <avr/io.h>
    #include <util/delay.h>

    //-------------------------------------------------------------------------------------------------
    //
    // Konfiguracja sygnałów sterujących wyświetlaczem.
    // Można zmienić stosownie do potrzeb.
    //
    //-------------------------------------------------------------------------------------------------
    #define LCD_RS_DIR      DDRD
    #define LCD_RS_PORT    PORTD
    #define LCD_RS         (1 << PD2)

    #define LCD_E_DIR      DDRD
    #define LCD_E_PORT      PORTD
    #define LCD_E         (1 << PD3)

    #define LCD_DB4_DIR      DDRD
    #define LCD_DB4_PORT   PORTD
    #define LCD_DB4         (1 << PD4)

    #define LCD_DB5_DIR      DDRD
    #define LCD_DB5_PORT   PORTD
    #define LCD_DB5         (1 << PD5)

    #define LCD_DB6_DIR      DDRD
    #define LCD_DB6_PORT   PORTD
    #define LCD_DB6         (1 << PD6)

    #define LCD_DB7_DIR      DDRD
    #define LCD_DB7_PORT   PORTD
    #define LCD_DB7         (1 << PD7)

    //-------------------------------------------------------------------------------------------------
    //
    // Instrukcje kontrolera Hitachi HD44780
    //
    //-------------------------------------------------------------------------------------------------

    #define HD44780_CLEAR               0x01

    #define HD44780_HOME               0x02

    #define HD44780_ENTRY_MODE            0x04
       #define HD44780_EM_SHIFT_CURSOR      0
       #define HD44780_EM_SHIFT_DISPLAY   1
       #define HD44780_EM_DECREMENT      0
       #define HD44780_EM_INCREMENT      2

    #define HD44780_DISPLAY_ONOFF         0x08
       #define HD44780_DISPLAY_OFF         0
       #define HD44780_DISPLAY_ON         4
       #define HD44780_CURSOR_OFF         0
       #define HD44780_CURSOR_ON         2
       #define HD44780_CURSOR_NOBLINK      0
       #define HD44780_CURSOR_BLINK      1

    #define HD44780_DISPLAY_CURSOR_SHIFT   0x10
       #define HD44780_SHIFT_CURSOR      0
       #define HD44780_SHIFT_DISPLAY      8
       #define HD44780_SHIFT_LEFT         0
       #define HD44780_SHIFT_RIGHT         4

    #define HD44780_FUNCTION_SET         0x20
       #define HD44780_FONT5x7            0
       #define HD44780_FONT5x10         4
       #define HD44780_ONE_LINE         0
       #define HD44780_TWO_LINE         8
       #define HD44780_4_BIT            0
       #define HD44780_8_BIT            16

    #define HD44780_CGRAM_SET            0x40

    #define HD44780_DDRAM_SET            0x80

    //-------------------------------------------------------------------------------------------------
    //
    // Deklaracje funkcji
    //
    //-------------------------------------------------------------------------------------------------

    void LCD_WriteCommand(unsigned char);
    void LCD_WriteData(unsigned char);
    void LCD_WriteText(char *);
    void LCD_GoTo(unsigned char, unsigned char);
    void LCD_Clear(void);
    void LCD_Home(void);
    void LCD_Initalize(void);

    //-------------------------------------------------------------------------------------------------
    //
    // Koniec pliku HD44780.h
    //
    //-------------------------------------------------------------------------------------------------


    Mam pytanie czy taktowanie procesora będzie miało w tym wypadku znaczenie , nie mam podpiętego zewnętrznego kwarcu ...

    hm i podświetlony jest pierwszy segment wyświetlacza tj ( 1 x 1 ) mruga sobie ... a napisu jak nie było tak nie ma :/
  • #10
    Rafał_
    Level 10  
    Witam , udało mi się odpalić wyświetlacz , użyłem innych bibliotek - pana Peter Fleury . Pojawił sie jednak kolejny problem , biblioteka jest do wyswietlacza 2x16 a ja chciałem ją przerobić na 4x20 i tu pojawia sie problem :

    - pierwsza linia wyświetla się ok
    - druga linia , pierwsze 8 znaków drugiej linii jest dublowane z linii pierwszej ( 8 ostatnich znaków), kolejne 12 jest ok .
    -trzecia linia działa ok
    - czwarta linia ,pierwsze 8 znaków czwartej linii jest dublowane z linii trzeciej ( 8 ostatnich znaków), kolejne 12 jest ok .

    najlepiej pokaże przykład :

    lcd_puts("abcdefghijklmnopqrstuvwxyz1234567890zwytrewxsdiuiuottttaaaaaaa");

    na wyświetlaczu wyświetla się :
    ______________________________
    a b c d e f g h i j k l m n o p q r s t
    m n o p q r s t u v w x y z 1 2 3 4 5 6
    r e w x s d i u i u o t t t t a a a a a
    ______________________________
    a o to biblioteki
    Code:
    #ifndef LCD_H
    
    #define LCD_H
    /*************************************************************************
     Title   :   C include file for the HD44780U LCD library (lcd.c)
     Author:    Peter Fleury <pfleury@gmx.ch>  http://jump.to/fleury
     File:       $Id: lcd.h,v 1.12.2.4 2005/02/28 22:54:41 Peter Exp $
     Software:  AVR-GCC 3.3
     Hardware:  any AVR device, memory mapped mode only for AT90S4414/8515/Mega
    ***************************************************************************/

    /**
     @defgroup pfleury_lcd LCD library
     @code #include <lcd.h> @endcode
     
     @brief Basic routines for interfacing a HD44780U-based text LCD display

     Originally based on Volker Oth's LCD library,
     changed lcd_init(), added additional constants for lcd_command(),
     added 4-bit I/O mode, improved and optimized code.
           
     Library can be operated in memory mapped mode (LCD_IO_MODE=0) or in
     4-bit IO port mode (LCD_IO_MODE=1). 8-bit IO port mode not supported.

     Memory mapped mode compatible with Kanda STK200, but supports also
     generation of R/W signal through A8 address line.
           
     @author Peter Fleury pfleury(malpa)gmx.ch http://jump.to/fleury
     
     @see The chapter <a href="http://homepage.sunrise.ch/mysunrise/peterfleury/avr-lcd44780.html" target="_blank">Interfacing a HD44780 Based LCD to an AVR</a>
          on my home page.

    */

    /*@{*/

    #if (__GNUC__ * 100 + __GNUC_MINOR__) < 303
    #error "This library requires AVR-GCC 3.3 or later, update to newer AVR-GCC compiler !"
    #endif

    #include <inttypes.h>
    #include <avr/pgmspace.h>

    /**
     *  @name  Definitions for MCU Clock Frequency
     *  Adapt the MCU clock frequency in Hz to your target.
     */
    #define XTAL 8000000              /**< clock frequency in Hz, used to calculate delay timer */

    /**
     *  @name  Definitions for Display Size
     *  Change these definitions to adapt setting to your display
     */



    #define LCD_LINES           4     /**< number of visible lines of the display */
    #define LCD_DISP_LENGTH    20     /**< visibles characters per line of the display */
    #define LCD_LINE_LENGTH  0x40     /**< internal line length of the display    */
    #define LCD_START_LINE1  0x00     /**< DDRAM address of first char of line 1 */
    #define LCD_START_LINE2  0x20     /**< DDRAM address of first char of line 2 */
    #define LCD_START_LINE3  0x40     /**< DDRAM address of first char of line 3 */
    #define LCD_START_LINE4  0x60     /**< DDRAM address of first char of line 4 */
    #define LCD_WRAP_LINES      1     /**< 0: no wrap, 1: wrap at end of visibile line */


    #define LCD_IO_MODE      1         /**< 0: memory mapped mode, 1: IO port mode */
    #if LCD_IO_MODE
    /**
     *  @name Definitions for 4-bit IO mode
     *  Change LCD_PORT if you want to use a different port for the LCD pins.
     *
     *  The four LCD data lines and the three control lines RS, RW, E can be on the
     *  same port or on different ports.
     *  Change LCD_RS_PORT, LCD_RW_PORT, LCD_E_PORT if you want the control lines on
     *  different ports.
     *
     *  Normally the four data lines should be mapped to bit 0..3 on one port, but it
     *  is possible to connect these data lines in different order or even on different
     *  ports by adapting the LCD_DATAx_PORT and LCD_DATAx_PIN definitions.
     * 
     */
    #define LCD_PORT         PORTD        /**< port for the LCD lines   */
    #define LCD_DATA0_PORT   LCD_PORT     /**< port for 4bit data bit 0 */
    #define LCD_DATA1_PORT   LCD_PORT     /**< port for 4bit data bit 1 */
    #define LCD_DATA2_PORT   LCD_PORT     /**< port for 4bit data bit 2 */
    #define LCD_DATA3_PORT   LCD_PORT     /**< port for 4bit data bit 3 */
    #define LCD_DATA0_PIN    4           /**< pin for 4bit data bit 0  */
    #define LCD_DATA1_PIN    5            /**< pin for 4bit data bit 1  */
    #define LCD_DATA2_PIN    6           /**< pin for 4bit data bit 2  */
    #define LCD_DATA3_PIN    7           /**< pin for 4bit data bit 3  */
    #define LCD_RS_PORT      LCD_PORT     /**< port for RS line         */
    #define LCD_RS_PIN       1            /**< pin  for RS line         */
    #define LCD_RW_PORT      LCD_PORT     /**< port for RW line         */
    #define LCD_RW_PIN       2            /**< pin  for RW line         */
    #define LCD_E_PORT       LCD_PORT     /**< port for Enable line     */
    #define LCD_E_PIN        3            /**< pin  for Enable line     */

    #elif defined(__AVR_AT90S4414__) || defined(__AVR_AT90S8515__) || defined(__AVR_ATmega64__) || \
          defined(__AVR_ATmega8515__)|| defined(__AVR_ATmega103__) || defined(__AVR_ATmega128__) || \
          defined(__AVR_ATmega161__) || defined(__AVR_ATmega162__)
    /*
     *  memory mapped mode is only supported when the device has an external data memory interface
     */
    #define LCD_IO_DATA      0xC000    /* A15=E=1, A14=RS=1                 */
    #define LCD_IO_FUNCTION  0x8000    /* A15=E=1, A14=RS=0                 */
    #define LCD_IO_READ      0x0100    /* A8 =R/W=1 (R/W: 1=Read, 0=Write   */
    #else
    #error "external data memory interface not available for this device, use 4-bit IO port mode"

    #endif


    /**
     *  @name Definitions for LCD command instructions
     *  The constants define the various LCD controller instructions which can be passed to the
     *  function lcd_command(), see HD44780 data sheet for a complete description.
     */

    /* instruction register bit positions, see HD44780U data sheet */
    #define LCD_CLR               0      /* DB0: clear display                  */
    #define LCD_HOME              1      /* DB1: return to home position        */
    #define LCD_ENTRY_MODE        2      /* DB2: set entry mode                 */
    #define LCD_ENTRY_INC         1      /*   DB1: 1=increment, 0=decrement     */
    #define LCD_ENTRY_SHIFT       0      /*   DB2: 1=display shift on           */
    #define LCD_ON                3      /* DB3: turn lcd/cursor on             */
    #define LCD_ON_DISPLAY        2      /*   DB2: turn display on              */
    #define LCD_ON_CURSOR         1      /*   DB1: turn cursor on               */
    #define LCD_ON_BLINK          0      /*     DB0: blinking cursor ?          */
    #define LCD_MOVE              4      /* DB4: move cursor/display            */
    #define LCD_MOVE_DISP         3      /*   DB3: move display (0-> cursor) ?  */
    #define LCD_MOVE_RIGHT        2      /*   DB2: move right (0-> left) ?      */
    #define LCD_FUNCTION          5      /* DB5: function set                   */
    #define LCD_FUNCTION_8BIT     4      /*   DB4: set 8BIT mode (0->4BIT mode) */
    #define LCD_FUNCTION_2LINES   3      /*   DB3: two lines (0->one line)      */
    #define LCD_FUNCTION_10DOTS   2      /*   DB2: 5x10 font (0->5x7 font)      */
    #define LCD_CGRAM             6      /* DB6: set CG RAM address             */
    #define LCD_DDRAM             7      /* DB7: set DD RAM address             */
    #define LCD_BUSY              7      /* DB7: LCD is busy                    */

    /* set entry mode: display shift on/off, dec/inc cursor move direction */
    #define LCD_ENTRY_DEC            0x04   /* display shift off, dec cursor move dir */
    #define LCD_ENTRY_DEC_SHIFT      0x05   /* display shift on,  dec cursor move dir */
    #define LCD_ENTRY_INC_           0x06   /* display shift off, inc cursor move dir */
    #define LCD_ENTRY_INC_SHIFT      0x07   /* display shift on,  inc cursor move dir */

    /* display on/off, cursor on/off, blinking char at cursor position */
    #define LCD_DISP_OFF             0x08   /* display off                            */
    #define LCD_DISP_ON              0x0C   /* display on, cursor off                 */
    #define LCD_DISP_ON_BLINK        0x0D   /* display on, cursor off, blink char     */
    #define LCD_DISP_ON_CURSOR       0x0E   /* display on, cursor on                  */
    #define LCD_DISP_ON_CURSOR_BLINK 0x0F   /* display on, cursor on, blink char      */

    /* move cursor/shift display */
    #define LCD_MOVE_CURSOR_LEFT     0x10   /* move cursor left  (decrement)          */
    #define LCD_MOVE_CURSOR_RIGHT    0x14   /* move cursor right (increment)          */
    #define LCD_MOVE_DISP_LEFT       0x18   /* shift display left                     */
    #define LCD_MOVE_DISP_RIGHT      0x1C   /* shift display right                    */

    /* function set: set interface data length and number of display lines */
    #define LCD_FUNCTION_4BIT_1LINE  0x20   /* 4-bit interface, single line, 5x7 dots */
    #define LCD_FUNCTION_4BIT_2LINES 0x28   /* 4-bit interface, dual line,   5x7 dots */
    #define LCD_FUNCTION_8BIT_1LINE  0x30   /* 8-bit interface, single line, 5x7 dots */
    #define LCD_FUNCTION_8BIT_2LINES 0x38   /* 8-bit interface, dual line,   5x7 dots */


    #define LCD_MODE_DEFAULT     ((1<<LCD_ENTRY_MODE) | (1<<LCD_ENTRY_INC) )



    /**
     *  @name Functions
     */


    /**
     @brief    Initialize display and select type of cursor
     @param    dispAttr \b LCD_DISP_OFF display off\n
                        \b LCD_DISP_ON display on, cursor off\n
                        \b LCD_DISP_ON_CURSOR display on, cursor on\n
                        \b LCD_DISP_ON_CURSOR_BLINK display on, cursor on flashing             
     @return  none
    */
    extern void lcd_init(uint8_t dispAttr);


    /**
     @brief    Clear display and set cursor to home position
     @param    void                                       
     @return   none
    */
    extern void lcd_clrscr(void);


    /**
     @brief    Set cursor to home position
     @param    void                                       
     @return   none
    */
    extern void lcd_home(void);


    /**
     @brief    Set cursor to specified position
     
     @param    x horizontal position\n (0: left most position)
     @param    y vertical position\n   (0: first line)
     @return   none
    */
    extern void lcd_gotoxy(uint8_t x, uint8_t y);


    /**
     @brief    Display character at current cursor position
     @param    c character to be displayed                                       
     @return   none
    */
    extern void lcd_putc(char c);


    /**
     @brief    Display string without auto linefeed
     @param    s string to be displayed                                       
     @return   none
    */
    extern void lcd_puts(const char *s);


    /**
     @brief    Display string from program memory without auto linefeed
     @param    s string from program memory be be displayed                                       
     @return   none
     @see      lcd_puts_P
    */
    extern void lcd_puts_p(const char *progmem_s);


    /**
     @brief    Send LCD controller instruction command
     @param    cmd instruction to send to LCD controller, see HD44780 data sheet
     @return   none
    */
    extern void lcd_command(uint8_t cmd);


    /**
     @brief    Send data byte to LCD controller
     
     Similar to lcd_putc(), but without interpreting LF
     @param    data byte to send to LCD controller, see HD44780 data sheet
     @return   none
    */
    extern void lcd_data(uint8_t data);


    /**
     @brief macros for automatically storing string constant in program memory
    */
    #define lcd_puts_P(__s)         lcd_puts_p(PSTR(__s))

    /*@}*/
    #endif //LCD_H


    lcd.c
    Code:
    /****************************************************************************
    
     Title   :   HD44780U LCD library
     Author:    Peter Fleury <pfleury@gmx.ch>  http://jump.to/fleury
     File:       $Id: lcd.c,v 1.13.2.5 2005/02/16 19:15:13 Peter Exp $
     Software:  AVR-GCC 3.3
     Target:    any AVR device, memory mapped mode only for AT90S4414/8515/Mega

     DESCRIPTION
           Basic routines for interfacing a HD44780U-based text lcd display

           Originally based on Volker Oth's lcd library,
           changed lcd_init(), added additional constants for lcd_command(),
           added 4-bit I/O mode, improved and optimized code.

           Library can be operated in memory mapped mode (LCD_IO_MODE=0) or in
           4-bit IO port mode (LCD_IO_MODE=1). 8-bit IO port mode not supported.
           
           Memory mapped mode compatible with Kanda STK200, but supports also
           generation of R/W signal through A8 address line.

     USAGE
           See the C include lcd.h file for a description of each function
           
    *****************************************************************************/
    #include <inttypes.h>
    #include <avr/io.h>
    #include <avr/pgmspace.h>
    #include "lcd.h"



    /*
    ** constants/macros
    */
    #define DDR(x) (*(&x - 1))      /* address of data direction register of port x */
    #if defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__)
        /* on ATmega64/128 PINF is on port 0x00 and not 0x60 */
        #define PIN(x) ( &PORTF==&(x) ? _SFR_IO8(0x00) : (*(&x - 2)) )
    #else
       #define PIN(x) (*(&x - 2))    /* address of input register of port x          */
    #endif


    #if LCD_IO_MODE
    #define lcd_e_delay()   __asm__ __volatile__( "rjmp 1f\n 1:" );
    #define lcd_e_high()    LCD_E_PORT  |=  _BV(LCD_E_PIN);
    #define lcd_e_low()     LCD_E_PORT  &= ~_BV(LCD_E_PIN);
    #define lcd_e_toggle()  toggle_e()
    #define lcd_rw_high()   LCD_RW_PORT |=  _BV(LCD_RW_PIN)
    #define lcd_rw_low()    LCD_RW_PORT &= ~_BV(LCD_RW_PIN)
    #define lcd_rs_high()   LCD_RS_PORT |=  _BV(LCD_RS_PIN)
    #define lcd_rs_low()    LCD_RS_PORT &= ~_BV(LCD_RS_PIN)
    #endif

    #if LCD_IO_MODE
    #if LCD_LINES==1
    #define LCD_FUNCTION_DEFAULT    LCD_FUNCTION_4BIT_1LINE
    #else
    #define LCD_FUNCTION_DEFAULT    LCD_FUNCTION_4BIT_2LINES
    #endif
    #else
    #if LCD_LINES==1
    #define LCD_FUNCTION_DEFAULT    LCD_FUNCTION_8BIT_1LINE
    #else
    #define LCD_FUNCTION_DEFAULT    LCD_FUNCTION_8BIT_2LINES
    #endif
    #endif


    /*
    ** function prototypes
    */
    #if LCD_IO_MODE
    static void toggle_e(void);
    #endif

    /*
    ** local functions
    */



    /*************************************************************************
     delay loop for small accurate delays: 16-bit counter, 4 cycles/loop
    *************************************************************************/
    static inline void _delayFourCycles(unsigned int __count)
    {
        if ( __count == 0 )   
            __asm__ __volatile__( "rjmp 1f\n 1:" );    // 2 cycles
        else
            __asm__ __volatile__ (
               "1: sbiw %0,1" "\n\t"                 
               "brne 1b"                              // 4 cycles/loop
               : "=w" (__count)
               : "0" (__count)
              );
    }


    /*************************************************************************
    delay for a minimum of <us> microseconds
    the number of loops is calculated at compile-time from MCU clock frequency
    *************************************************************************/
    #define delay(us)  _delayFourCycles( ( ( 1*(XTAL/4000) )*us)/1000 )


    #if LCD_IO_MODE
    /* toggle Enable Pin to initiate write */
    static void toggle_e(void)
    {
        lcd_e_high();
        lcd_e_delay();
        lcd_e_low();
    }
    #endif


    /*************************************************************************
    Low-level function to write byte to LCD controller
    Input:    data   byte to write to LCD
              rs     1: write data   
                     0: write instruction
    Returns:  none
    *************************************************************************/
    #if LCD_IO_MODE
    static void lcd_write(uint8_t data,uint8_t rs)
    {
        unsigned char dataBits ;


        if (rs) {   /* write data        (RS=1, RW=0) */
           lcd_rs_high();
        } else {    /* write instruction (RS=0, RW=0) */
           lcd_rs_low();
        }
        lcd_rw_low();

        if ( ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT == &LCD_DATA3_PORT )
          && (LCD_DATA0_PIN == 0) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) )
        {
            /* configure data pins as output */
            DDR(LCD_DATA0_PORT) |= 0x0F;

            /* output high nibble first */
            dataBits = LCD_DATA0_PORT & 0xF0;
            LCD_DATA0_PORT = dataBits |((data>>4)&0x0F);
            lcd_e_toggle();

            /* output low nibble */
            LCD_DATA0_PORT = dataBits | (data&0x0F);
            lcd_e_toggle();

            /* all data pins high (inactive) */
            LCD_DATA0_PORT = dataBits | 0x0F;
        }
        else
        {
            /* configure data pins as output */
            DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN);
            DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN);
            DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN);
            DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN);
           
            /* output high nibble first */
            LCD_DATA3_PORT &= ~_BV(LCD_DATA3_PIN);
            LCD_DATA2_PORT &= ~_BV(LCD_DATA2_PIN);
            LCD_DATA1_PORT &= ~_BV(LCD_DATA1_PIN);
            LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN);
           if(data & 0x80) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN);
           if(data & 0x40) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN);
           if(data & 0x20) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);
           if(data & 0x10) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);   
            lcd_e_toggle();
           
            /* output low nibble */
            LCD_DATA3_PORT &= ~_BV(LCD_DATA3_PIN);
            LCD_DATA2_PORT &= ~_BV(LCD_DATA2_PIN);
            LCD_DATA1_PORT &= ~_BV(LCD_DATA1_PIN);
            LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN);
           if(data & 0x08) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN);
           if(data & 0x04) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN);
           if(data & 0x02) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);
           if(data & 0x01) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);
            lcd_e_toggle();       
           
            /* all data pins high (inactive) */
            LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);
            LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);
            LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN);
            LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN);
        }
    }
    #else
    #define lcd_write(d,rs) if (rs) *(volatile uint8_t*)(LCD_IO_DATA) = d; else *(volatile uint8_t*)(LCD_IO_FUNCTION) = d;
    /* rs==0 -> write instruction to LCD_IO_FUNCTION */
    /* rs==1 -> write data to LCD_IO_DATA */
    #endif


    /*************************************************************************
    Low-level function to read byte from LCD controller
    Input:    rs     1: read data   
                     0: read busy flag / address counter
    Returns:  byte read from LCD controller
    *************************************************************************/
    #if LCD_IO_MODE
    static uint8_t lcd_read(uint8_t rs)
    {
        uint8_t data;
       
       
        if (rs)
            lcd_rs_high();                       /* RS=1: read data      */
        else
            lcd_rs_low();                        /* RS=0: read busy flag */
        lcd_rw_high();                           /* RW=1  read mode      */
       
        if ( ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT == &LCD_DATA3_PORT )
          && ( LCD_DATA0_PIN == 0 )&& (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) )
        {
            DDR(LCD_DATA0_PORT) &= 0xF0;         /* configure data pins as input */
           
            lcd_e_high();
            lcd_e_delay();       
            data = PIN(LCD_DATA0_PORT) << 4;     /* read high nibble first */
            lcd_e_low();
           
            lcd_e_delay();                       /* Enable 500ns low       */
           
            lcd_e_high();
            lcd_e_delay();
            data |= PIN(LCD_DATA0_PORT)&0x0F;    /* read low nibble        */
            lcd_e_low();
        }
        else
        {
            /* configure data pins as input */
            DDR(LCD_DATA0_PORT) &= ~_BV(LCD_DATA0_PIN);
            DDR(LCD_DATA1_PORT) &= ~_BV(LCD_DATA1_PIN);
            DDR(LCD_DATA2_PORT) &= ~_BV(LCD_DATA2_PIN);
            DDR(LCD_DATA3_PORT) &= ~_BV(LCD_DATA3_PIN);
                   
            /* read high nibble first */
            lcd_e_high();
            lcd_e_delay();       
            data = 0;
            if ( PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN) ) data |= 0x10;
            if ( PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN) ) data |= 0x20;
            if ( PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN) ) data |= 0x40;
            if ( PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN) ) data |= 0x80;
            lcd_e_low();

            lcd_e_delay();                       /* Enable 500ns low       */
       
            /* read low nibble */   
            lcd_e_high();
            lcd_e_delay();
            if ( PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN) ) data |= 0x01;
            if ( PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN) ) data |= 0x02;
            if ( PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN) ) data |= 0x04;
            if ( PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN) ) data |= 0x08;       
            lcd_e_low();
        }
        return data;
    }
    #else
    #define lcd_read(rs) (rs) ? *(volatile uint8_t*)(LCD_IO_DATA+LCD_IO_READ) : *(volatile uint8_t*)(LCD_IO_FUNCTION+LCD_IO_READ)
    /* rs==0 -> read instruction from LCD_IO_FUNCTION */
    /* rs==1 -> read data from LCD_IO_DATA */
    #endif


    /*************************************************************************
    loops while lcd is busy, returns address counter
    *************************************************************************/
    static uint8_t lcd_waitbusy(void)

    {
        register uint8_t c;
       
        /* wait until busy flag is cleared */
        while ( (c=lcd_read(0)) & (1<<LCD_BUSY)) {}
       
        /* the address counter is updated 4us after the busy flag is cleared */
        delay(2);

        /* now read the address counter */
        return (lcd_read(0));  // return address counter
       
    }/* lcd_waitbusy */


    /*************************************************************************
    Move cursor to the start of next line or to the first line if the cursor
    is already on the last line.
    *************************************************************************/
    static inline void lcd_newline(uint8_t pos)
    {
        register uint8_t addressCounter;


    #if LCD_LINES==1
        addressCounter = 0;
    #endif
    #if LCD_LINES==2
        if ( pos < (LCD_START_LINE2) )
            addressCounter = LCD_START_LINE2;
        else
            addressCounter = LCD_START_LINE1;
    #endif
    #if LCD_LINES==4
        if ( pos < LCD_START_LINE3 )
            addressCounter = LCD_START_LINE2;
        else if ( (pos >= LCD_START_LINE2) && (pos < LCD_START_LINE4) )
            addressCounter = LCD_START_LINE3;
        else if ( (pos >= LCD_START_LINE3) && (pos < LCD_START_LINE2) )
            addressCounter = LCD_START_LINE4;
        else
            addressCounter = LCD_START_LINE1;
    #endif
        lcd_command((1<<LCD_DDRAM)+addressCounter);

    }/* lcd_newline */


    /*
    ** PUBLIC FUNCTIONS
    */

    /*************************************************************************
    Send LCD controller instruction command
    Input:   instruction to send to LCD controller, see HD44780 data sheet
    Returns: none
    *************************************************************************/
    void lcd_command(uint8_t cmd)
    {
        lcd_waitbusy();
        lcd_write(cmd,0);
    }


    /*************************************************************************
    Send data byte to LCD controller
    Input:   data to send to LCD controller, see HD44780 data sheet
    Returns: none
    *************************************************************************/
    void lcd_data(uint8_t data)
    {
        lcd_waitbusy();
        lcd_write(data,1);
    }



    /*************************************************************************
    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 LCD_LINES==1
        lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x);
    #endif
    #if LCD_LINES==2
        if ( y==0 )
            lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x);
        else
            lcd_command((1<<LCD_DDRAM)+LCD_START_LINE2+x);
    #endif
    #if LCD_LINES==4
        if ( y==0 )
            lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x);
        else if ( y==1)
            lcd_command((1<<LCD_DDRAM)+LCD_START_LINE2+x);
        else if ( y==2)
            lcd_command((1<<LCD_DDRAM)+LCD_START_LINE3+x);
        else /* y==3 */
            lcd_command((1<<LCD_DDRAM)+LCD_START_LINE4+x);
    #endif

    }/* lcd_gotoxy */


    /*************************************************************************
    *************************************************************************/
    int lcd_getxy(void)
    {
        return lcd_waitbusy();
    }


    /*************************************************************************
    Clear display and set cursor to home position
    *************************************************************************/
    void lcd_clrscr(void)
    {
        lcd_command(1<<LCD_CLR);
    }


    /*************************************************************************
    Set cursor to home position
    *************************************************************************/
    void lcd_home(void)
    {
        lcd_command(1<<LCD_HOME);
    }


    /*************************************************************************
    Display character at current cursor position
    Input:    character to be displayed                                       
    Returns:  none
    *************************************************************************/
    void lcd_putc(char c)
    {
        uint8_t pos;


        pos = lcd_waitbusy();   // read busy-flag and address counter
        if (c=='\n')
        {
            lcd_newline(pos);
        }
        else
        {
    #if LCD_WRAP_LINES==1
    #if LCD_LINES==1
            if ( pos == LCD_START_LINE1+LCD_DISP_LENGTH )
                lcd_write((1<<LCD_DDRAM)+LCD_START_LINE1,0);
    #elif LCD_LINES==2
            if ( pos == LCD_START_LINE1+LCD_DISP_LENGTH )
                lcd_write((1<<LCD_DDRAM)+LCD_START_LINE2,0);   
            else if ( pos == LCD_START_LINE2+LCD_DISP_LENGTH )
                lcd_write((1<<LCD_DDRAM)+LCD_START_LINE1,0);
    #elif LCD_LINES==4
            if ( pos == LCD_START_LINE1+LCD_DISP_LENGTH )
                lcd_write((1<<LCD_DDRAM)+LCD_START_LINE2,0);   
            else if ( pos == LCD_START_LINE2+LCD_DISP_LENGTH )
                lcd_write((1<<LCD_DDRAM)+LCD_START_LINE3,0);
            else if ( pos == LCD_START_LINE3+LCD_DISP_LENGTH )
                lcd_write((1<<LCD_DDRAM)+LCD_START_LINE4,0);
            else if ( pos == LCD_START_LINE4+LCD_DISP_LENGTH )
                lcd_write((1<<LCD_DDRAM)+LCD_START_LINE1,0);
    #endif
            lcd_waitbusy();
    #endif
            lcd_write(c, 1);
        }

    }/* lcd_putc */


    /*************************************************************************
    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 */


    /*************************************************************************
    Initialize display and select type of cursor
    Input:    dispAttr LCD_DISP_OFF            display off
                       LCD_DISP_ON             display on, cursor off
                       LCD_DISP_ON_CURSOR      display on, cursor on
                       LCD_DISP_CURSOR_BLINK   display on, cursor on flashing
    Returns:  none
    *************************************************************************/
    void lcd_init(uint8_t dispAttr)
    {
    #if LCD_IO_MODE
        /*
         *  Initialize LCD to 4 bit I/O mode
         */
         
        if ( ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT == &LCD_DATA3_PORT )
          && ( &LCD_RS_PORT == &LCD_DATA0_PORT) && ( &LCD_RW_PORT == &LCD_DATA0_PORT) && (&LCD_E_PORT == &LCD_DATA0_PORT)
          && (LCD_DATA0_PIN == 0 ) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3)
          && (LCD_RS_PIN == 4 ) && (LCD_RW_PIN == 5) && (LCD_E_PIN == 6 ) )
        {
            /* configure all port bits as output (all LCD lines on same port) */
            DDR(LCD_DATA0_PORT) |= 0x7F;
        }
        else if ( ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT == &LCD_DATA3_PORT )
               && (LCD_DATA0_PIN == 0 ) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) )
        {
            /* configure all port bits as output (all LCD data lines on same port, but control lines on different ports) */
            DDR(LCD_DATA0_PORT) |= 0x0F;
            DDR(LCD_RS_PORT)    |= _BV(LCD_RS_PIN);
            DDR(LCD_RW_PORT)    |= _BV(LCD_RW_PIN);
            DDR(LCD_E_PORT)     |= _BV(LCD_E_PIN);
        }
        else
        {
            /* configure all port bits as output (LCD data and control lines on different ports */
            DDR(LCD_RS_PORT)    |= _BV(LCD_RS_PIN);
            DDR(LCD_RW_PORT)    |= _BV(LCD_RW_PIN);
            DDR(LCD_E_PORT)     |= _BV(LCD_E_PIN);
            DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN);
            DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN);
            DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN);
            DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN);
        }
        delay(16000);        /* wait 16ms or more after power-on       */
       
        /* initial write to lcd is 8bit */
        LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);  // _BV(LCD_FUNCTION)>>4;
        LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);  // _BV(LCD_FUNCTION_8BIT)>>4;
        lcd_e_toggle();
        delay(4992);         /* delay, busy flag can't be checked here */
       
        /* repeat last command */
        lcd_e_toggle();     
        delay(64);           /* delay, busy flag can't be checked here */
       
        /* repeat last command a third time */
        lcd_e_toggle();     
        delay(64);           /* delay, busy flag can't be checked here */

        /* now configure for 4bit mode */
        LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN);   // LCD_FUNCTION_4BIT_1LINE>>4
        lcd_e_toggle();
        delay(64);           /* some displays need this additional delay */
       
        /* from now the LCD only accepts 4 bit I/O, we can use lcd_command() */   
    #else
        /*
         * Initialize LCD to 8 bit memory mapped mode
         */
       
        /* enable external SRAM (memory mapped lcd) and one wait state */       
        MCUCR = _BV(SRE) | _BV(SRW);

        /* reset LCD */
        delay(16000);                           /* wait 16ms after power-on     */
        lcd_write(LCD_FUNCTION_8BIT_1LINE,0);   /* function set: 8bit interface */                   
        delay(4992);                            /* wait 5ms                     */
        lcd_write(LCD_FUNCTION_8BIT_1LINE,0);   /* function set: 8bit interface */                 
        delay(64);                              /* wait 64us                    */
        lcd_write(LCD_FUNCTION_8BIT_1LINE,0);   /* function set: 8bit interface */               
        delay(64);                              /* wait 64us                    */
    #endif
        lcd_command(LCD_FUNCTION_DEFAULT);      /* function set: display lines  */
        lcd_command(LCD_DISP_OFF);              /* display off                  */
        lcd_clrscr();                           /* display clear                */
        lcd_command(LCD_MODE_DEFAULT);          /* set entry mode               */
        lcd_command(dispAttr);                  /* display/cursor control       */

    }/* lcd_init */



    wielkie thx za pomoc ;)
  • #11
    tymon_x
    Level 30  
    Zobacz tu: https://www.elektroda.pl/rtvforum/topic1748487.html

    Na podstawie dokumentacji od LCD zmień te parametry.
    Code:
    #define LCD_LINES           4     /**< number of visible lines of the display */ 
    
    #define LCD_DISP_LENGTH    20     /**< visibles characters per line of the display */
    #define LCD_LINE_LENGTH  0x40     /**< internal line length of the display    */
    #define LCD_START_LINE1  0x00     /**< DDRAM address of first char of line 1 */
    #define LCD_START_LINE2  0x20     /**< DDRAM address of first char of line 2 */
    #define LCD_START_LINE3  0x40     /**< DDRAM address of first char of line 3 */
    #define LCD_START_LINE4  0x60     /**< DDRAM address of first char of line 4 */
    #define LCD_WRAP_LINES      1     /**< 0: no wrap, 1: wrap at end of visibile line */
  • #12
    Rafał_
    Level 10  
    to są właśnie moje zmiany , czytałem dokumentacje do wyświetlacza orginalnie w bibliotekach było :

    Code:

    #define LCD_LINES           2     /**< number of visible lines of the display */
    #define LCD_DISP_LENGTH    16     /**< visibles characters per line of the display */
    #define LCD_LINE_LENGTH  0x40     /**< internal line length of the display    */
    #define LCD_START_LINE1  0x00     /**< DDRAM address of first char of line 1 */
    #define LCD_START_LINE2  0x40     /**< DDRAM address of first char of line 2 */
    #define LCD_START_LINE3  0x14     /**< DDRAM address of first char of line 3 */
    #define LCD_START_LINE4  0x54     /**< DDRAM address of first char of line 4 */
    #define LCD_WRAP_LINES      0     /**< 0: no wrap, 1: wrap at end of visibile line */

    i nie działało poprawienie , po modyfikacji biblioteki nic sie nie zmieniło :(
  • #13
    tymon_x
    Level 30  
    Te #define miałeś dobrze, w tym gąszczu nie zauważyłem jaki to wyświetlacz (;

    Ta biblioteka mnie przytłacza, nie lepiej użyć tej funkcji z niej:
    Code:
    lcd_gotoxy(uint8_t x, uint8_t y);

    I potem:
    Code:
    lcd_puts("kapusta");

    Do 20 znaków. Lepiej dla Ciebie by było jakbyś sam skroił Swoją bibliotekę, byś wiedział przynajmniej co w niej piszczy (;
  • #14
    Rafał_
    Level 10  
    chciałem tak zrobić tylko problem w tym że dubluje mi znaki :/ np takie współrzędne
    lcd_gotoxy(19,0);
    mają dwa segmenty wyświetlacza , w pierwszej linii 20 segment i w drugiej linii segment 8 segment :(