mikrocontroller.net

Forum: Compiler & IDEs Angepasste LCD-Library für AVR-Ctrl


Autor: Ludwigs (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
Ich versuche gerade selber das LCD-Library von Peter Fleury anzupassen 
und bräuchte mal ein bisschen Hilfe. Die LCD.h ist ja kein Problem 
anzupassen. Aber mit der LCD.C habe ich noch einige Probleme. Wäre nett 
wenn mir da mal einer helfen könnte.

Mit freundlichen Grüßen
Ludwigs



Pinbelegung

PC0 -> RS
PC1 -> RW
PC2 -> E
PC3 ->
PC4 -> DB4
PC5 -> DB5
PC6 -> DB6
PC7 -> DB7


Angepasste LCD.H
/*********************************************************************** 
**
 Title  :   C include file for the HD44780U LCD library (lcd.c)
 Author:    Peter Fleury <pfleury@gmx.ch>  http://jump.to/fleury
 Date:      23-Sep-2000
 Software:  AVR-GCC with AVR-AS
 Target:    any AVR device, memory mapped mode only for 
AT90S4414/8515/Mega

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

       Based on Volker Oth's lcd library 
(http://members.xoom.com/volkeroth),
       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.


************************************************************************ 
***/
#ifndef LCD_H
#define LCD_H


/* change these definitions to adapt setting */

#define LCD_LINES           2     /* visible lines */
#define LCD_LINE_LENGTH  0x40     /* internal line length */
#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_IO_MODE      1         /* 0: memory mapped mode, 1: IO port 
mode */

#if LCD_IO_MODE  /* only necessary in IO mode */
#define LCD_PORT         PORTC     /* Portc  */
#define LCD_DATA_PORT    LCD_PORT  /* port for 4bit data (Pin 0..3) */
#define LCD_RS_PORT      LCD_PORT  /* port for RS line */
#define LCD_RS_PIN       0
#define LCD_RW_PORT      LCD_PORT  /* port for RW line */
#define LCD_RW_PIN       1
#define LCD_E_PORT       LCD_PORT  /* port for Enable line */
#define LCD_E_PIN        2
#else            /* only necessary in memory mapped mode */
#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 
*/
#endif


/* you shouldn't need to change anything below this line */

typedef unsigned char  u08;
typedef unsigned short u16;


/* instruction register bit positions */
#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) )


/*
** function prototypes
*/
extern void lcd_command(u08 cmd);
extern void lcd_gotoxy(u08 x, u08 y);
extern void lcd_clrscr(void);
extern void lcd_home(void);
extern void lcd_putc(char c);
extern void lcd_puts(const char *s);
extern void lcd_puts_p(const char *progmem_s);
extern void lcd_init(u08 dispAttr);

/*
** macros for automatically storing string constant in program memory
*/
#ifndef P
#define P(s) ({static const char c[] _attribute_ ((progmem)) = s;c;})
#endif
#define lcd_puts_P(__s)         lcd_puts_p(P(__s))


#endif //LCD_H




Noch nicht Angepasste LCD.c
/*********************************************************************** 
*****
 Title  :   HD44780U LCD library
 Author:    Peter Fleury <pfleury@gmx.ch>  http://jump.to/fleury
 Date:      23-Sep-2000
 Software:  AVR-GCC with AVR-AS
 Target:    any AVR device, memory mapped mode only for 
AT90S4414/8515/Mega

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

       Based on Volker Oth's lcd library 
(http://members.xoom.com/volkeroth),
       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 <io.h>
#include <progmem.h>
#include "lcd.h"


/*
** constants/macros
*/
#define DDR(x) ((x)-1)    /* address of data direction register of port 
x */
#define PIN(x) ((x)-2)    /* address of input register of port x */

#if LCD_IO_MODE
#define lcd_e_delay()   asm volatile("rjmp _PC_+0")  /* delay 500ns with 
4Mhz */
#define lcd_e_high()    sbi(LCD_E_PORT, LCD_E_PIN)
#define lcd_e_low()     cbi(LCD_E_PORT, LCD_E_PIN)
#define lcd_e_toggle()  toggle_e()
#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
*/
static void delay(u16 us);
#if LCD_IO_MODE
static void toggle_e(void);
#endif

/*
** local functions
*/

static void delay(u16 us)
/* delay for a minimum of <us> microseconds    */
/* with a 4Mhz crystal, the resolution is 1 us */
{
    while ( us ) us--;
}


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


#if LCD_IO_MODE
static void inline lcd_write(u08 data,u08 rs)
{
    /* configure data pins as output */
    outp(0xFF, DDR(LCD_DATA_PORT) );

    if (rs) {   /* write data        (RS=1, RW=0) */

       /* output high nibble first */
       outp( ((data>>4)&0x0F)|(1<<LCD_RS_PIN), LCD_DATA_PORT );
       lcd_e_toggle();

       /* output low nibble */
       outp( (data&0x0F)|(1<<LCD_RS_PIN), LCD_DATA_PORT );
       lcd_e_toggle();

    } else {    /* write instruction (RS=0, RW=0) */

       /* output high nibble first */
       outp( (data>>4)&0x0F, LCD_DATA_PORT );
       lcd_e_toggle();

       /* output low nibble */
       outp( data&0x0F, LCD_DATA_PORT );
       lcd_e_toggle();
    }

    /* all data pins high (inactive) */
    outp(0x0F, LCD_DATA_PORT);
}
#else
#define lcd_write(d,rs) if (rs) *(volatile u08*)(LCD_IO_DATA) = d; else 
*(volatile u08*)(LCD_IO_FUNCTION) = d;
/* rs==0 -> write instruction to LCD_IO_FUNCTION */
/* rs==1 -> write data to LCD_IO_DATA */
#endif


#if LCD_IO_MODE
static u08 lcd_read(u08 rs)
{
    register u08 dataH, dataL;

    if (rs) sbi(LCD_RS_PORT, LCD_RS_PIN);    /* RS=1: read data      */
    else    cbi(LCD_RS_PORT, LCD_RS_PIN);    /* RS=0: read busy flag */
    sbi(LCD_RW_PORT, LCD_RW_PIN);            /* RW=1  read mode      */

    /* configure data pins as input */
    outp(0xF0, DDR(LCD_DATA_PORT));

    lcd_e_high();
    lcd_e_delay();
    dataH = inp(PIN(LCD_DATA_PORT));         /* read high nibble first 
*/
    lcd_e_low();

    lcd_e_delay();                           /* Enable 500ns low 
*/

    lcd_e_high();
    lcd_e_delay();
    dataL = inp(PIN(LCD_DATA_PORT));         /* read low nibble 
*/
    lcd_e_low();

    return ( (dataH<<4) | (dataL&0x0F) );
}
#else
#define lcd_read(rs) (rs) ? *(volatile u08*)(LCD_IO_DATA+LCD_IO_READ) : 
*(volatile u08*)(LCD_IO_FUNCTION+LCD_IO_READ)
/* rs==0 -> read instruction from LCD_IO_FUNCTION */
/* rs==1 -> read data from LCD_IO_DATA */
#endif


static inline unsigned char lcd_waitbusy(void)
/* loops while lcd is busy, reads address counter */
{
    register unsigned char c;

    while ( (c=lcd_read(0)) & (1<<LCD_BUSY)) {}

    return (c);  // return address counter
}


static inline void lcd_newline(u08 pos)
/* goto start of next line */
{
    register u08 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
*/

void lcd_command(u08 cmd)
/* send commando <cmd> to LCD */
{
    lcd_waitbusy();
    lcd_write(cmd,0);
}


void lcd_gotoxy(u08 x, u08 y)
/* goto position (x,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 */


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


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


void lcd_putc(char c)
/* print character at current cursor position */
{
    register unsigned char pos;

    pos = lcd_waitbusy();   // read busy-flag and address counter
    if (c=='\n')
        lcd_newline(pos);
    else
        lcd_write(c, 1);
}


void lcd_puts(const char *s)
/* print string on lcd (no auto linefeed) */
{
    register char c;

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

}


void lcd_puts_p(const char *progmem_s)
/* print string from program memory on lcd (no auto linefeed) */
{
    register char c;

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

}


void lcd_init(u08 dispAttr)
/* initialize display and select type of cursor */
/* dispAttr: LCD_DISP_OFF, LCD_DISP_ON, LCD_DISP_ON_CURSOR, 
LCD_DISP_CURSOR_BLINK */
{
#if LCD_IO_MODE
    /*------ Initialize lcd to 4 bit i/o mode -------*/

    outp( 0xFF, DDR(LCD_DATA_PORT) );         /* all port bits as output 
*/

    delay(16000);        /* wait 16ms or more after power-on       */

    /* initial write to lcd is 8bit */
    outp(LCD_FUNCTION_8BIT_1LINE>>4,LCD_DATA_PORT);
    lcd_e_toggle();
    delay(4992);         /* delay, busy flag can't be checked here */

    outp(LCD_FUNCTION_8BIT_1LINE>>4,LCD_DATA_PORT);
    lcd_e_toggle();
    delay(64);           /* delay, busy flag can't be checked here */

    outp(LCD_FUNCTION_8BIT_1LINE>>4,LCD_DATA_PORT);
    lcd_e_toggle();
    delay(64);           /* delay, busy flag can't be checked here */

    outp(LCD_FUNCTION_4BIT_1LINE>>4,LCD_DATA_PORT); /* set IO mode to 
4bit */
    lcd_e_toggle();

    /* 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 */
    /* add  -Wl,--defsym,__init_mcucr__=0xC0 to the link command   */
    /* or uncomment the next line:                                 */
    outp((1<<SRE)|(1<<SRW), MCUCR);

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

Autor: Jonas Diemer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wo hakts denn? die einzige anpassung, die die library benötigt kann doch 
eigentlich nur die Pins sein, an denen das LCD hängt, oder irre ich da?

Autor: Ludwigs (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
{PC0 -> RS
 PC1 -> RW
 PC2 -> E} Diese Pins konnte man ja in der LCD.H ändern.


{PC4 -> DB4
 PC5 -> DB5
 PC6 -> DB6
 PC7 -> DB7} Diese müssen aber in der LCD.C geändert werden.

{PC0-> DB4
 PC1-> DB5
 PC2-> DB6
 PC3-> DB7} Das währe die Momentane Einstellung.

Mit freundlichen Grüßen
Ludwigs

Autor: Jonas Diemer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hmm. hab mir zwar nicht alles durchgelesen, aber: mach doch die LCD.c 
auch modul, d.h. dort auch mit defines die einzelnen pins deklarieren.

Weden im programm momentan hexkonstanten für die ports verwendet? falls 
ja, ändere sie in diese form:

zum beispiel sollen pin 1 und pin2 vom lcd high, der rest low:

(1<<LCD_DATA1) | (1<<LCD_DATA2)

wie gesagt, sind nur tips, habs mir nicht alles durchgelesen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.