Hallo zusammen, ich hatte schon in http://www.mikrocontroller.net/forum/read-1-93736.html gepostet und bevor ich jetzt den ATMega8 auslöte, wollte ich Euch bitten mal über den Sourcecode zu schauen. Ist zwar nicht sehr schön, aber sollte doch eigentlich funktionieren, oder? Ich hab' es mit und ohne Interruptroutinen ausprobiert und es werden einfach keine Daten gesendet. Der Port ist ständig auf 5 Volt und nichts passiert. Vielen Dank für Eure Mühe. Gruß Markus P.S.: Der Schaltplan ist im anderen Posting, da es jetzt nur um das Programm geht, es ist auch nur eine einfache Grundschaltung. Es gibt zwar viele USART Fragen, aber ich habe noch keine C-Sourcen gefunden, wenn hier doch welche existieren, tut's mir für das überflüssige Posting leid.
UART-Beispiele sollte es schon geben... Guck'mer mal. Erste Frage: > // USART Test - ATMega8 @ 16 MHz Den RC-Oszillator hast Du auch abgeschaltet? > void flash_init(void); Kein glücklicher Namen übrigens -- `flash' wird bei Microcontrollern heutzutage gern mit flash-ROM in Verbindung gebracht. > SIGNAL(SIG_UART_RECV) { > cli(); ... > sei(); cli()/sei() sind unsinnig. Beim Eintritt in die Routine sind die Interrupts sowieso gesperrt, beim RETI werden sie automatisch freigegeben. > PORTD ^= _BV(PC2); PC2 paßt nicht zu PORTD. Dann nimm gleich eine 2 (statt PC2), sonst ist das eher verwirrend. > // Bei leerem Sendepuffer LED wechsel > SIGNAL(SIG_UART_TRANS) { Ich weiß, daß Du das nur für 'ne LED machst, trotzdem der Hinweis: SIG_UART_TRANS ist selten sinnvoll, SIG_UART_DATA ist sinnvoller. Das kommt nämlich wirklich, wenn der Sende*puffer* leer ist, nicht erst, wenn das Zeichen rausgeschoben worden ist. Damit kannst Du rechtzeitig das nächste Zeichen bereitstellen und diese ,,Rücken an Rücken'' senden. > // Port D, Pin 6 auf Eingang schalten > DDRD |= _BV(PD6); Der Kommentar beschreibt genau das Gegenteil von dem, was gemacht wird. Wenn ich mir angucke, wie oft Du auf irgendwelchen Bits von Port D eine LED an- oder ausschalten willst, denke ich, daß Du das auch im Kopf verdreht hast... Die LEDs an Port D2 und D3 sind jedenfalls nicht als Ausgang geschaltet. Damit wirst Du deren Blinkern schlecht sehen können, zusammen mit einer schrägen Datenrate (bspw. durch völlig falschen Prozessortakt, s. o.) siehst Du auch nichts beim Empfänger, das könnte Dich vermuten lassen, daß gar nichts geht. Hast Du denn mal einen Oszi an die TxD-Leitung gehalten? > // Auf Frame Error prüfen > if (UCSRA & _BV(FE) ) { Das kann man vielleicht wirklich besser in der Interruptroutine gleich machen. > PORTC &= ~_BV(PC1); // LED an > waste = UDR; // UDR leeren Das ist unsinnig (sollte aber auch nicht schaden): die Rx-Interruptroutine hat das Zeichen ja schon gelesen, egal ob's ein framing error war oder nicht. > UBRRH = 0x00; Mußt Du nicht setzen, 0 ist Voreinstellung. > // Double Transmission Speed einschalten > UCSRA |= _BV(U2X); ? > // 8N1 Modus > UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); Auch das ist voreingestellt. Ansonsten sollte das aber schon gehen, ja.
Danke für die Hinweise. Es ist mein erster Atmel und manche Dinge waren mir nicht klar (sei, cli). Die LEDs nehme ich zum "debuggen", weil ich kein Oszilloskop habe. Für 5 Projekte im Jahr lohnt es sich nicht. Die 16MHz liegen an, denke ich. Darauf habe ich die delay_ms Routine kalibriert. Zugegebenermaßen hatte ich natürlich anfangs die entsprechenden Fuses nicht gesetzt. Nun sieht's so aus: Fuse Low Byte = 0xff Fuse High Byte = 0xd9 Fuse Extended Byte = 0xff Calibration Byte = 0xa7 -- Read Only Lock Bits = 0xff BLB12 -> 1 BLB11 -> 1 BLB02 -> 1 BLB01 -> 1 LB2 -> 1 LB1 -> 1 Sollte ok sein. Gruß Markus
> ... weil ich kein Oszilloskop habe. Für 5 Projekte im Jahr lohnt es > sich nicht. Ach, ein Oszi lohnt immer. Für bissel RS232-Analyse genügt ja das billigste NF-Teil. Gerade alte DDR-Oszilloskope bekommst Du gut hinterhergeworfen (und wenn Du einen EO174 nimmst, den kannst Du sogar mit 12 V und damit netzgetrennt betreiben). Die Baudrate mag ich jetzt nicht nachrechnen, kannst Du selbst tun (oder die Rechnung dem C-Präprozessor überlassen). Bleibt immer noch, daß Du die DDRx-Register falsch herum gesetzt hast. Deine Hardware habe ich mir nicht angeguckt, aber an die RS232-Inverter (die Pegelwandler sind invertierend) hast Du gedacht, ja?
Jup, daran habe ich gedacht und das ist auch das Problem. Ich hatte den Kondensator an V+ vom MAX232 überbrückt, der ist dadurch ziemlich heiß geworden - klar - und nun ist mein Problem, das ich nicht weiß, ob der USART Block vom Atmel auch hin ist. Ich habe testeshalber die Ports TxD, RxD als normale I/O Ports umprogrammiert und sie dann getestet, das funktionierte auch. Den Quellcode habe ich korrigiert. Die Baudrate ist aus dem Atmel Datasheet. Daher auch der USART-Quellcode, nur das ich ihn ein wenig abgewandelt habe und zur Sicherheit auch Default Werte nochmal in die Register geschrieben habe, nachdem ich gesehen habe, was der AVR-GCC aus der delay_ms Routine ohne den NOP Befehl alles weg optimiert hat. Nun, da es mein erster Atmel ist und meine erste SMD Lötung und dann auch nichts auf Anhieb klappt, wird man verzweifelt und macht jeden unsinnigen Mist in der Hoffnung, dass es die Lösung ist.
Wie auch immer, hab' gerade festgestellt, dass wenn ich die Pins TxD und RxD mit dem Finger berühre, der µC sich aufhängt. Das Teil ist wohl im Eimer. Werd' wohl alles neu machen :-( Gruß Markus
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.