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 + AVR Studio, problem.

vcd_a 12 Mar 2008 21:51 13535 4
  • #1
    vcd_a
    Level 18  
    Witam, właśnie walczę z obsługą LCD pod Atmegą 8 - cały kod jest w C, z użyciem biblioteki: LCD Library

    Napisałem prosty kod przy użyciu Bascoma i LCD ładnie działa, niestety pod C są problemy ;(. Poniżej zamieszczam kod z lcd.h gdzie zmodyfikowałem podłączenia do uC (podłączone D6...D9, RS, RW, E, XTAL).
    Dodam, że uC zaczyna się dziwnie lekko grzać jak wrzucę ten kod w C (zamieszczony poniżej).

    lcd.h
    
    #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@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 4000000              /**< 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           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 */
    
    
    #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   PORTD     /**< port for 4bit data bit 0 */
    #define LCD_DATA1_PORT   PORTD     /**< port for 4bit data bit 1 */
    #define LCD_DATA2_PORT   PORTD    /**< port for 4bit data bit 2 */
    #define LCD_DATA3_PORT   PORTD     /**< port for 4bit data bit 3 */
    #define LCD_DATA0_PIN    0           /**< pin for 4bit data bit 0  */
    #define LCD_DATA1_PIN    1            /**< pin for 4bit data bit 1  */
    #define LCD_DATA2_PIN    2           /**< pin for 4bit data bit 2  */
    #define LCD_DATA3_PIN    3           /**< pin for 4bit data bit 3  */
    #define LCD_RS_PORT      PORTD     /**< port for RS line         */
    #define LCD_RS_PIN       4            /**< pin  for RS line         */
    #define LCD_RW_PORT      PORTD     /**< port for RW line         */
    #define LCD_RW_PIN       5            /**< pin  for RW line         */
    #define LCD_E_PORT       PORTD     /**< port for Enable line     */
    #define LCD_E_PIN        6            /**< 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
    


    Oraz kod programu:

    
    // Test_2
    #include "lcd.c"
    #include <avr/io.h>
    
    void pokaz(void);
    
    //------------------------------ MAIN ----------------------------------
    int main()
    {
    	lcd_init(LCD_DISP_ON);
    
    	while(1)
    	{
    		pokaz();
    	}
    }
    
    
    //+++++++++++++++++++++++++ FUNKCJE ++++++++++++++++++++++++++++++++++++
    //----------------------------------------------------------------------
    void pokaz(void)
    {
    	char napis[] = "Hello!!!";
    
    	lcd_gotoxy(0,0);
    	lcd_puts(napis);
    }
    
    


    Z góry dzięki za odpowiedzi, pozdrawiam Krzysiek

    Jeżeli ktoś ma jakąś inną bibliotekę byłbym zobowiązany :), pozdrawiam
  • #2
    bynajmniej
    Level 11  
    to znaczy, chodzi ci o jakiś kod w C który obsługuje LCD 2x16 znaków?

    kod znaleziony na elektrodzie i trochę przeze mnie przerobiony

    
    #define F_CPU 1000000UL
    #include <avr/io.h> 
    #include <avr/delay.h>
    
    
    // Definicje dotyczace LCD 
    #define LCD PORTD             //port z LCD 
    #define RS 0                     // wybor rejestru 
    #define RW 2                     // 1 - odczyt; 0 - zapis 
    #define E 3                      // sygnal zezwalajacy (enable) 
    #define SET_E LCD |= _BV(E) 
    #define CLR_E LCD &= ~_BV(E) 
    #define SET_RS LCD |= _BV(RS) 
    #define CLR_RS LCD &= ~_BV(RS) 
    #define SET_RW LCD |= _BV(RW) 
    #define CLR_RW LCD &= ~_BV(RW) 
    #define DDRLCD DDRA             // port z podlaczanym LCD 
    #define PINLCD PINA             // port z podlaczanym LCD 
    // Wykorzystujemy tylko cztery linie przesylowe D4-D7 portu PORTLCD 
    // pcodedura zapisu bajtu do wyœwietlacza LCD 
    // bez rozróżnienia instrukcja/dana 
    void write_to_lcd(char x) 
    { 
    SET_E; // ustaw na E stan wysoki 
    LCD = ((LCD & 0x0F) | (x & 0xF0)); // zapis pierwszej połówki bajtu 
    CLR_E; // opadajšce zbocze na E -> zapis do wyœwietlacza 
    asm("nop"); 
    SET_E; // ustaw na E stan wysoki 
    LCD = ((LCD & 0x0F) | ((x & 0x0F) << 4)); // zapis drugiej połowki bajtu 
    CLR_E; // opadajšce zbocze na E -> zapis do wyœwietlacza 
    _delay_ms(1); // czekaj 1ms 
    } 
    
    //***************** procedura zapisu instrukcji do wyœwietlacza LCD 
    void write_command(char x) 
    { 
    CLR_RS; // niski stan na RS -> zapis instrukcji 
    write_to_lcd(x); // zapis do LCD 
    } 
    //***************** procedura zapisu danej do wyœwietlacza LCD 
    void write_char(char x) 
    { 
       SET_RS; // wysoki stan na RS -> zapis danej 
       write_to_lcd(x); // zapis do LCD _delay_ms
    } 
    //***************** procedura zapisu tekstu do wyœwietlacza LCD 
    void write_text(char * s) 
    { 
    while(*s) // do napotkania 0 
      { 
      write_char(*s); // zapisz znak wskazywany przez s na LCD 
      s++; // zwiększ s (przygotuj nastepny znak) 
      } 
    } 
    //***************** procedura inicjalizacji wyœwietlacza LCD 
    void lcd_init(void) 
    { 
    _delay_ms(15); // czekaj 15ms na ustabilizowanie się napięcia zasilajšcego 
    CLR_E; // E = 0 
    CLR_RS; // RS = 0 
    char i; // zmienna licznikowa 
    for(i = 0; i < 3; i++) // trzykrotne powtórzenie bloku instrukcji 
      { 
      SET_E; // E = 1 
      LCD &= 0x30; // 
      CLR_E; // E = 0 
      _delay_ms(5); // czekaj 5ms 
      } 
    SET_E; // E = 1 
    LCD &= 0x2E; // 
    CLR_E; // E = 0 
    _delay_ms(1); // czekaj 1ms 
    write_command(0x28); // interfejs 4-bity, 2-linie, znak 5x7 
    write_command(0x08); // wyłšcz LCD, kursor i miganie 
    write_command(0x01); // czyœć LCD
    _delay_ms(5); 
    write_command(0x06); // bez przesuwania w prawo 
    write_command(0x0C); // włšcz LCD, bez kursora i mrugania 
    } 
    
    //***************** procedura ustawiania pozycji kursora 
    void lcd_yx(unsigned char w, unsigned char k) 
    { 
       write_command((w*0x40+k) | 0x80); 
    } 
    
  • #3
    monsinior
    Level 16  
    Mam na pewno na na "hard drive" kod w C działający dla LCD 2x16 znaków jest na Atmega162 ale mogę Ci przesłać jako źródło natchnienia

    Pozdrawiam M.M.

    Info na Priv
  • #4
    Ravender
    Level 20  
    Ja korzystam skutecznie z biblioteki w załączniku z drobnymi zmianami i dodaniem funkcji programującej znak. w pliku .h możesz zmienić numeracje pinów.

    Przykład użycia
    
    uint8_t serce[] = {4, 10, 17, 23, 23, 17, 31, 0}; //serduszko
    uint8_t termo[] = {14, 10, 10, 14, 31, 31, 14, 0}; //termometr
    
    int main(void)
    {
    
    LCD_Initalize();
    
    LCD_ProgrammChar(0, serce); //zaprogramowanie własnego znaku
    LCD_ProgrammChar(1, termo);
    
    LCD_Clear();	//czyszczenie wyswietlacza
    
    LCD_WriteData(1); //wyswietlenie wlasnego znaku numer 1.
    LCD_WriteText("A TO JUZ TEKST"); 
    LCD_GoTo(0,1); //przejscie do drugiej linii
    LCD_WriteText("A TO JUZ DRUGA LINIA");
    (...)
    
    Attachments:
  • #5
    matmix1
    Level 10  
    Ja również mam problem z kompilacją projektu wykorzystującego wyświetlacz LCD 2x16, tyle że na atmega32. Poniżej zamieszczam screen z message boxa w AVRStudio.

    Atmega8 + LCD + AVR Studio, problem.