Hallo Zuammen, ich hab mal versuch das ASM Beispiel aus dem Tutorial zum ansteuern eines HD44780 in C zu portieren. Leider war dieses Vorhaben nich von Erfolg gekrönt. Anstat dem erwarteten Hallo auf dem Display sehe ich nur einen blinkenden Cursor. Vielleicht könnt Ihr euch ja mal den Code anschauen und mir sagen wo der Fehler ist. Danke schon mal im Vorraus, der Jochen #include <avr/io.h> #define PORT PORTC #define DDR DDRC #define PIN PINC #define E_PIN 5 #define RS_PIN 4 #define BYTE char void delay50us(void) { asm(" ldi r16, 0x42 \n" "1: \n" " dec r16 \n" " brne 1b \n" ::); } void delay5ms(void) { asm(" ldi r16, 0x21 \n" "1: \n" " ldi r17, 0xC9 \n" "2: \n" " dec r17 \n" " brne 2b \n" " dec r16 \n" " brne 1b \n" ::); } void lcd_enable(void) { outp(0x00, PORT); // all low outp(0xff, DDR); sbi(PORT, E_PIN); asm("nop\n\tnop\n\tnop"::); cbi(PORT, E_PIN); } void send_command(BYTE data) { outp(0x00, PORT); // all low outp(0xff, DDR); BYTE high_nibble, low_nibble; outp(0xf0, DDR); outp(0x1f, PORT); //High und Lownibble ermitteln high_nibble = data>>4; low_nibble = data; //unnötige daten auf null setzten high_nibble = 0x0f; low_nibble = 0x0f; //High Nibble ausgeben outp(high_nibble, PORT); lcd_enable(); //Low Nibble ausgeben outp(low_nibble, PORT); lcd_enable(); } void lcd_init(void) { outp(0x00, PORT); // all low outp(0xff, DDR); // 50 x 5 ms warten int i; for(i=0; i<50; i++) delay5ms(); //Drei mal 0x03 zum initialisieren schicken outp(0x03, PORT); for(i=0; i<3; i++) { lcd_enable(); delay5ms(); } //4-BIT Modus setzen outp(0x02, PORT); lcd_enable(); delay5ms(); send_command(0x28); send_command(0x0c); send_command(0x04); } void lcd_clear(void) { send_command(0x01); delay5ms(); } void send_data(BYTE data) { outp(0x00, PORT); // all low outp(0xff, DDR); BYTE high_nibble, low_nibble; outp(0xf0, DDR); outp(0x1f, PORT); //High und Lownibble ermitteln high_nibble = data>>4; low_nibble = data; //unnötige daten auf null setzten high_nibble = 0x0f; low_nibble = 0x0f; //RS-Bit setzten high_nibble |= 1<<RS_PIN; low_nibble |= 1<<RS_PIN; //High Nibble ausgeben outp(high_nibble, PORT); lcd_enable(); //Low Nibble ausgeben outp(low_nibble, PORT); lcd_enable(); } int main(void) { lcd_init(); lcd_clear(); send_data("H"); send_data("a"); send_data("l"); send_data("l"); send_data("o"); return 0; }
Danke, für den Link. Ich kenn die Seite. Das Problem ist aber das dort die R/W Leitung benutzt wird die ich bei mir auf GND gelegt habe. Deshalb wollte ich eben die ASM Routine von hier in C umschreiben. Vielleicht hat ja noch jemand ein Tipp was das Problem sein könnte. Ein Fehler den ich schon gefunden hab ist der folgende: //unnötige daten auf null setzten high_nibble = 0x0f; low_nibble = 0x0f; muss natürlich so aussehen: //unnötige daten auf null setzten high_nibble &= 0x0f; low_nibble &= 0x0f; Hat sonst noch jemand Fehleer entdeckt? Der Jochen
Auf der letzten Seite in der "Codesammlung" ist noch ein Codebeispiel... wirst du wahrscheinlich aber auch schon kenne. Ich bin auch noch auf der Suche nach einem gutem Beispiel oder Tutorial für LCD mit C und nicht Assembler in C.
Ich hab schon einige Beispiele gefunden, aber immer mit der R/W Leitung. Deshalb wollte ich ja auch den ASM-Code von dem Tutorial hier 1:1 in C umsetzen. Ist mir aber im Moment noch nicht gelungen. Der Jochen
Die ganzen codes aus der sammlung kenne ich - jeden einzelnen link hier angeklickt - Meistens in Assembler und eins war in C++... könntes du vielleicht mal deine links posten, die du für LCD steuerung gut findest?
Ich denke, das ist so der Standart Link: http://www.mysunrise.ch/users/pfleury/avr-software.html#libs Hier ist halt das Problem das er die R/W Leitung verwendet um das BussyFlag zu lesen. Ich hab das bei mir halt auf GND, darum müsste ich die ganzen Abfragen nach dem BussyFlag in delays umwandel. Mir wäre es auch ganz lieb wenn ich meinen eigenen Code zum laufen bekommen würde, dann weis ich nämlich das ich verstanden habe was ich da so mache. Kann mir vielleicht einer Sagen wofür folgeder Code in der ASM Variante der LCD ansteuerung ist? ldi temp1, LOW(RAMEND) ; LOW-Byte der obersten RAM-Adresse out SPL, temp1 ldi temp1, HIGH(RAMEND) ; HIGH-Byte der obersten RAM-Adresse out SPH, temp1 Danke, der Jochen
> Danke, für den Link. Ich kenn die Seite. Das Problem ist aber das > dort die R/W Leitung benutzt wird die ich bei mir auf GND gelegt > habe. Typischer Fall von »selbst schuld«. Sowas macht man nicht, zumindest nicht ohne Not. (»Not« wäre es, wenn Du in einer Massenfertigung durch die eingesparte Leitung den nächstkleineren Controller nehmen kannst, oder wenn Du aus irgendwelchen Gründen gezwungen bist, ein Display zu nehmen, das R/W nicht herausführt.) Wenn Du das busy-Flag nämlich nicht mehr lesen kannst, mußt Du oftmals ein Vielfaches dessen an Wartezeit einplanen, was tatsächlich notwendig wäre, um auf der sicheren Seite zu liegen. Damit ist eigentlich auch schon beschrieben, wie man ein HD44780 Display ansteuert, wenn man R/W nicht zur Verfügung hat: jeder Test des busy-Flags muß durch die im Datenblatt vorgeschriebenen Verzögerungen ersetzt werden. > Kann mir vielleicht einer Sagen wofür folgeder Code in der ASM > Variante der LCD ansteuerung ist? > ldi temp1, LOW(RAMEND) ; LOW-Byte der obersten RAM-Adresse > out SPL, temp1 > ldi temp1, HIGH(RAMEND) ; HIGH-Byte der obersten RAM-Adresse > out SPH, temp1 Nun, ist das wirklich so schwer zu raten? Hast Du denn überhaupt eine Vorstellung von der Wirkungsweise des Controllers? Damit wird der Stackpointer auf das obere RAM-Ende initialisiert. Irgendwer hier hat Dir auch schon mal beschrieben, daß Dein Controller gar nicht wirklich ein SPH-Register hat, da er nur 256 Byte RAM besitzt, damit kannst Du diesen Teil klemmen. Außerdem ist das Ganze natürlich nur einmal pro Applikation nötig. Wenn Du die Applikation im Ganzen in C schreibst, erledigt das das C-Laufzeitsystem für Dich, Du mußt Dich da nicht mehr drum kümmern, egal ob Du dann die LCD-Bibliothek in Assemblercode einbinden willst oder nicht. Allerdings beschleicht mich das Gefühl, daß Du Dich erstmal mit den Grundlagen der Controller vertraut machen solltest, um diese von Grund auf zu verstehen. LCD und UART sind da leider schon so komplex, daß sie keinen guten Einstieg bieten. Fang mal wirklich mit dem einfachsten an, das typische ,,Hello world!'' Programm der Microcontroller ist wirklich nur die blinkende Leuchtdiode (oder die auf- und abschwellende mit einem PWM, wie im demo.c der avr-libc). Wenn Du bei diesem verstanden hast, wie's geht, einschließlich des Timings (Deine LED also wirklich im von Dir gewünschten Takt blinkt, und zwar durch Berechnung der Zeiten, nicht etwa durch trial&error Verzögerungsschleifen, bei denen Du die Schleifenzähler empirisch ermittelst), dann kannst Du weiter machen. Als nächsten Schritt würde ich sehen, daß man sich einen simplen RS232-Treiber an die UART-Pins anschließt (MAX232 oder Äquivalent), auf dem PC ein einfaches Terminalprogramm, und ein paar Zeichen ausgibt. Wenn das funktioniert, hast Du zumindest mal eine simple Debug-Möglichkeit. Erst dann würde ich mich dran machen, eine LCD anzuschließen. Den ADC kannst Du ggf. ja schon zuvor mal ausprobieren, die Ausgaben können ja auch anfangs über die UART gehen. Beispielcode findest Du im Netz ausreichend, aber wenn Du ihn nicht verstehen kannst, nützt Dir das alles überhaupt nichts.
Ich muss Dir insoweit REcht geben das ich die Funktionen des atmega8 nicht alle im Detail kenne. Allerdings ist es auchnicht so das ich keinen Plan von uC im allegmeinen habe. Nun muß ich noch etwas zu den "Lernmethoden" sagen. Mag sein das es für Dich der richtige Weg ist alles von Grund auf zu machen und dabei zu lernen. Ich habe für mich jedoch die Erfahrung gemacht das ich Sachen besser begreife wenn ich etwas hab das funktioniert und dan step by step mir anschaue wie es geht. Ich denke gnaz einfach jeder hat seinen eigen Lernstiel. Nun noch etwas zu dem Display: Ich hab mittlerweile die R/S-Leitung angeschlossen und alles tut einwandfrei. Auch hab ich es zuvor geschaft durch ersetzen der BusyFlag Abfrage durch Delays das Display zum laufen zu bekommen. Das ich moch viel lernen muss das weis ich auch selber. Aber auf einem langen Weg zum behersche des ARs ist es auch immer wieder schön mal ein Erfolgserlebnis zu haben. BTW: Bei meinem letzten Problem mit dem UART hat mir Dein Tipp ja auch weiter geholfen und ich konnte das Problem lösen. So, einen schönen Abend noch und Danke, der Jochen P.S. PWM muss ich mir allerding auch noch ansehen.
> Aber auf einem langen Weg zum behersche des ARs ist es auch immer > wieder schön mal ein Erfolgserlebnis zu haben. Ja, daher ja mein Vorschlag, das schrittweise anzugehen. Aber klar, wenn Du für Dich andere Schritte bevorzugt, nur zu! Hat ja offenbar nun auch funktioniert. > PWM muss ich mir allerding auch noch ansehen. Nun, siehe demo.c, ist bei avr-libc dabei und wird auch von WinAVR mit installiert. Die Doku enthält einiges an Kommentaren dazu. Die Idee dafür ist übrigens nicht von mir sondern von Rich Neswold. Er hatte vor Jahren mal eine separate Doku und ein Einsteigerdokument für AVR-GCC & Co. geschrieben und dort die Idee dieses Demo-Projektes drin gehabt, war aber selbst nicht zur Realisierung gekommen.
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.