UART Probleme mit AT90CAN128

Gast #587068
Lesenswert?

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
Gast #587206
Lesenswert?

"#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
Gast #587477
Lesenswert?

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
Gast #587551
Lesenswert?

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
Gast #587604
Lesenswert?

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.
Gast #587612
Lesenswert?

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
Gast #587615
Lesenswert?

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?
Gast #587624
Lesenswert?

- 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 ;) ))
Gast #587642
Lesenswert?

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!!!!!
Gast #587646
Lesenswert?

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.
Gast #587651
Lesenswert?

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?
Gast #587657
Lesenswert?

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
#587671
Lesenswert?

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.
Gast #587673
Lesenswert?

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 :-)
#587678
Lesenswert?

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!)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren