Hallo zusammen, ich habe ein STK501 mit einem AT90Can128 Controller. Zur inbetriebnahme meines UARTS Habe ich mal das Tutorial genutzt, möchte beim drücken einer Taste auf dem Board das Zeichen x an mein Terminalprogramm des PC`s senden. Habe einen 4 MHz Quarz und auch die Fuse Bits dementsprechend eingestellt. Lieder bekomme ich beim drücken der Taste immer nur Müll am Terminalprogramm raus, wie bsp. zwei Zeilen voller yyyyyyy Woran kann das noch liegen?? Mache schon den ganzen Tag daran rum und bekomme es einfach nicht zum rennen... Bin verzweifelt.... Hier ist der Code: #include <stdint.h> #include <avr/io.h> #define F_CPU 3686400 /* Quarz mit 3.6864 Mhz */ int main (void) { //Port A und B initialisieren um Taster und LED`s zu steuern. DDRB= 0xff; //Ganzen Port B als Ausgang setzten DDRA= 0x00; //Ganzen Port A als Eingang setzten PORTA= 0xff; //Pull ab Widerstände für gesamten Port A aktiv //USART Contollregister initialisieren siehe S.197 Datenblatt /* USART-Init 19200 Baud bei 4MHz für AT90CAN128 */ UBRR1H = 0; // Highbyte ist 0 UBRR1L = 12; // Lowbyte ist 12 ( dezimal ) ergibt 19,2k bei 4Mhz Clocktakt UCSR1B |= ( 1 << TXEN1 ); // UART TX einschalten (Sendebereit machen) UCSR1C |= ( 0 << UMSEL1 )|(0<<UPM1)|(0<<USBS1)|( 3<<UCSZ1 ); // Asynchron modus Character Size 8-bit,2 Stopbit, kein Parity while (1) { if (!(PINA & (1<<PA0)) ) //Wenn PIN 0 von Port A 0 ist dann.... { // setzte Pin4 an Port B (LED) PORTB |= (1<<PB4); while (!(UCSR1A & (1<<UDRE1))) /* warten bis Senden moeglich solange UDRE1 flag 0 ist */ { asm volatile ("nop"); } UDR1 = 'x'; /* schreibt das Zeichen x auf die Schnittstelle */ } else { PORTB &= ~(1<<PB4); } } } Kann mir da irgendwer helfen? Wäre wirklich froh darüber. Viel kann es nicht sein, da wenn ich die Taste drücke empfange ich ja was, leider aber nur scheiss.... Vielen Dank schon mal
"#define F_CPU 3686400 " -- das stimmt zwar nicht, aber wenn du das korrigierst, kannst du es auch benutzen (s.u.) die Schleifen, in denen du auf ein bestimmtes Bit wartest, kannst du leer lassen:
1 | while( !(UCSR1A & (1<<UDRE1))) |
2 | ;
|
3 | #ifndef F_CPU
|
4 | # define F_CPU 4000000UL //korrekten Wert eintragen!
|
5 | #endif
|
6 | #define BAUD((rate)) (F_CPU/(16*rate) -1)
|
7 | UBRR1H = BAUD(19200)>>8; |
8 | UBRR1L = BAUD(19200); |
9 | // ... (0<<x) hat keine Auswirkungen
|
10 | // 3<<UCSZ1 ist definitiv falsch,
|
11 | // UCSR1C |= ( 3<<UCSZ0 ); // 'korrigiert'
|
12 | UCSR1C |= ((1<<UCSZ1)|(1<<UCSZ0)); // korrekt und besser lesbar ;) |
Für '8N1' brauchst du eigentlich nichts extra einzustellen, das sind die Defaults nach dem Reset ("Initial Value" im Datenblatt) hth. Jörg
Hallo Jörg, vielen dank für deine Antwort! Leider haben die Änderungen auch nicht den gewünschten Erfolg gebracht, ich habe immer noch komische Zeichen im Terminalprgram! Mir ist auch nicht ganz klar, warum ich die Baudrate über deine Rechnung angeben soll und nicht einfach über UBRR1 = 12; Das müsste doch normal bei 4Mhz 19200 Baud ergeben!?!? Wo könnte der Fehler jetzt noch liegen? Das ist echt zum verzweifeln, kann doch so schwer nicht sein! Danke Gruß Simon
hast Du ggf noch den 1:8 Clock-Teiler gesetzt? Der ist von Hause aus immer aktiv.
Mhh gute Frage, jedenfalls habe ich Ihn nicht bewust ausgeschaltet. Wie schalte ich den Timer aus? Ist das ein Register? Oder Muss man das im M-File machen? Gruß Simon
... ich klicke einfach das Häkchen raus ... Umpf. Ist ein Fuse-Bit!
Hallo, >hast Du ggf noch den 1:8 Clock-Teiler gesetzt? Der ist von Hause aus >immer aktiv in diese "Falle" bin ich auch schon mal getappt. Warum hat der eigentlich den 1:8 standardmäßig aktiviert - macht ja nicht wirklich Sinn, oder? Gruß, Christian
Ist der Teiler aktiviert wenn das Häkchen gesetzt ist oder wenn es gelöscht ist?? Ist immer so en Scheiss mit den Null aktiven Fuses...???
Funktioniert trotzdem nicht, so ein Scheiss!! Ich hätte nicht gedacht das es so ein Problem ist ein Zeichen auf eiem UART auszugeben :-(
der Controller läuft aber schon mit externem Quarz und nicht mir dem standardmäßigem RC-Oszillator oder? (Fuses!)
Ist es auch nicht. Vielleicht suchst Du das Problem an der falschen Stelle ggf ein daueraktiver Watchdog (fuse gesetzt) ohne WD-Routine ein defekter XX232, oder die Cmos version mit Elkos statt keramischen Kondensatoren, oder ein nicht Cmos-XX232 mit Cmos-Beschaltung ... hast Du z.B. mal die echte Frequenz an deinem CAN128 gemessen? Du kannst dazu den Takt an einen Port (PD7??) weiterleiten.
Ja hab ich gemacht, hat genau 3,7 Mhz, das passt alles... Ist ein externer 4Mhz Quarz. Was mich auch wundert ist das nach dem beschreiben des UCSR1C |= (( 1<<UCSZ11 )|(1<<UCSZ10)); Registers werden auch die UBRR1H flags 9 und 10 beschrieben?!?! Ich setzte sie einfach in der nächsten Zeile mit UBRR1H = 0; wieder zurück, sonst passt ja meine Datenrate mit 19.2k bei 4 MHz nicht, dazu muss ich ja nur UBRR1L mit 12 beschreiben siehe: UBRR1L = 12; Irgendwas stimmt mit dem Takt nicht oder mein Code hat einen morts Bug.. Please help me! Danke
nein es ist PC7 << Ist immer so en Scheiss mit den Null aktiven Fuses...??? >> Dieses Statement macht mich mistrauisch. Woher weisst Du, dass Du überhaupt die Richtige Einstellung für die Clock hast?
3,7 Mhz? Was genau soll da noch aus der seriellen Schnittstelle rauskommen?
- Warum ich die Rechnung in den Code schreibe? -- Warum soll ich denn den Registerwert ausrechen, wenn der Compiler das doch selber kann (das muss der nicht AVR ausrechnen) - Die CKDIV8 -Fuse ist von Haus ausprogrammiert, damit der µC bei jeder erlaubten KOmbination aus Spannung und Takt losläuft, sonst könnte man den evtl. nicht ISP-Programmieren - Bist du sicher, dass der AVR mit 4Mhz läuft? (Woher kommen die: STK-500, Quarz, internerRC-Oszillator...) - Benutzt du die richtige Serielle schnittstelle? hth. Jörg kannst du mal das aktulle Programm posten ? (möglichst in [c ] [/c ]-Tags(ohne Leerzeichen ;) ))
>3,7 MHz... das passt alles... Ist ein externer 4Mhz Quarz.
widerspricht sich meiner Meinung nach, lässt aber auf 3.6864 Mhz Quaz
schließen...
Hallo nochmal, ja wie gesagt ich verwende ein STK501 Board. Auf dem STK 500 also dem unteren Teil ist ein 4Mhz Quarz gesteckt. Wenn ich am Pin 7 messe, messe ich 3,7 Mhz. Externen Clock habe ich über die Fuses auf Ext. Cristal Osc. 3-8 Mhz Startuptime 65ms gestellt, den Teilerfaktor austeschaltet. Der aktuelle Code sieht so aus: #include <stdint.h> #include <avr/io.h> #ifndef F_CPU #define F_CPU 4000000UL /* Quarz mit 3.6864 Mhz */ #endif int main (void) { //Port A und B initialisieren um Taster und LED`s zu steuern. DDRB= 0xff; //Ganzen Port B als Ausgang setzten DDRA= 0x00; //Ganzen Port A als Eingang setzten PORTA= 0xff; //Pull ab Widerstände für gesamten Port A aktiv //USART Contollregister initialisieren siehe S.197 Datenblatt /* USART-Init 19200 Baud bei 4MHz für AT90CAN128 */ UBRR1L = 12; // Lowbyte ist 12 ( dezimal ) ergibt 19,2k bei 4Mhz Clocktakt UCSR1B |= (1 << TXEN1); // UART TX einschalten (Sendebereit machen) UCSR1C |= (( 1<<UCSZ11 )|(1<<UCSZ10)); // Asynchron modus Character Size 8-bit,1 Stopbit, kein Parity UBRR1H = 0; //UBRR1H auf 0 zurücksetzten while (1) { if (!(PINA & (1<<PA0)) ) //Wenn PIN 0 von Port A 0 ist dann.... { PORTB |= (1<<PB4); // setzte Pin4 an Port B (LED) while (!(UCSR1A & (1<<UDRE1))); /* warten bis Senden moeglich UDR1 = 'x'; } else { PORTB &= ~(1<<PB4); } } } Liegts am Code, am Quarz, an den Fuses?!?! Danke für eure Hilfe!!!!!
3,7MHz -- Ist der Takt vom stk-500, jaa auch dem must du wohl sagen, dass du einen Quarz benutzen willst, und NEIN 3,7 Mhz sind nicht ok, wenn man 4 haben will ;) . Die Sache mit den UBRRnH Bits steht unter "Known Issues" (dt. bekannte Fehler) in der Doku des SIMULATORs! (AVR-Studio-help), hat also keine Auswirkungen auf den AVR. In der AVR-Studio Software heißt Haken: Programmierte (aktive) Fuse, igorier einfach mal, ob das jetzt 0 oder 1 heißt.
Also was stimmt jetzt?? Soll ich #define F_CPU 4000000UL schreiben oder #define F_CPU 3700000UL Wie soll ich dem dem sagen das ich einen 4 Mhz Quarz gesteckt habe??Zumindest steht das auf dem Quarzgehäuse. Das Problem liegt sicher an dem Takt, ich denke der Code wäre sonst ok oder?
Jipiiiiiii!!!!!! Es geht fast, ich hab jetzt das UBRR1L mit 11 beschrieben und jetzt kommt mein Zeichen an!!!!! Leider aber bestimmt 80 mal wenn ich die Taste drücke. Wie bekomme ich das jetzt hin, das es nur einmal ankommt??? Hey voll cool, vielen Dank für euer aller Hilfe, echt Top, ihr habt mir einen riesen Gefallen getan. Bin gerade an meiner Diplomarbeit und dreh noch durch mit dem UART... Vielleicht gibts jetzt noch nen Trick das ich nur ein Zeichen bekomme!! Vielen Dank Gruß Simon
Crystal Oscillator ist nicht gleich Crystal! Außerdem musst Du afaik einen Jumper umstecken, um einen Quarz im STK500 nutzen zu können.
Simon wrote: > Vielleicht gibts jetzt noch nen Trick das ich nur ein Zeichen bekomme!! > Vielen Dank Der Trick heißt "eindeutige Tasterzustandsauswertung" bzw. "Tastenentprellung". Da gibts hier tausende Threads zu (gib mal "Entprellung" in die Suche ein).
such nach "enprellung", in der Codesammlung und in den AVR-tutorials bei dem #define F_CPU gehört DIE Frequenz hin, mit der der AVR tatsächlich läuft, natürlich ;) hth. Jörg
>Vielleicht gibts jetzt noch nen Trick das ich nur ein Zeichen bekomme!!
den Taster kürzer drücken
Tip Top, werd mal schauen ob ich das mit der entprellten Taste hinbekomme. Man kann sich kaum vorstellen das die kleinen Taster so prellen können :-)
Das hat in Deinem Fall primär gar nichts mit dem Prellen zu tun, sondern mit Deiner Abfrage. Du fragst nur ab, ob die Taste gedrückt ist. Und wenn das der Fall ist, dann wird gesendet, bis die Taste wieder losgelassen wurde. Und selbst bei einem "schnellen" Drücken ist der Kontakt mindestens einige zig ms geschlossen. Das reicht auf jeden Fall für mehrere Zeichen aus. Deshalb auch der Hinweis auf "eindeutige Tasterzustandsauswertung". Und dazu genügt es i.d.R. schon, bei der Abfrage des Tasterzustandes den jeweils aktuellen Zustand zu speichern und beim nächsten mal die Aktion nur dann durchzuführen, wenn der Taster gedrückt ist, aber im vorherigen Zyklus nicht gedrückt war (also beim letzten Mal 1 und jetzt 0). Alle anderen Zustände werden ignoriert.
Hey Jonny Stimmt, da hast Du auch wieder recht. Mal sehen ob eine solche Abfrage hin bekommen, hab eben auch noch nicht wirklich viel µC programmiert. Falls Du eine solche Abfrage gerade aus dem Ärmel schütteln kannst, kannst Du sie gerne posten :-)
Hab doch schon alles beschrieben. Du musst nur jedes Mal, wenn Du den Taster abfragst, den Zustand des Tasters speichern (also ne 1 für "nicht gedrückt" und ne 0 für "gedrückt"). Und senden tust Du nur dann, wenn der gespeicherte alte Zustand (von der jeweils vorhergehenden Abfrage) 1 und der aktuelle 0 ist. Das geht z.B. mit einer UND-Verknüpfung des alten Zustandes mit dem invertierten neuen Zustand (1 & !0 == 1, alle anderen Kombinationen ergeben 0). Für das Speichern und Vergleichen brauchste halt eine Variable. Der Rest ist basic (damit meine ich NICHT die Programmiersprache!)
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.