hi, ich habe mein ATmega8 mit einem MAX232 CPE verbunden um mir eine Schnittstelle zum PC zu bauen. Was allerdings komisch ist, dass sobald ich den PC mit dem Board verbinde mein ATmega8 Timer stehnbleibt und solange nicht weitermacht bis ich die verbindung wieder trenne. Ich denke dass die die leitungen richtig angeschlossen habe da ich zwischen GND - Pin2 -8.5V, GND - Pin3 0.0V haben und die Voltzahl sich verändert wenn der Timer jede ~6sec ein zeichen sendet. jemand eine erklärung dafür? mfg blan
update jo das kabel hat nicht so recht getan. habs nun direkt an PC angeschlossen und der timer läuft ganz normal bloß kommen keine daten an. weder übers Windows Terminal, mein kleines C-Programm noch "cat /dev/ttyS0". woran könnte das liegen? stimmt denn mein ATmega8 UART Code den ich oben gepostet habe? hab noch mein C-Programm angehängt. mfg blan
update also scheint so alsob ich was gesendet bekomm, jedenfalls hat man nur was im hex-view gesehn und das war ne ganze menge "00", also mehr als 12 oder so. wie kommen die zusammen bei nur einem 'c' das gesendet wird? mfg blan
Also mich wundert das dein MCU-Programm überhaupt läuft weil in main eine Endlosschleife fehlt. So weit ich weiss ohne solche Schleife wird das Programm dauern beendet und neu durchlaufen. Die funktionen uart_init und uart_putc scheinen in Ordnung zu sein(für atmega8). Ich habe sie mit Funktionen verglichen die ich benutze.
hrm bis jetzt hab ich alle programme so gemacht unds hat immer funktioniert, naja werds mal reinmachen. beim kompilieren bekomm ich diesen fehler: main.c: In function `uart_init': main.c:28: warning: integer overflow in expression kanns vll daran irgendwie liegen. die "00" kommen mir irgendwie komisch vor :( mfg blan
>>>das war ne ganze menge "00", also mehr als 12 oder so. wie kommen die zusammen bei nur einem 'c' das gesendet wird? riecht nach nicht passender Baudrate, weil interner Takt statt Quarz aktiv... probier mal 600 Baud im Terminal aus, dann müsste es klappen wenn der AVR noch auf 1MHz läuft.
>>main.c:28: warning: integer overflow in expression
Ja stimmt das habe ich übersehen. das muss beim compilieren berechnet
werden weil es nich ich 16bit passt. Also mach das lieber so:
ubrr-Variable komplett weg, also das verschwindet:
uint16_t ubrr = (uint16_t) ((uint32_t) F_CPU/(16*BAUD_RATE) - 1);
Makro definieren:
#define UART_BAUD_CALC(UART_BAUD,F_OSC) ((F_CPU)/((UART_BAUD)*16L)-1)
Und dann anstatt:
UBRRH = (uint8_t) (ubrr>>8);
UBRRL = (uint8_t) (ubrr);
Das rein machen:
UBRRH=(unsigned char)(UART_BAUD_CALC(UART_BAUD,F_CPU)>>8);
UBRRL=(unsigned char)UART_BAUD_CALC(UART_BAUD,F_CPU);
@Martin: Alle mir bekannten Compiler fügen am Ende von main automatisch eine (leere) Endlosschleife ein.
sehr geil danke, es funktioniert fast perfekt. ich bekomm immer so wies sein sollte 'c' gesendet. jedoch manchmal aufeinmal 20 'c' aufeinmal. wie ist das mit 1mhz gemeint, der ATmega8 hat doch 16Mhz so wie ichs oben definiert habe? und ich hab jetzt im programm BAUD = 9600 und im terminal = 600, da kann dann ja auch net alles passen? mfg blan
was du im programm für eine taktfrequenz definierst, interessiert den controller herzlich wenig. der richtet sich nach seinem internen takt oder ggf. nach dem von einem quarz oder von sonsteiner taktquelle. einzustellen über die fusebits -> datenblatt. gruß
>>jedoch manchmal aufeinmal 20 'c' Also höstwahrscheinlich liegt das an dem PC-Programm mit dem du es empfengst. Ich habe hier dein Progamm in ein Atmega8 einprogrammiert und es scheint alles in ordnung zu sein. Diode Blinkt und synchron dazu wird ein c gesendet. >>16Mhz Ich benutze hier etwas andren uart-gerechten Quarz 14.7456MHz Schau im Datenblatt nach wie gut sich 16MHz und 9600Baud vertragen.
>> was du im programm für eine taktfrequenz definierst, interessiert
den
controller herzlich wenig.
der richtet sich nach seinem internen takt oder ggf. nach dem von
einem
quarz oder von sonsteiner taktquelle.
einzustellen über die fusebits -> datenblatt.
gruß
natürlich, is mir klar aber der ATmega8 hat doch ne taktfrequenz von
16Mhz, so stands jedenfalls mal auf nem Datenblatt. die frage ist halt
nur was ich machen kann ohne mir ein externen quarz zu holen und ein
sauberes signal bekomme?
mfg blan
nur weil im datenblatt steht, dass der controller bis 16mhz laufen KANN, heisst das nicht, dass er es im auslieferungszustand auch tut. falls du an den fuses bis jetzt nichts verstellt und keine externe taktqualle dranhast läuft das teil mit internen 1mhz. gruß
okay, da das teil dann wohl mit 1mhz läuft hab ich mein F_CPU angepasst und im datenblatt geschaut was ich so bei 1mhz benutzten kann, jedoch kommen zwischendurch (mal mehr mal weniger oft) mehrere 'a' an und manchmal sogar ein 'c' was überhaupt net gesendet wurde o.O muss man sowas akzeptieren oder habt ihr solche probleme nicht? mfg blan
Nuja, so ein Controller macht sowieso, was er will. Da kanns dann schonmal passieren, dass der UART ausser Kontrolle gerät und wild herumsendet. Quatsch mit Soße ;) Natürlich ist das nicht normal. Du hast mit Sicherheit einen Bug in Deinem Programm. Ich habe nur kurz drübergeschaut, was hast Du an Deinem ext. Int angeschlossen? Einen Taster? Dann suche mal im Forum nach "Taster entprellen).
Der interne RC-Oszillator ist für UART-Übertragung zu ungenau. Du solltest einen Baudratenquarz verwenden, z.B. 3,6864MHz oder ein ganzzahliges Vielfaches davon. Der Mega8 wird mit aktiviertem internen Oszillator ausgeliefert, der auf 1MHz eingestellt ist. Will man eine andere Taktquelle und/oder eine andere Taktfrequenz, dann muss man das dem Mega8 auch über die Fusebits mitteilen. Das sollte man aber erst tun, wenn man sich sachkundig gemacht hat (Datenblatt, diverse Threads hier im Forum), denn wenn man ohne exaktes Wissen drauflos probiert, dann hat man sich schnell ausgesperrt. Übrigens hat das mir vorliegende Datenblatt zum Mega8 303 Seiten. Da steht alles Wichtige drin. Es genügt aber nicht, nur die erste Seite mit der Feature-Auflistung zu lesen. ...
hrm an dem ext. interrupt ist normal nichts dran, werd ihn aber trotzdem mal ausmachen. also kann ich daraus schließen dass ich ohne einen externen quarz bzw. mit meinen 1mhz nichts mit dem UART anfangen kann? mfg blan
> also kann ich daraus schließen dass ich ohne einen > externen quarz bzw. mit meinen 1mhz nichts mit dem > UART anfangen kann? Im Prinzip ja. Der interne RC-Oszillator hat je nach Einstellung Abweichungen im Prozent-Bereich. Dazu kommt noch eine starke Temperaturdrift (Im Datenblatt unter Electrical Characteristics sind irgendwo die Kennlinien). Da man für eine asynchrone serielle Übertragung einen ziemlich genauen Takt braucht (als Toleranz werden meist 2% angegeben, weniger ist aber sinnvoll), ist das mit dem internen RC-Oszillator eher Glückssache, wenn die Übertragung mal klappt... Und wenns im Sommer klappt, dann im Winter wahrscheinlich nicht
Man kann den internen Oszillator kalibrieren, d.h. in diesem Fall etwas verstimmen, um näher an die richtige Baudrate heranzukommen. Aber das ist nicht sehr temperaturstabil. Oder die Baudrate auf 2400 Baud runterschrauben, dann klappt es recht gut, auch wenn die Abweichungen recht groß sind. Wenn Du am externen Int nichts dran hast, dann fängt der Pin Störungen auf und löst den Interrupt aus. Mindestens den internen Pull-Up einschalten oder einen externen Pull-Up anschließen.
> Oder die Baudrate auf 2400 Baud runterschrauben
Auch bei niedrigeren Baudraten gelten die genannten (prozentualen!)
Toleranzen. Wenn es mit 9600 Baud nicht läuft, dann gehts mit 2400 auch
nicht besser! Es ist der selbe Oszillator, und wenn Du das
Oszillator-Signal runterdividierst wirds auch nicht genauer...
Es ist schon ein kleiner Unterschied, ob man durch Reduzieren der Baudrate (bei Benutzung eines Quarzes, der für UART nicht optimal ist) einen ganzzahligen Teiler erreicht (und damit die Abweichung minimiert), oder ob man damit versucht, die durch einem recht instabilen RC-Oszillator schlechte und unzuverlässige Übertragung zu verbessern. Im ersten Fall hat man schon eine Chance, im zweiten Fall nicht. Denn die prozentuale Abweichung bleibt bei jeder Baudrate erhalten. Wenn es aber zuverlässig sein soll, sollte man schon einen baudratentauglichen Quarz benutzen. ...
@Hannes: Stimmt natürlich. Ich war jetzt von der Voraussetzung ausgegangen, dass beide genannten Baudraten mit der gegebenen Taktfrequenz mit gleicher Genauigkeit einstellbar sind...
okay ist natürlich jetzt bischen schade das zu hören :( kann mir jemand sagen wo es die Quarze gibt. Hab bei reichelt geschaut aber weiss net ob ich jetzt ein "Quarz" oder ein "Quarzoszillator" brauch und wieviel Mhz optimal für sone schaltung sind (sollte ich dann gleich ambesten irgendwas mit 16,xxxx Mhz nehmen?) mfg blan
Ich habe mich mal bei CSD mit baudratentauglichen Quarzen eingedeckt. Da gibt es "die ganze Staffel" zu fairen Preisen. Es kann aber sein, dass man dort momentan etwas warten muss, denn da ist zur Zeit der Bär los weil sich die fairen Preise herumgesprochen haben. Ich persönlich bevorzuge beim AVR Quarze (also keine Quarzoszillatoren), denn der AVR hat den Oszillator bereits eingebaut. Du solltest bei der Gelegenheit auch an die 22pF-Kondensatoren für die Quarze denken, siehe auch Datenblatt Seite 25. Ein paar Kerkos 100nF (z.B. in SMD 0805) solltest du auch gleich mitbestellen, die werden nämlich vom Anfänger gern vergessen. Quarzoszillatoren (als komplettes Bauteil) haben einen höheren Stromverbrauch, erzeugen mehr Störungen und sind meist teurer. Mir fällt gerade kein Grund ein, sie für AVRs zu verwenden. > ambesten irgendwas mit 16,xxxx Mhz nehmen? Gibt es einen Grund, ständig am Limit (oder dahinter) zu arbeiten? Man muss doch den Controller nicht immer mit maximaler Taktrate fahren. Meist reicht 3,6864MHz oder 7,3728MHz völlig aus. Beachte, dass höhere Taktfrequenzen auch höhere Ansprüche an das Platinendesign stellen. Eine Liste einiger baudratentauglicher Frequenzen findest du hier: http://www.hanneslux.de/avr/tipps/baudratenquarz.html oder im Datenblatt des Mega8 Seite 156 bis 159. ...
ok danke. ne muss net sein dass man immer am limit arbeitet aber habs grad so mit meim cpu im pc verglichen da kauf ich mir meist auf net des langsamste :D achso: seitdem ich den interrupt, der (was ich garnet wusste) ein 'c' sendet wenn er aktiviert wird, auskommentiert habe funktioniert der UART soweit ich des seh perfekt. im datenblatt steht auch dass er bei 2400 BAUD nur 0,2% fehler hat (bei 1.000000mhz) also aufjedenfall nochmals vielen dank, bei ner neuen schlatung werd ich dann quarze verwenden. darf ich bei dem quarz auch 100nF kerkos verwenden (hab grad soviele da ^^) mfg blan
> darf ich bei dem quarz auch 100nF kerkos > verwenden (hab grad soviele da ^^) Aber sicher darfst du das. Ist ja dann dein Quarz und dein MC. Aber schwingen wird der Quarz damit vermutlich nicht. Denn 100nF ist etwa das Fünftausendfache des empfohlenen Wertes. Das empfindet Quarz und Oszillator vermutlich als Kurzschluss. ...
kleine frage hab ich noch. momentan realisier ich die abfrage von dem UART mit einem Timer, was aber sicher nicht sehr elegant ist. bloß bleibt mein programm immer bei folgendem stehen: INTERRUPT(SIG_UART_RECV) { uint8t_t dummy = uart_getc_wait(); switch_port(0, 1); } wieso? mfg blan
Lass um *Gottes* Willen die Finger von INTERRUPT! Da ist SIGNAL ja noch besser! Allerdings sind beide veraltet! Bitte benutze ISR und dann den richtigen Vektornamen! Sorry für die vielen Ausrufezeichen, aber wenn ich so was sehe, dann....!!!!!
> uint8t_t dummy = uart_getc_wait();
des weiteren muss das hier keine ...wait() Funktion
sein (was auch immer die macht. Aber das ...wait() varanlasst
mich zur Vermutung, dass die auf irgendetwas warten wird).
Du bist im Interrupt. Du weist, dass ein Zeichen empfangen
wurde, sonst wärst du nicht im Interrupt.
Du kannst das Zeichen aus dem UDR Register holen, denn es steht
bereits vollständig drinnen.
Ich vermute mal, dass es genau diese wait-Funktion ist, die dafür sorgt, dass 'das Programm stehenbleibt' (worauf auch immer diese Funktion wartet...). Möglicherweise ein klassischer Stack Overflow... Vielleicht noch mal zur Erklärung: eine mit INTERRUPT eingeleitete ISR ist (im Unterschied zu SIGNAL und ISR) unterbrechbar. Je nachdem, was Du in der ISR machst, kann es passieren, dass sich die ISR selber unterbricht, wenn Interrupts schneller kommen, als sie bearbeitet werden. Und genau das führt zwangsläufig zu einem Stack Overflow und damit zum Systemabsturz. Verschachtelte Interrupts sollte man nur dann verwenden, wenn man sich ganz sicher ist, dass man weiß, was man tut!
Eine andere Möglichkeit wäre, dass diese ...wait() Funktion genau auf das Auftreten des Interrupt Flags wartet. Dieses ist aber bereits gelöscht worden, da ja die Interrupt Funktion aufgerufen wurde.
wo bekomm ich denn die vectornamen her, überall steht was anderes. im datenblatt steht nicht viel drin und hier steht alles aber funktionert wohl nicht (http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html#gae8ea90ab1d3064dfeb128c126d4709d) ISR(TIMER0_OVF_vect) { switch_port(0, 1); switch_port(1, 1); switch_port(2, 1); } muss doch funktionieren. mfg blan
Die Dinger heissen normalerweise gleich wie im Datenblatt von AVR, nur mit einem angehängten _vect TIMER0_OVF_vect ist daher richtig. Im Zweifelsfall kann man immer noch in das Prozessor- spezifische io.h schauen. Bei einem AMega16 heist diese Datei zb. iom16.h > muss doch funktionieren. Rein von dem was ich hier sehen kann: Klar, sollte tadellos funktionieren. Die ISR sollte aufgerufen werden. Falls Timer und Interrupts richtig initialisiert werden.
ja genau auf die idee bin ich auch gekommen nur steht dort folgendes: /* Interrupt vectors */ #define SIG_INTERRUPT0 _VECTOR(1) #define SIG_INTERRUPT1 _VECTOR(2) #define SIG_OUTPUT_COMPARE2 _VECTOR(3) #define SIG_OVERFLOW2 _VECTOR(4) #define SIG_INPUT_CAPTURE1 _VECTOR(5) #define SIG_OUTPUT_COMPARE1A _VECTOR(6) #define SIG_OUTPUT_COMPARE1B _VECTOR(7) #define SIG_OVERFLOW1 _VECTOR(8) #define SIG_OVERFLOW0 _VECTOR(9) #define SIG_SPI _VECTOR(10) #define SIG_UART_RECV _VECTOR(11) #define SIG_UART_DATA _VECTOR(12) #define SIG_UART_TRANS _VECTOR(13) #define SIG_ADC _VECTOR(14) #define SIG_EEPROM_READY _VECTOR(15) #define SIG_COMPARATOR _VECTOR(16) #define SIG_2WIRE_SERIAL _VECTOR(17) #define SIG_SPM_READY _VECTOR(18) was bischen komisch ist oder? timer sollte richtig initialisiert sein, mit INTERUPT() hats auch geklappt: int main(void) { TIMSK |= (1 << TOIE0); TCNT0 = 0x0; TCCR0 |= (1 << CS02); uart_init(); sei(); return 0; } mfg blan
> nur steht dort folgendes: Geh mal schnell zu http://winavr.sourceforge.net/ und hol dir eine neuere Version.
jo hab wohl echt ne veraltete version. nur gibts für meine distribution nur diese version. muss ich mal schaun wie ich das hinbekomme :( mfg blan
also ich hab mir jetzt die neuste version neu compiliert und tatsächlich - es funktioniert :D ich empfehl jemdem die neuste version ;) danke nochmals! mfg blan
@Karl Heinz: > ...genau auf das Auftreten des Interrupt Flags > wartet. Dieses ist aber bereits gelöscht worden, da > ja die Interrupt Funktion aufgerufen wurde. If memory serves: War da nicht was, dass das RXC-Flag, im Unterschied zu den meisten anderen Interrupt-Flags, erst dann gelöscht wird, wenn UDR gelesen wird, und nicht beim Einsprung in die ISR?
Ja da war was. Ich denke du hast recht. Aber ohne Kenntnis des Aufbaus der Funktion ist das alles sowieso stochern im Nebel :-)
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.