Hängt anscheinend mit den Zeilenadressen zusammen, siehe hier
https://www.roboternetz.de/phpBB2/viewtopic.php?t=56904
Hallo Leute,
ich hab ein Problem ein EA DIP204-4NLED Display von Electronic assembly zu laufen zu kriegen. Ich verwende CodeVision AVR zum proggen.
Ich hab schon die Original Librarys von CodeVision AVR und auch angeblich funktionierende lib's aus dem Internet probiert.
Ich hab d auch schon versucht die Initialisierungsroutine zu verändern - Kein Erfolg.
Manche lib's funktionieren gar nicht, andere zeigen die eingegebenen Zeichen an der falschen Stelle an.
Verkabelungsfehler hab ich auch keinen, hab die Leitungen schon ein paar mal durchgemessen.
Ein anderes EA DIP204 hab ich auch schon versucht - Gleiches Fehlerbild.
Ich häng euch mal die relevanten Codeteile rein, eventuell hatte ja schon jemand anderes ein ähnliches Problem.
Die Main Routine ( Ausschnitte ):
Die zum Display gehörende Header datei:Code:#include <mega1280.h> #include <string.h> #include <delay.h> // Alphanumeric LCD Module functions #asm .equ __lcd_port=0x02 ;PORTA #endasm #include "lcddip.h" .... void main (void) { .... // LCD module initialization lcd_init(20); // Watchdog Timer initialization // Watchdog Timer Prescaler: OSC/256k // Watchdog Timer interrupt: Off #pragma optsize- #asm("wdr") //WDTCSR=0x1F; **** Watchdogtimer für Testzwecke deaktiviert !!!! //WDTCSR=0x0F; #ifdef _OPTIMIZE_SIZE_ #pragma optsize+ #endif // Global enable interrupts #asm("sei") while (1) { //*** Reset des Watchdog Timers #asm("wdr"); //**** Test **** lcd_gotoxy(0,0); strcpyf(uc_line1,"Zeile 1 sollte hier"); lcd_puts(uc_line1); lcd_gotoxy(0,1); strcpyf(uc_line2,"Zeile 2 sollte hier"); lcd_puts(uc_line2); lcd_gotoxy(0,2); strcpyf(uc_line3,"Zeile 3 sollte hier"); lcd_puts(uc_line3); lcd_gotoxy(0,3); strcpyf(uc_line4,"Zeile 4 sollte hier"); lcd_puts(uc_line4); delay_ms(300); .... }
Die Display library:Code:/* LCD driver routines CodeVisionAVR C Compiler (C) 1998-2000 Pavel Haiduc, HP InfoTech S.R.L. BEFORE #include -ING THIS FILE YOU MUST DECLARE THE I/O ADDRESS OF THE DATA REGISTER OF THE PORT AT WHICH THE LCD IS CONNECTED! EXAMPLE FOR PORTB: #asm .equ __lcd_port=0x18 #endasm #include <lcddip.h> Copy the File LCDDIP204.lib into the entire folder */ #ifndef _LCD_INCLUDED_ #define _LCD_INCLUDED_ #pragma used+ void _lcd_ready(void); void _lcd_write_data(unsigned char data); // write a byte to the LCD character generator or display RAM void lcd_write_byte(unsigned char addr, unsigned char data); // read a byte from the LCD character generator or display RAM unsigned char lcd_read_byte(unsigned char addr); // set the LCD display position x=0..39 y=0..3 void lcd_gotoxy(unsigned char x, unsigned char y); // clear the LCD void lcd_clear(void); void lcd_putchar(char c); // write the string str located in SRAM to the LCD void lcd_puts(char *str); // write the string str located in FLASH to the LCD void lcd_putsf(char flash *str); // initialize the LCD controller unsigned char lcd_init(unsigned char lcd_columns); #pragma used- #pragma library LCDDIP204.lib #endif
Code:/* LCD driver routines CodeVisionAVR C Compiler (C) 1998-2004 Pavel Haiduc, HP InfoTech S.R.L. */ #asm .equ __lcd_direction=__lcd_port-1 .equ __lcd_pin=__lcd_port-2 .equ __lcd_rs=0 .equ __lcd_rd=1 .equ __lcd_enable=2 .equ __lcd_busy_flag=7 #endasm #pragma used+ static unsigned char _base_y[4]={0x80,0xc0}; unsigned char _lcd_x,_lcd_y,_lcd_maxx; #pragma used- void _lcd_ready(void) { #asm in r26,__lcd_direction andi r26,0xf ;set as input out __lcd_direction,r26 sbi __lcd_port,__lcd_rd ;RD=1 cbi __lcd_port,__lcd_rs ;RS=0 __lcd_busy: rcall __lcd_delay sbi __lcd_port,__lcd_enable ;EN=1 rcall __lcd_delay in r26,__lcd_pin cbi __lcd_port,__lcd_enable ;EN=0 rcall __lcd_delay sbi __lcd_port,__lcd_enable ;EN=1 rcall __lcd_delay cbi __lcd_port,__lcd_enable ;EN=0 sbrc r26,__lcd_busy_flag rjmp __lcd_busy #endasm } #asm __lcd_write_nibble: andi r26,0xf0 or r26,r27 out __lcd_port,r26 ;write sbi __lcd_port,__lcd_enable ;EN=1 rcall __lcd_delay cbi __lcd_port,__lcd_enable ;EN=0 __lcd_delay: ldi r31,15 __lcd_delay0: dec r31 brne __lcd_delay0 ret #endasm void _lcd_write_data(unsigned char data) { #asm cbi __lcd_port,__lcd_rd ;RD=0 in r26,__lcd_direction ori r26,0xf7 ;set as output out __lcd_direction,r26 in r27,__lcd_port andi r27,0xf ld r26,y rcall __lcd_write_nibble ;RD=0, write MSN ld r26,y swap r26 rcall __lcd_write_nibble ;write LSN sbi __lcd_port,__lcd_rd ;RD=1 #endasm } /* write a byte to the LCD character generator or display RAM */ #if funcused lcd_write_byte void lcd_write_byte(unsigned char addr, unsigned char data) { _lcd_ready(); _lcd_write_data(addr); _lcd_ready(); #asm sbi __lcd_port,__lcd_rs ;RS=1 #endasm _lcd_write_data(data); } #endif #if funcused lcd_read_byte || funcused lcd_init #asm __lcd_read_nibble: sbi __lcd_port,__lcd_enable ;EN=1 rcall __lcd_delay in r30,__lcd_pin ;read cbi __lcd_port,__lcd_enable ;EN=0 rcall __lcd_delay andi r30,0xf0 ret #endasm static unsigned char lcd_read_byte0(void) { #asm rcall __lcd_delay rcall __lcd_read_nibble ;read MSN mov r26,r30 rcall __lcd_read_nibble ;read LSN cbi __lcd_port,__lcd_rd ;RD=0 swap r30 or r30,r26 #endasm } #endif #if funcused lcd_read_byte /* read a byte from the LCD character generator or display RAM */ unsigned char lcd_read_byte(unsigned char addr) { _lcd_ready(); _lcd_write_data(addr); _lcd_ready(); #asm in r26,__lcd_direction andi r26,0xf ;set as input out __lcd_direction,r26 sbi __lcd_port,__lcd_rs ;RS=1 #endasm return lcd_read_byte0(); } #endif /* set the LCD display position x=0..39 y=0..3 */ #if funcused lcd_gotoxy || funcused lcd_putchar || funcused lcd_puts || funcused lcd_putsf void lcd_gotoxy(unsigned char x, unsigned char y) { _lcd_ready(); // RS=0 _lcd_write_data(_base_y[y]+x+0x80); _lcd_x=x; _lcd_y=y; } #endif // clear the LCD #if funcused lcd_clear || funcused lcd_init void lcd_clear(void) { _lcd_ready(); // RS=0 _lcd_write_data(2); // cursor home _lcd_ready(); _lcd_write_data(0xc); // cursor off _lcd_ready(); _lcd_write_data(1); // clear _lcd_x=_lcd_y=0; } #endif #if funcused lcd_putchar || funcused lcd_puts || funcused lcd_putsf #pragma keep+ void lcd_putchar(char c) { #asm push r30 push r31 ld r26,y set cpi r26,10 breq __lcd_putchar1 clt #endasm ++_lcd_x; if (_lcd_x>_lcd_maxx) { #asm("__lcd_putchar1:") ++_lcd_y; lcd_gotoxy(0,_lcd_y); #asm("brts __lcd_putchar0") }; #asm rcall __lcd_ready sbi __lcd_port,__lcd_rs ;RS=1 ld r26,y st -y,r26 rcall __lcd_write_data __lcd_putchar0: pop r31 pop r30 #endasm } #pragma keep- #endif // write the string str located in SRAM to the LCD #if funcused lcd_puts void lcd_puts(char *str) { #ifdef _MODEL_TINY_ #asm clr r31 #endasm #endif #ifdef _MODEL_SMALL_ #asm ldd r31,y+1 #endasm #endif #asm ld r30,y __lcd_puts0: ld r26,z+ tst r26 breq __lcd_puts1 st -y,r26 rcall _lcd_putchar rjmp __lcd_puts0 __lcd_puts1: #endasm } #endif // write the string str located in FLASH to the LCD #if funcused lcd_putsf void lcd_putsf(char flash *str) { #asm ld r30,y ldd r31,y+1 __lcd_putsf0: #endasm #if defined _CHIP_ATMEGA128_ || defined _CHIP_ATMEGA128L_ #asm("elpm") #else #asm("lpm") #endif #asm tst r0 breq __lcd_putsf1 adiw r30,1 st -y,r0 rcall _lcd_putchar rjmp __lcd_putsf0 __lcd_putsf1: #endasm } #endif #if funcused lcd_init static void _long_delay(void) { #asm clr r26 clr r27 __long_delay0: sbiw r26,1 ;2 cycles brne __long_delay0 ;2 cycles #endasm } static void _lcd_init_write(unsigned char data) { #asm cbi __lcd_port,__lcd_rd ;RD=0 in r26,__lcd_direction ori r26,0xf7 ;set as output out __lcd_direction,r26 in r27,__lcd_port andi r27,0xf ld r26,y rcall __lcd_write_nibble ;RD=0, write MSN sbi __lcd_port,__lcd_rd ;RD=1 #endasm } // initialize the LCD controller unsigned char lcd_init (unsigned char lcd_columns) { #asm cbi __lcd_port,__lcd_enable ;EN=0 cbi __lcd_port,__lcd_rs ;RS=0 #endasm _lcd_maxx=lcd_columns; _base_y[0]=0; _base_y[1]=lcd_columns + 0x0C; _base_y[2]=lcd_columns + 0x2C; _base_y[3]=lcd_columns + 0x4C; _long_delay(); _lcd_init_write(0x30); _long_delay(); _lcd_init_write(0x30); _long_delay(); _lcd_init_write(0x30); _long_delay(); _lcd_init_write(0x20); _long_delay(); _lcd_init_write(0x24); _long_delay(); _lcd_write_data(0x09); // 4 Zeilen _long_delay(); _lcd_write_data(0x28); _long_delay(); _lcd_write_data(4); _long_delay(); _lcd_write_data(0x85);//85 _long_delay(); #asm in r26,__lcd_direction andi r26,0xf ;set as input out __lcd_direction,r26 sbi __lcd_port,__lcd_rd ;RD=1 #endasm if (lcd_read_byte0()!=5) return 0; _lcd_ready(); _lcd_write_data(6); lcd_clear(); return 1; } #endif
Hängt anscheinend mit den Zeilenadressen zusammen, siehe hier
https://www.roboternetz.de/phpBB2/viewtopic.php?t=56904
Hallo Hubert,
ich hab die Startadressen auf folgende Werte geändert.
Line 1=0x00
Line 2=0x0C
Line 3=0x40
Line 4=0x4C
Den ausgegebenen Text hab ich verkürzt ( Zeile 1 usw. )
Jetzt wird Zeile 1 bis 4 korrekt angezeigt.
Zeile 2 wird aber auch auf Zeile 1 position 13 bis 20 angezeigt.
Ich könnte also so nur die ersten 12 Zeichen des Displys nutzen, was natürlich Blödsinn ist.
Wenn ich nicht wegen der kleinen Bauform so ein Display benötigen würde, würde ich mir ein anderes raussuchen - Es nervt schön langsam...
Hallo Hubert,
das Problem ist anscheinend gelöst.
Die Original und auch meine bearbeitete Library sendeten während der initialisierungsphase nur das höherwertige Nibble an das Display.
Deshalb wurde es nicht richtig auf 4 Zeilen Modus initialisiert und machte diesen Quatsch.
Nachdem ich die Routine nun so geändert hab, das auch das lower Nibble übertragen wird funktionierts!
Die .lib pass für CodeVision AVR - Falls das Jemand braucht.
Hier die funktionierende Library LCDDIP204.c:
Und das dazugehörige Header File lcddip.h:Code:/* LCD driver routines CodeVisionAVR C Compiler (C) 1998-2004 Pavel Haiduc, HP InfoTech S.R.L. */ #asm .equ __lcd_direction=__lcd_port-1 .equ __lcd_pin=__lcd_port-2 .equ __lcd_rs=0 .equ __lcd_rd=1 .equ __lcd_enable=2 .equ __lcd_busy_flag=7 #endasm #pragma used+ static unsigned char _base_y[4]={0x80,0xc0}; unsigned char _lcd_x,_lcd_y,_lcd_maxx; #pragma used- void _lcd_ready(void) { #asm in r26,__lcd_direction andi r26,0xf ;set as input out __lcd_direction,r26 sbi __lcd_port,__lcd_rd ;RD=1 cbi __lcd_port,__lcd_rs ;RS=0 __lcd_busy: rcall __lcd_delay sbi __lcd_port,__lcd_enable ;EN=1 rcall __lcd_delay in r26,__lcd_pin cbi __lcd_port,__lcd_enable ;EN=0 rcall __lcd_delay sbi __lcd_port,__lcd_enable ;EN=1 rcall __lcd_delay cbi __lcd_port,__lcd_enable ;EN=0 sbrc r26,__lcd_busy_flag rjmp __lcd_busy #endasm } #asm __lcd_write_nibble: andi r26,0xf0 or r26,r27 out __lcd_port,r26 ;write sbi __lcd_port,__lcd_enable ;EN=1 rcall __lcd_delay cbi __lcd_port,__lcd_enable ;EN=0 __lcd_delay: ldi r31,15 __lcd_delay0: dec r31 brne __lcd_delay0 ret #endasm void _lcd_write_data(unsigned char data) { #asm cbi __lcd_port,__lcd_rd ;RD=0 in r26,__lcd_direction ori r26,0xf7 ;set as output out __lcd_direction,r26 in r27,__lcd_port andi r27,0xf ld r26,y rcall __lcd_write_nibble ;RD=0, write MSN ld r26,y swap r26 rcall __lcd_write_nibble ;write LSN sbi __lcd_port,__lcd_rd ;RD=1 #endasm } /* write a byte to the LCD character generator or display RAM */ #if funcused lcd_write_byte void lcd_write_byte(unsigned char addr, unsigned char data) { _lcd_ready(); _lcd_write_data(addr); _lcd_ready(); #asm sbi __lcd_port,__lcd_rs ;RS=1 #endasm _lcd_write_data(data); } #endif #if funcused lcd_read_byte || funcused lcd_init #asm __lcd_read_nibble: sbi __lcd_port,__lcd_enable ;EN=1 rcall __lcd_delay in r30,__lcd_pin ;read cbi __lcd_port,__lcd_enable ;EN=0 rcall __lcd_delay andi r30,0xf0 ret #endasm static unsigned char lcd_read_byte0(void) { #asm rcall __lcd_delay rcall __lcd_read_nibble ;read MSN mov r26,r30 rcall __lcd_read_nibble ;read LSN cbi __lcd_port,__lcd_rd ;RD=0 swap r30 or r30,r26 #endasm } #endif #if funcused lcd_read_byte /* read a byte from the LCD character generator or display RAM */ unsigned char lcd_read_byte(unsigned char addr) { _lcd_ready(); _lcd_write_data(addr); _lcd_ready(); #asm in r26,__lcd_direction andi r26,0xf ;set as input out __lcd_direction,r26 sbi __lcd_port,__lcd_rs ;RS=1 #endasm return lcd_read_byte0(); } #endif /* set the LCD display position x=0..39 y=0..3 */ #if funcused lcd_gotoxy || funcused lcd_putchar || funcused lcd_puts || funcused lcd_putsf void lcd_gotoxy(unsigned char x, unsigned char y) { _lcd_ready(); // RS=0 _lcd_write_data(_base_y[y]+x+0x80); _lcd_x=x; _lcd_y=y; } #endif // clear the LCD #if funcused lcd_clear || funcused lcd_init void lcd_clear(void) { _lcd_ready(); // RS=0 _lcd_write_data(2); // cursor home _lcd_ready(); _lcd_write_data(0xc); // cursor off _lcd_ready(); _lcd_write_data(1); // clear _lcd_x=_lcd_y=0; } #endif #if funcused lcd_putchar || funcused lcd_puts || funcused lcd_putsf #pragma keep+ void lcd_putchar(char c) { #asm push r30 push r31 ld r26,y set cpi r26,10 breq __lcd_putchar1 clt #endasm ++_lcd_x; if (_lcd_x>_lcd_maxx) { #asm("__lcd_putchar1:") ++_lcd_y; lcd_gotoxy(0,_lcd_y); #asm("brts __lcd_putchar0") }; #asm rcall __lcd_ready sbi __lcd_port,__lcd_rs ;RS=1 ld r26,y st -y,r26 rcall __lcd_write_data __lcd_putchar0: pop r31 pop r30 #endasm } #pragma keep- #endif // write the string str located in SRAM to the LCD #if funcused lcd_puts void lcd_puts(char *str) { #ifdef _MODEL_TINY_ #asm clr r31 #endasm #endif #ifdef _MODEL_SMALL_ #asm ldd r31,y+1 #endasm #endif #asm ld r30,y __lcd_puts0: ld r26,z+ tst r26 breq __lcd_puts1 st -y,r26 rcall _lcd_putchar rjmp __lcd_puts0 __lcd_puts1: #endasm } #endif // write the string str located in FLASH to the LCD #if funcused lcd_putsf void lcd_putsf(char flash *str) { #asm ld r30,y ldd r31,y+1 __lcd_putsf0: #endasm #if defined _CHIP_ATMEGA128_ || defined _CHIP_ATMEGA128L_ #asm("elpm") #else #asm("lpm") #endif #asm tst r0 breq __lcd_putsf1 adiw r30,1 st -y,r0 rcall _lcd_putchar rjmp __lcd_putsf0 __lcd_putsf1: #endasm } #endif #if funcused lcd_init static void _long_delay(void) { #asm clr r26 clr r27 __long_delay0: sbiw r26,1 ;2 cycles brne __long_delay0 ;2 cycles #endasm } static void _lcd_init_write(unsigned char data) { #asm cbi __lcd_port,__lcd_rd ;RD=0 in r26,__lcd_direction ori r26,0xf7 ;set as output out __lcd_direction,r26 in r27,__lcd_port andi r27,0xf ld r26,y rcall __lcd_write_nibble ;RD=0, write MSN ld r26,y swap r26 rcall __lcd_write_nibble ;write LSN sbi __lcd_port,__lcd_rd ;RD=1 #endasm } // initialize the LCD controller unsigned char lcd_init (unsigned char lcd_columns) { #asm cbi __lcd_port,__lcd_enable ;EN=0 cbi __lcd_port,__lcd_rs ;RS=0 #endasm _lcd_maxx=lcd_columns; _base_y[0]=0x00; _base_y[1]=lcd_columns + 0x0C; _base_y[2]=lcd_columns + 0x2C; _base_y[3]=lcd_columns + 0x4C; _long_delay(); _lcd_init_write(0x24); // 4 Bit Modus + RE Bit set _long_delay(); _lcd_write_data(0x09); // 4 Zeilen _long_delay(); _lcd_write_data(0x20); // 4 Bit Modus + RE Bit clear _long_delay(); _lcd_write_data(0x0C); // Display On _long_delay(); _lcd_write_data(0x01); // Clear Display _long_delay(); _lcd_write_data(0x06); //Auto Increment on _long_delay(); #asm in r26,__lcd_direction andi r26,0xf ;set as input out __lcd_direction,r26 sbi __lcd_port,__lcd_rd ;RD=1 #endasm if (lcd_read_byte0()!=5) return 0; _lcd_ready(); _lcd_write_data(6); lcd_clear(); return 1; } #endif
Code:/* LCD driver routines CodeVisionAVR C Compiler (C) 1998-2000 Pavel Haiduc, HP InfoTech S.R.L. BEFORE #include -ING THIS FILE YOU MUST DECLARE THE I/O ADDRESS OF THE DATA REGISTER OF THE PORT AT WHICH THE LCD IS CONNECTED! EXAMPLE FOR PORTB: #asm .equ __lcd_port=0x18 #endasm #include <lcddip.h> Copy the File LCDDIP204.lib into the entire folder */ #ifndef _LCD_INCLUDED_ #define _LCD_INCLUDED_ #pragma used+ void _lcd_ready(void); void _lcd_write_data(unsigned char data); // write a byte to the LCD character generator or display RAM void lcd_write_byte(unsigned char addr, unsigned char data); // read a byte from the LCD character generator or display RAM unsigned char lcd_read_byte(unsigned char addr); // set the LCD display position x=0..39 y=0..3 void lcd_gotoxy(unsigned char x, unsigned char y); // clear the LCD void lcd_clear(void); void lcd_putchar(char c); // write the string str located in SRAM to the LCD void lcd_puts(char *str); // write the string str located in FLASH to the LCD void lcd_putsf(char flash *str); // initialize the LCD controller unsigned char lcd_init(unsigned char lcd_columns); #pragma used- #pragma library LCDDIP204.c #endif
Lesezeichen