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:
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
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
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 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?
- 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 nichtAVR 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 ;) ))
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
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
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!)