Datum: 15.01.2008 14:51
Habe zwar die LCD-Routine aus dem AVR-GCC-Tutorial mit Erfolg getestet: Lcd.c:
#include <avr/io.h> #include "lcd-routines.h" int main(void){ lcd_string("Hello World!"); while(1); return 0; } |
Leider habe ich aber eine vorgegebene Hardware, an der RS und EN nicht an PD4 bzw. PD5 liegen, sondern #define LCD_RS PB7 #define LCD_EN PB6 Diese Umdefinitionen reichen allein natürlich nicht aus, um das Programm wieder zum Laufen zu bringen. Habe auch keine Ahnung vom AVR (Kenne nur 8051, wo man mit sbit RS=P1^2; und dann RS=1; einzelne Portleitungen setzen kann) und weiß nicht wie das bei Atmel geht, geschweige denn, was so komplexe Sequenzen wie LCD_DDR = LCD_DDR | 0x0F | (1<<LCD_RS) | (1<<LCD_EN); genau machen. Vielleicht findet sich ja hier ein Profi, der sich herausgefordert fühlt das zu realisieren (oder hat so etwas schon einmal für verschiedene Portpins gemacht)? Wäre sehr, sehr dankbar, wenn er es hier posten könnte !!! ------------------------------------------------------------------------------------------------------------------------ Hier nochmal alle Quelltexte: lcd-routines.h:
void lcd_data(unsigned char temp1); void lcd_string(char *data); void lcd_command(unsigned char temp1); void lcd_enable(void); void lcd_init(void); void lcd_home(void); void lcd_clear(void); void set_cursor(uint8_t x, uint8_t y); #define F_CPU 8000000 #define CLEAR_DISPLAY 0x01 #define CURSOR_HOME 0x02 #define LCD_PORT PORTD #define LCD_DDR DDRD #define LCD_RS PD4 #define LCD_EN PD5 |
lcd-routines.c:
#include <avr/io.h> #include "lcd-routines.h" #include <util/delay.h> void lcd_data(unsigned char temp1) { unsigned char temp2 = temp1; LCD_PORT |= (1<<LCD_RS); // RS auf 1 setzen temp1 = temp1 >> 4; temp1 = temp1 & 0x0F; LCD_PORT &= 0xF0; LCD_PORT |= temp1; // setzen lcd_enable(); temp2 = temp2 & 0x0F; LCD_PORT &= 0xF0; LCD_PORT |= temp2; // setzen lcd_enable(); _delay_us(42); } void lcd_command(unsigned char temp1) { unsigned char temp2 = temp1; LCD_PORT &= ~(1<<LCD_RS); // RS auf 0 setzen temp1 = temp1 >> 4; // oberes Nibble holen temp1 = temp1 & 0x0F; // maskieren LCD_PORT &= 0xF0; LCD_PORT |= temp1; // setzen lcd_enable(); temp2 = temp2 & 0x0F; // unteres Nibble holen und maskieren LCD_PORT &= 0xF0; LCD_PORT |= temp2; // setzen lcd_enable(); _delay_us(42); } void lcd_enable(void) { LCD_PORT |= (1<<LCD_EN); _delay_us(1); // kurze Pause LCD_PORT &= ~(1<<LCD_EN); } void lcd_init(void) { LCD_DDR = LCD_DDR | 0x0F | (1<<LCD_RS) | (1<<LCD_EN); // Port auf Ausgang schalten _delay_ms(15); LCD_PORT &= 0xF0; LCD_PORT |= 0x03; LCD_PORT &= ~(1<<LCD_RS); // RS auf 0 lcd_enable(); _delay_ms(5); lcd_enable(); _delay_ms(1); lcd_enable(); _delay_ms(1); LCD_PORT &= 0xF0; LCD_PORT |= 0x02; lcd_enable(); _delay_ms(1); lcd_command(0x28); lcd_command(0x0C); lcd_command(0x06); lcd_clear(); } void lcd_clear(void) { lcd_command(CLEAR_DISPLAY); _delay_ms(5); } void lcd_home(void) { lcd_command(CURSOR_HOME); _delay_ms(5); } void set_cursor(uint8_t x, uint8_t y) { uint8_t tmp; switch (y) { case 1: tmp=0x80+0x00+x; break; // 1. Zeile case 2: tmp=0x80+0x40+x; break; // 2. Zeile case 3: tmp=0x80+0x10+x; break; // 3. Zeile case 4: tmp=0x80+0x50+x; break; // 4. Zeile } lcd_command(tmp); } void lcd_string(char *data) { while(*data) { lcd_data(*data); data++; } } |
Datum: 15.01.2008 15:18
Hans Mustermann wrote: > Habe zwar die LCD-Routine aus dem AVR-GCC-Tutorial mit Erfolg getestet: > Lcd.c: >
> #include <avr/io.h> > #include "lcd-routines.h" > int main(void){ > lcd_string("Hello World!"); > while(1); > return 0; > } > |
> > Leider habe ich aber eine vorgegebene Hardware, an der RS und EN nicht > an PD4 bzw. PD5 liegen, sondern > #define LCD_RS PB7 > #define LCD_EN PB6 Was ist mit den restlichen Datenleitungen? Liegen die ebenfalls am Port B? Welche Pins? Wenn die Datenleitungen ebenfalls am PORTB, Pins PB0 bis PB4 liegen, dann reichen folgende Änderungen aus: > #define LCD_PORT PORTB > #define LCD_DDR DDRB > #define LCD_RS PB7 > #define LCD_EN PB6 und das LCD sollte am PortB laufen.
Datum: 15.01.2008 15:41
Pin #-LCD Bezeichnung-LCD Pin-µC 1 Vss GND 2 Vcc 5V 3 Vee GND oder Poti (siehe oben) 4 RS PD4 am AVR 5 RW GND 6 E PD5 am AVR 7 DB0 offen 8 DB1 offen 9 DB2 offen 10 DB3 offen 11 DB4 PD0 am AVR 12 DB5 PD1 am AVR 13 DB6 PD2 am AVR 14 DB7 PD3 am AVR das oben steht in der beschreibung. also musste db4 bis db7 an port0-port3 anschliessen.
Datum: 15.01.2008 17:12
Wenn die Datenleitungen wie im Tutorial an PORTD liegen und nur die Steuerleitungen wie von dir angegeben an PORTB, dann könntest du so vorgehen
#define LCD_PORT PORTD #define LCD_DDR DDRD #define LCD_RS PD4 #define LCD_EN PD5 |
ersetzt du durch
#define LCD_CTRL_PORT PORTB #define LCD_CTRL_DDR DDRB #define LCD_RS PB7 #define LCD_EN PB6 #define LCD_DATA_PORT PORTD #define LCD_DATA_DDR DDRD |
In jedem Statement (Zeile) mit LCD_RS oder LCD_EN ersetzt du LCD_PORT durch LCD_CTRL_PORT. Und in jeder anderen Zeile mit LCD_PORT ersetzt du LCD_PORT durch LCD_DATA_PORT Den Abschnitt
// Port auf Ausgang schalten LCD_DDR = LCD_DDR | 0x0F | (1<<LCD_RS) | (1<<LCD_EN); |
ersetzt du durch
// Ports auf Ausgang schalten LCD_DATA_DDR = LCD_DATA_DDR | 0x0F; LCD_CTRL_DDR = LCD_CTRL_DDR | (1<<LCD_RS) | (1<<LCD_EN); |
Datum: 16.01.2008 00:43
kbuchegg wrote: >Wenn die Datenleitungen ebenfalls am PORTB, Pins PB0 bis PB4 liegen, >dann reichen folgende Änderungen aus: ... Für so eine einfache Portsubstitution hätte ich dann doch das Forum nicht bemüht :) stefan wrote: >... Habe jetzt wie beschrieben #define LCD_CTRL_PORT PORTB #define LCD_CTRL_DDR DDRB #define LCD_RS PB7 #define LCD_EN PB6 #define LCD_DATA_PORT PORTD #define LCD_DATA_DDR DDRD und in LCD_RS- bzw LCD_EN-Zeilen LCD_PORT durch LCD_CTRL_PORT ersetzt und in jeder anderen Zeil LCD_PORT durch LCD_DATA_PORT ersetzt und es klappt tatsächlich! Weiß nur noch nicht ganz sicher, ob alle andern, "freien" Pins (PD4...PD7 und PB0...PB5) noch uneingeschränkt anderweitige Aufgaben erfüllen können, ohne von LCD-Routinen beeinflußt zu werden. Denn für einen AVR-Neuling sind im Gegensatz zu RS=1 bei Intel so Arten von “Schiebeoperationen“ zum Portsetzen wie PORTB |= (1<<PB0); doch etwas kryptisch (muß mich bei Zeiten mal da einarbeiten; auch ADW und Interruptsteuerung...). Dank‘ Dir auf jeden Fall Stefan für die Hilfe!
Datum: 16.01.2008 09:32
Hans Mustermann wrote: > kbuchegg wrote: >>Wenn die Datenleitungen ebenfalls am PORTB, Pins PB0 bis PB4 liegen, >>dann reichen folgende Änderungen aus: ... > Für so eine einfache Portsubstitution hätte ich dann doch das Forum > nicht bemüht :) Dann solltest du dir zumindest vormerken, das nächste vollständige Angaben in einer Anfrage zu machen :-)
Datum: 16.01.2008 09:49
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial da drin ist die lcd-routine ein bisschen beschissen erstellt worden. der lernende fragt sich , wo werden die pins0-pins3 in den routinen herausgestellt. es ist kein bezug da. also, wenn was dargestellt werder soll, ein bisschen mehr licht ins dunkel, dann hört auch die diskussion auf.
Datum: 16.01.2008 10:34
klaus wrote: > http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial > > da drin ist die lcd-routine ein bisschen beschissen erstellt worden. Ein "bisschen beschissen" gibt es nicht. Du solltest dir überlegen, welche Motivation du einem Artikelautor mit einem solchen Statement gibst, für dich und andere das Tutorial zu verbessern. Nein, ich bin nicht der Autor. Ja, ich finde, der Autor hat gute Arbeit geleistet. > der lernende fragt sich , wo werden die pins0-pins3 in den routinen > herausgestellt. es ist kein bezug da. > > also, wenn was dargestellt werder soll, ein bisschen mehr licht ins > dunkel, dann hört auch die diskussion auf. Ich habe versucht aus deinem Text deinen Wunsch heraus zu klauben. Wenn es darum geht anzuzeigen, wo die Leitungen DB4 bis DB8 des LCD am AVR angeschlossen sind, dann steht das im Tutorialtext eindeutig drin. In dem Sourcecode steht es nicht eindeutig drin. Die Pinbelegung habe ich mit einem Kommentar im Quelltext ergänzt. Ich hoffe, das ist auch im Sinn des Tutorialautors.
Datum: 16.01.2008 12:06
klaus wrote: > http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial > > da drin ist die lcd-routine ein bisschen beschissen erstellt worden. > der lernende fragt sich , wo werden die pins0-pins3 in den routinen > herausgestellt. es ist kein bezug da. Es wird auch davon ausgegangen, dass 'der Lernende' zumindest über Grundkenntnisse in C verfügt, bevor er sich an ein LCD wagt. Für jemanden mit Grundkenntnissen, der auch bereit ist den Code den er da abtippt zu verstehen, ist es absolut kein Problem im veröffentlichten Code die entsprechenden Stellen zu finden, zu verstehen und zu ändern.
Datum: 16.01.2008 13:41
Hans Mustermann wrote: > Habe auch keine Ahnung vom AVR (Kenne nur 8051, wo man mit sbit RS=P1^2; > und dann RS=1; einzelne Portleitungen setzen kann) und weiß nicht wie > das bei Atmel geht Eigentlich ganz genau so, wie beim 8051, nur daß man noch die Direction-Bits setzen muß. Die Bitzugriffe kann man mit einem Macro (SBIT) definieren. Anbei mal ein Beispiel für 2*40 LCD im 4Bit-Mode mit jedem beliebigen Pin. Peter
Datum: 18.01.2008 13:02
...Für jemanden mit Grundkenntnissen, der auch bereit ist den Code den er da abtippt zu verstehen, ist es absolut kein Problem im veröffentlichten Code die entsprechenden Stellen zu finden, zu verstehen und zu ändern.... da sehe ich in einem tut anders, da gehört aufklärung rein, auch im code.
Datum: 18.01.2008 13:04
....Anbei mal ein Beispiel für 2*40 LCD im 4Bit-Mode mit jedem beliebigen Pin....... dieses beispiel ist auch für anfänger wunderbar geschrieben, klasse. mfg
Datum: 18.01.2008 13:17
typedef unsigned char u8; typedef signed char s8; typedef unsigned short u16; typedef signed short s16; typedef unsigned long u32; typedef signed long s32; welchen vorzug hat diese schreibweise? text zu sparen? u8 statt uint8_t !
Datum: 18.01.2008 13:17
roboter wrote: > ...Für jemanden mit Grundkenntnissen, der auch bereit ist > den Code den er da abtippt zu verstehen, ist es absolut kein > Problem im veröffentlichten Code die entsprechenden Stellen > zu finden, zu verstehen und zu ändern.... > > da sehe ich in einem tut anders, da gehört aufklärung rein, auch im > code. Ist ganz einfach. Wenn du denkst, dass diese Stellen nicht gut genug einen Sachverhalt beschreiben, dann ändere sie. Genau aus diesem Grund ist das ja ein Wiki.
Datum: 14.05.2008 13:23
Warum wird eigentlich bei dir der C code So Farbig angezeigt? Bei mir geht das garnicht! Das beispiel von Peter Danneger klappt super! Damit habe ich vorhin zum ersten mal ein Display angesteuert!
Datum: 15.05.2008 17:47
Ich hab mal den Code verändert. "3 mal w".verleihnix.890m.com/index.php?p=1_16 der nimmt meine URL sonst nicht an die lcd-routines.h
// Ansteuerung eines HD44780 kompatiblen LCD im 4-Bit-Interfacemodus // http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial // void lcd_string(char *data); void lcd_enable(void); void lcd_init(void); void lcd_home(void); void lcd_clear(void); void set_cursor(uint8_t x, uint8_t y); // Hier die verwendete Taktfrequenz in Hz eintragen, wichtig! #define F_CPU 8000000 // LCD Befehle #define CLEAR_DISPLAY 0x01 #define CURSOR_HOME 0x02 // Pinbelegung für das LCD, an verwendete Pins anpassen #define LCD_PORT_4 PORTD #define LCD_DDR_4 DDRD #define LCD_D4 PD1 #define LCD_PORT_5 PORTC #define LCD_DDR_5 DDRC #define LCD_D5 PC1 #define LCD_PORT_6 PORTC #define LCD_DDR_6 DDRC #define LCD_D6 PC2 #define LCD_PORT_7 PORTC #define LCD_DDR_7 DDRC #define LCD_D7 PC3 #define LCD_RS_PORT PORTC #define LCD_RS_DDR DDRC #define LCD_RS PC5 #define LCD_EN1_PORT PORTB #define LCD_EN1_DDR DDRB #define LCD_EN1 PB0 |
die lcd-routines.c
// Ansteuerung eines HD44780 kompatiblen LCD im 4-Bit-Interfacemodus // http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial // // Die Pinbelegung ist über defines in lcd-routines.h einstellbar #include <avr/io.h> #include "lcd-routines.h" #include <util/delay.h> // sendet ein Datenbyte an das LCD void lcd_data(unsigned char temp1) { unsigned char temp2 = temp1; LCD_RS_PORT |= (1<<LCD_RS); // RS auf 1 setzen temp1 = temp1 >> 4; temp1 = temp1 & 0x0F; LCD_PORT_4 &= ~(1<<LCD_D4); LCD_PORT_5 &= ~(1<<LCD_D5); LCD_PORT_6 &= ~(1<<LCD_D6); LCD_PORT_7 &= ~(1<<LCD_D7); if(temp1 & 0x01) LCD_PORT_4 |=(1<<LCD_D4) ;// setzen if(temp1 & 0x02) LCD_PORT_5 |=(1<<LCD_D5) ; if(temp1 & 0x04) LCD_PORT_6 |=(1<<LCD_D6) ; if(temp1 & 0x08) LCD_PORT_7 |=(1<<LCD_D7) ; lcd_enable(); temp2 = temp2 & 0x0F; LCD_PORT_4 &= ~(1<<LCD_D4); LCD_PORT_5 &= ~(1<<LCD_D5); LCD_PORT_6 &= ~(1<<LCD_D6); LCD_PORT_7 &= ~(1<<LCD_D7); if(temp2 & 0x01) LCD_PORT_4 |=(1<<LCD_D4) ;// setzen if(temp2 & 0x02) LCD_PORT_5 |=(1<<LCD_D5) ; if(temp2 & 0x04) LCD_PORT_6 |=(1<<LCD_D6) ; if(temp2 & 0x08) LCD_PORT_7 |=(1<<LCD_D7) ; lcd_enable(); _delay_us(42); } // sendet einen Befehl an das LCD void lcd_command(unsigned char temp1) { unsigned char temp2 = temp1; LCD_RS_PORT &= ~(1<<LCD_RS); // RS auf 0 setzen temp1 = temp1 >> 4; // oberes Nibble holen temp1 = temp1 & 0x0F; LCD_PORT_4 &= ~(1<<LCD_D4); LCD_PORT_5 &= ~(1<<LCD_D5); LCD_PORT_6 &= ~(1<<LCD_D6); LCD_PORT_7 &= ~(1<<LCD_D7); // maskieren if(temp1 & 0x01) LCD_PORT_4 |=(1<<LCD_D4) ;// setzen if(temp1 & 0x02) LCD_PORT_5 |=(1<<LCD_D5) ; if(temp1 & 0x04) LCD_PORT_6 |=(1<<LCD_D6) ; if(temp1 & 0x08) LCD_PORT_7 |=(1<<LCD_D7) ; lcd_enable(); temp2 = temp2 & 0x0F; LCD_PORT_4 &= ~(1<<LCD_D4); LCD_PORT_5 &= ~(1<<LCD_D5); LCD_PORT_6 &= ~(1<<LCD_D6); LCD_PORT_7 &= ~(1<<LCD_D7); // unteres Nibble holen und maskieren if(temp2 & 0x01) LCD_PORT_4 |=(1<<LCD_D4) ;// setzen if(temp2 & 0x02) LCD_PORT_5 |=(1<<LCD_D5) ; if(temp2 & 0x04) LCD_PORT_6 |=(1<<LCD_D6) ; if(temp2 & 0x08) LCD_PORT_7 |=(1<<LCD_D7) ; lcd_enable(); _delay_us(42); } // erzeugt den Enable-Puls void lcd_enable(void) { // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers einfügen // http://www.mikrocontroller.net/topic/81974#685882 LCD_EN1_PORT |= (1<<LCD_EN1); _delay_us(1); // kurze Pause // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers verlängern // http://www.mikrocontroller.net/topic/80900 LCD_EN1_PORT &= ~(1<<LCD_EN1); } // Initialisierung: // Muss ganz am Anfang des Programms aufgerufen werden. void lcd_init(void) { // Ports auf Ausgang schalten LCD_DDR_4 |=(1<<LCD_D4); LCD_DDR_5 |=(1<<LCD_D5); LCD_DDR_6 |=(1<<LCD_D6); LCD_DDR_7 |=(1<<LCD_D7); LCD_EN1_DDR |= (1<<LCD_EN1); LCD_RS_DDR |= (1<<LCD_RS); // muss 3mal hintereinander gesendet werden zur Initialisierung _delay_ms(15); LCD_PORT_4 |= (1<<LCD_D4); LCD_PORT_5 |= (1<<LCD_D5); LCD_PORT_6 &= ~(1<<LCD_D6); LCD_PORT_7 &= ~(1<<LCD_D7); LCD_RS_PORT &= ~(1<<LCD_RS); // RS auf 0 lcd_enable(); _delay_ms(5); lcd_enable(); _delay_ms(1); lcd_enable(); _delay_ms(1); // 4 Bit Modus aktivieren LCD_PORT_4 &= ~(1<<LCD_D4); LCD_PORT_5 |= (1<<LCD_D5); LCD_PORT_6 &= ~(1<<LCD_D6); LCD_PORT_7 &= ~(1<<LCD_D7); lcd_enable(); _delay_ms(1); // 4Bit / 2 Zeilen / 5x7 lcd_command(0x28); // Display ein / Cursor aus / kein Blinken lcd_command(0x0C); // inkrement / kein Scrollen lcd_command(0x06); lcd_clear(); } // Sendet den Befehl zur Löschung des Displays void lcd_clear(void) { lcd_command(CLEAR_DISPLAY); _delay_ms(5); } // Sendet den Befehl: Cursor Home void lcd_home(void) { lcd_command(CURSOR_HOME); _delay_ms(5); } // setzt den Cursor in Zeile y (1..4) Spalte x (0..15) void set_cursor(uint8_t x, uint8_t y) { uint8_t tmp; switch (y) { case 1: tmp=0x80+0x00+x; break; // 1. Zeile case 2: tmp=0x80+0x40+x; break; // 2. Zeile case 3: tmp=0x80+0x10+x; break; // 3. Zeile case 4: tmp=0x80+0x50+x; break; // 4. Zeile } lcd_command(tmp); } // Schreibt einen String auf das LCD void lcd_string(char *data) { while(*data) { lcd_data(*data); data++; } } |
falls es Fehler gibt bitte melden Ich hoffe ich konnte helfen
Antwort schreiben
Die Angabe einer Email-Adresse ist freiwillig. Wenn Sie automatisch per Email über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.
Wichtige Regeln - erst lesen, dann posten!
- Suchfunktion und Betreffsuche benutzen - vielleicht gibt es schon einen ähnlichen Beitrag
- Aussagekräftigen Betreff wählen
- Im Betreff angeben um welchen Controllertyp es geht (AVR, PIC, ...)
- Groß- und Kleinschreibung verwenden
- Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
- JPEG-Dateien (.jpg) nur für Fotos und Scans verwenden
- Schaltpläne, Screenshots usw. als PNG oder GIF anhängen
Formatierung (mehr Informationen...)
- [c]C-Code[/c]
- [avrasm]AVR-Assembler-Code[/avrasm]
- [pre]vorformatierter Text (z.B. Code in anderen Sprachen)[/pre]
- [math]Formel in LaTeX-Syntax[/math]
- [[Titel]] - Link zu Artikel