Hallo Liebes Forum, ich sitze momentan an einem kleinen Projekt. Dieses soll unter anderm ein LCD Display erhalten (http://www.reichelt.de/LCD-Module-DIP-Anschluss/LCD-162-DIP/index.html?;ACTION=3;LA=2;ARTICLE=44903;GROUPID=3009;SID=11Th2Htn8AAAIAAGC37UA583d34fa1d7eea237f05d23b8e140395). In diesem Tutorial (http://www.mikrocontroller.net/articles/AVR-Tutorial:_LCD) habe ich gelesen, dass man durch Setzen oder nicht setzen von RW unter anderem das Busy Flag auslesen kann. Das kommt ja, wenn man das LCD im 8bit betrieb laufen lässt auf Port7 des LCD. Ich würde das LCD auch gerne im 8bit Modus laufen lassen, da ich nicht so viele Ports brauche, und es somit auch schneller sein sollte (oder irre ich mich da ? ) auf jedenfall angenehmer anzusteuern :D. Das ganze soll in GCC programmiert werden. Meine frage nun: wie kann ich einen Port in GCC als Ausgang und als Eingang (gleichzeitig benutzen) ??. Durch DDRC = 0xFF setze ich ja alle ports als ausgang (oder verwechsel ich das gerade ?? ). Habe einen kleinen Code ausschnitt (ich denke aber er ist falsch ^^ aber keine Ahnung, wie er richtig sein sollte ...) LCD DDR wird vorher auf 0xFF gesetzt. static void lcd_enable( void ) { LCD_PORT |= (1<<LCD_EN); // Enable auf 1 setzen while(LCD_PORT != 0x80) // Auf Busy flag Warten LCD_PORT &= ~(1<<LCD_EN); // Enable auf 0 setzen } MfG GnR1993 wenn meine Fragestellung unklar ist, dann schreibt das bitte ;) .. und auch bitte was ihr nicht versteht, damit ich euch die fehlenden Informationen geben kann. Danke schonmal im vorraus ;)
LCD ist beui mir schon etwas her. Weiß also deswegen gerade nicht ob es eine extra Busy-Leitung hatte, wenn nicht musst du halt nach absenden deiner Befehle den Portpin als Eingang umschalten. Ich programmiere ja in Assembler und habe mir für solche Zwecke die binäre Schreibweise angewöhnt. Da man da gleich sieht wie die Pins geschalten sind, bei hex ist halt nur FF und 00 und bei dez 255 und 0 auf den ersten Blick eindeutig. ldi temp, 0b11111111 out DDRC, temp ;Alle PortC Pins als Ausgang Befehle und Daten verschicken ldi temp, 0b01111111 ;PinC7 als Eingang Rest Ausgang out DDRC, temp Auf busy prüfen danach Port wieder als Ausgang umschalten
Für den GCC wäre das Tutorial passender: http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung Wegen dem RW, schau Dir mal die LCD-Lib von Peter Fleury an: http://homepage.hispeed.ch/peterfleury/avr-software.html#libs Bei der wird auch vom LCD gelesen.
Erstens kannst du nicht gleichzeitig Ports als Eingang und Ausgang setzen. Zweitens brauchst du das auch gar nicht: nur solange du etwas ausgibst, muß man mit DDR... auf Ausgang setzen, solange du etwas einliest als Eingang. Drittens kannst du nicht nur alleine das BUSY abfragen; du musst vielmehr per DDR... alle Datenbits als Eingang setzen, RS auf 0, RW auf 1, EN auf 1 und damit liest du alle 8 Datenbit. Davon interessiert dich nur BUSY, damit kannst du machen was du willst und vor dem nächsten Schreiben musst du wieder DDR... auf Ausgang aetzen.
Danke für die ganzen schnellen Antworten (echt gute Community :P ) @ ...: Ja, das Tutorial habe ich gelesen, aber es benutzt 4Bit und warte Zeiten ;) ich will mir aber die Warte Zeiten sparen und das ganze über Busy machen :P @Klaus: klar, will ja nicht den anderen ports nen High Pegel geben und dann nur von einem lesen ;), will ja nicht mein LCD zerstören :D ... also muss ich das ganze dann wahrscheinlich so machen: (LCD an Port C , RW, RS und E auf Port A) C-Code:
1 | #define LCD_PORT PORTC
|
2 | #define LCD_DDR DDRC
|
3 | #define LCD_ADD_PORT PORTA
|
4 | |
5 | |
6 | static void lcd_enable( void ) |
7 | {
|
8 | |
9 | LCD_ADD_PORT |= (1<<LCD_EN) | (1<<LCD_RW) ; // Enable auf 1 setzen |
10 | LCD_DDR = 0b00000000; |
11 | while(LCD_PORT != 0b10000000); // Auf Busy flag Warten |
12 | LCD_ADD_PORT &= ~(1<<LCD_EN); // Enable auf 0 setzen |
13 | |
14 | }
|
15 | |
16 | //Dann wäre ja hier alle meine LCD datenbytes auf READ, oder?
|
17 | //Und wenn ich dann schreiben will, würde ja folgendes kommen:
|
18 | |
19 | void lcd_command( uint8_t data ) |
20 | {
|
21 | LCD_ADD_PORT &= ~(1<<LCD_RS); // RS auf 0 setzen |
22 | LCD_ADD_PORT &= ~(1<<LCD_RW); // RW auf 0 setzen |
23 | LCD_DDR = 0b11111111; |
24 | lcd_out( data ); // Bits Senden |
25 | LCD_DDR = 0b00000000; |
26 | LCD_ADD_PORT |= (1<<LCD_RW); |
27 | while(LCD_PORT != 0b10000000); // Auf Busy flag Warten |
28 | |
29 | }
|
So müsste das ganze doch aussehen, oder? @Thomas ;) ich persönlich komm mit der Umrechnung absolut klar :D is ja auch eigentlich simpel :D .. maximal F und 0001 is ja ne eins 0010 ne 2 und sow weiter ;) und wenn man die dann addiert, hat man das gesamte :D PS: ich weiß auch, dass du das wahrscheinlich wusstest :P MfG GnR1993
und eine hex53? Hand aufs Herz auf den ersten Blick erkennt man das nur in Binär welcher Portpin was macht.
Patrick Nies schrieb: > Danke für die ganzen schnellen Antworten (echt gute Community :P ) > @ ...: Ja, das Tutorial habe ich gelesen, aber es benutzt 4Bit und warte > Zeiten ;) ich will mir aber die Warte Zeiten sparen und das ganze über > Busy machen :P Macht aber im Endeffekt keinen bis kaum einen Unterschied. Denn das lesen des Busy Bits gibts nun mal nicht gratis (= kostet auch Zeit). Und Hand aufs Herz. Auch mit Warten kannst du immer noch schneller aufs LCD schreiben, als irgendein Mensch lesen kann.
Thomas O. schrieb: > und eine hex53? Hand aufs Herz auf den ersten Blick erkennt man das nur > in Binär welcher Portpin was macht. na ja, nicht wirklich Hex ist bei mir ins Blut gegangen und die Bits habe ich sofort vor den Augen ohne nachzudenken. Bei den vielen Einsen und Nullen würde ich mich bloss verzählen:-) z.B finde ich: 0xAFFE viel besser zu lesen als: 0b1010111111111110
>
1 | > static void lcd_enable( void ) |
2 | > { |
3 | >
|
4 | > LCD_ADD_PORT |= (1<<LCD_EN) | (1<<LCD_RW) ; // Enable auf 1 setzen |
5 | > LCD_DDR = 0b00000000; |
6 | > while(LCD_PORT != 0b10000000); // Auf Busy flag Warten |
7 | > LCD_ADD_PORT &= ~(1<<LCD_EN); // Enable auf 0 setzen |
8 | >
|
9 | >} |
nochmal drüber nachdenken. Wie liest du denn vom LCD, wenn du gerade mitten drinn bist, den Enable Puls an das LCD zu geben, mit dem du eine Datenkommunikation auf den Weg bringst? Ausserdem steht dein Port immer noch auf Eingang, da wird dann das löschen des LCD_EN Flags nicht so toll kommen. Wenn du schon auf das Busy Bits warten willst, dann so: Abfrage ob das LCD Busy ist, BEVOR du eine neue Aktion am LCD machst (clear screen, zeichen ausgeben, etc...) nicht danach. Dein Programm macht ja in der Zwischenzeit weiter und kann dan andere Dinge tun, als auf das Busy Bit zu warten. Erst wenn du das nächste mal etwas vom LCD willst, muss das LCD mit seiner vorhergehenden Aktion fertig sein.
Davon abgesehen prüft LCD_PORT != 0b10000000 nicht, ob das Busy gesetzt ist, sondern ob (Busy gesetzt && alle anderen gleich Null sind). Wenn man nur das Busy testen will, müsste man etwa mit 0!=(LCD_PORT&0b10000000) prüfen, oder ((LCD_PORT&0b10000000)==0b10000000).
Hallo Patrick, ich kann zwar nur Assembler, aber was mir auffällt 1) Beim Lesen muss man nicht PORTx abfragen sondern PINx (eventuell ist das in C aber anders) 2) Das Lesen des Ports(PINx) muss in der Zeit zwischen Enable(High) und Enable(Low) erfolgen, d.h. die Enable-Umschaltung muss Teil deiner While-Schleife werden. In Assembler fügt man vorsichtshalber noch zwei Wartetakte ein (hängt vom Systemtakt ab) Etwa so... > DDRC auf Eingang > RW-Bit setzen > RS-Bit löschen (Schleifenbeginn) > Enable auf High schalten > nop > nop > PINC lesen (nur MSB interessiert) > Enable auf Low schalten > Wiederhole, bis MSB=0 (Schleifenende) (Jetzt kann DDRC wieder auf Ausgang gesetzt werden) Ich hoffe der programmiersprachenfreie Algorithmus ist verständlich :) Gruß Andreas
1 | busy: |
2 | in temp, pina |
3 | sbic pina, 7 |
4 | rjmp busy |
so sieht bei mir die Busy Schleife aus, da ich bei dem Programm nicht viel zu tun habe wird läufts ohne Interrupts. Muss man halt auf den Port und den entsprechenden Pin ändern
Hallo Patrick! Konntest Du dein Projekt erfolgreich abschließen oder bist Du noch in der Umsetzung? Es wäre schön hier noch einmal den erfolgreichen Lösungsansatz nachvollziehen zu können. Es wird sicher auch in Zukunft Ratsuchende geben, die dankbar sind, wenn sie beim Suchen eine funktionierende Problemlösung finden ;-) Gruß Andreas
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.