mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik UART probleme mit At90Can128


Autor: Tartaruga (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi
Ich würde gerne mit einem AT90Can128 der auf einem DVK09CAN1 ist eine 
Nachricht über die UART schicken leider funkt das nicht so einfach wie 
ich mir das gedacht habe. Das größte Problem ist das ich erstens nicht 
weiß welche UART ich programmierne soll (UART 1 oder UART0) weil ich nur 
eine RS 232 auf meinem Board habe und das andere Problem ist das er den 
angegeben wert nicht in das UDR0 Register speichert.
anbei mein Code

int uart_put_c(unsigned char c){

  while(UCSR0A !=(UCSR0A|0x20));
  UDR0 = c;
  return (0);

}//int uart_put_c


void uart_put_s(char *s){

  while(*s){
  
  uart_put_c(*s);
  s++;

  }//end while *s

}//end void uart_put_s



 int main(void){

/********UART Registersettings****************/

//UCSR1A = (UCSR1A|0x02); //00 00 00 00 
UCSR0B = (UCSR1B|0x08); //00 00 10 00 transmit bit is enable
UCSR0C = (UCSR1C|0x06); //00 00 00 11 ansyncrone 8 bit
UBRR0L  = 47;//Baud = 9600 

/******************ENDE***********************/


  char bufferUART[16];
  uint16_t test = 2343;
  
  Registersettings();

  while(1){
  
utoa(test, bufferUART, 10);
uart_put_s(bufferUART);

}//end while


return (0);
}//end main

Ich will nur eine Zahl schicken und hab mich da sehr streng an das 
Tutorial gehalten

Danke für eure Hilfe

lg
Tartaruga

Autor: Oops (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Abgesehen davon, das Du unbedingt (z.B. anhand des Schaltplans) 
herausfinden musst, welcher UART denn nun herausgeführt ist empfehle ich 
Dir http://www.mikrocontroller.net/articles/AVR-GCC-Tu... zu 
lesen

Gruss
Oops

Autor: Tartaruga (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
naja nach diesem Beitrag hab ich meine Schnittstelle programmiert nur 
leider funkt das trotztdem nicht
das umstellen ob UART0 oder UART1 sollte ja kein Problem darstellen nur 
ist es das leider nicht
also ich bekomm weder bei dem einem noch bei dem anderen was über die 
Leitung

Autor: Oops (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also gut. Du hast das Tutorial also gelesen.

Ändere erstmal
UCSR0B = (UCSR1B|0x08); //00 00 10 00 transmit bit is enable
UCSR0C = (UCSR1C|0x06); //00 00 00 11 ansyncrone 8 bit
in
UCSR0B = 0x08; //00 00 10 00 transmitter enable
UCSR0C = 0x06; //00 00 01 10 asynchron 8 bit
Das kompliziert die Sache nur.

Ausserdem poste mal die Initialisierung.

Welchen C-Compiler verwendest Du?

Gruss
Oops

Autor: Oops (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was mir noch gerade auffällt...
UBRR0L  = 47; //Baud = 9600
ist natürlich falsch, da Du
//UCSR1A = (UCSR1A|0x02); //00 00 00 00 
ja auskommentiert hast.
Es muss also
UBRR0L  = 23; //Baud = 9600
heissen.
Wenn es aber nur daran liegen sollte, dann müsstest Du die Leitung 
wenigstens zappen sehen.

Gruss
Oops

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>  while(UCSR0A !=(UCSR0A|0x20));

Das steht so bestimmt nicht im Tutorial und ist wohl die Wurzel des 
Übels ;-)

> UCSR0B = (UCSR1B|0x08); //00 00 10 00 transmit bit is enable
> UCSR0C = (UCSR1C|0x06); //00 00 00 11 ansyncrone 8 bit

Sowas auch nicht. Im Tutorial werden für die Bits aussagekräftige 
Makronamen benutzt. Der Kenner kann die auf den zweiten Blick auf 
Plausibilität prüfen, statt mühsam die Bitmaske aufzudröseln und mit dem 
Datenblatt zu vergleichen.

> UBRR0L  = 47;//Baud = 9600

Ohne Infos zur Taktrate des µC nicht nachprüfbar. Wie kommst du azf die 
47?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> UCSR0B = (UCSR1B|0x08); //00 00 10 00 transmit bit is enable
Wenn man sowas als
UCSR0B |= 0x08;
schreibt, dann passieren solche Fehler gar nicht. Gegen das "|" ist 
nichts einzuwenden, aber es ist ziemlich sinnfrei, UCSR0B mit dem Inhalt 
von UCSR1B zu beschreiben...

Autor: Oops (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sehe gerade noch was:
while(UCSR0A !=(UCSR0A|0x20));

Was soll das eigentlich machen?
Im Tutorial sehe eher sowas wie:
    while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich 

Das Problem mit Deinem Code ist folgendes:
1. Es wird wegen
...hile(USCR0A !...
 UCSR0A gelesen.
Nehmen wir an es sei Bit 0x20 gesetzt. Das Datenregister ist also leer 
und kann neue Daten aufnehmen. Wir lesen also 0x20
2. Es wird wegen
...(UCSR0A|...
 nochmal UCSR0A gelesen. Wir lesen wieder 0x20. Die Bedingung hat sich 
in der Zwischenzeit nicht geändert.
3. Wir testen auf Ungleichheit. 0x20 ist nicht ungleich 0x20 also 
bleiben wir in der Schleife.

Das funktioniert nicht!

Es muss eher:
while(!(UCSR0A & 0x20));
sein.

Gruss
Oops

Autor: Tartaruga (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Na das mit den | verknüpfung ist uns so auf der Uni erklärt worden weil 
wenn ich z.B:

>>UCSR0B = (UCSR0B|0x08); hinschreibe dann kann ich sichergehen das ich keine 
anderen Bit überschreibe.

Die Schleife while(UCSR0A !=(UCSR0A|0x20)); Funktioniert eigentlich also 
beim debuggen hab ich hier keine Problems das ich in der schleife bleibe 
hab es aber schon geändert.
Leider Funktioniert es noch immer nicht.

Weiß wer von euch warum ich beim debuggen nicht sehe das das 
DatenRegister UDR0 geladen wird?????
Der werd ist immer 0x00; auch nach der Zeile >> UDR0 = c;

Der µC wird von einem extern Oszillator getaktet. Auf dem steht drauf 
8.0000M S5 Darum habe ich angenommen das er 8 Mhz hat. Die 
Initialisierung steht eh in den Funktionen über der Main. #

Danke für eure zahlreichen antworten

lg
Markus

Autor: Tartaruga (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Compiler ist Winavr 1.4.6

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tartaruga wrote:
> Na das mit den | verknüpfung ist uns so auf der Uni erklärt worden weil
> wenn ich z.B:
>
>>>UCSR0B = (UCSR0B|0x08); hinschreibe dann kann ich sichergehen das ich keine
> anderen Bit überschreibe.
Ja, aber das führt bei Änderungen wie oben dann zu Fehlern! Die 
Kurzschreibweise mit "|=" macht exakt dasselbe, aber der Registername 
steht nur einmal da -> Tippfehlerwahrscheinlichkeit kleiner und Programm 
übersichtlicher...

Merke:
REGISTER |= WERT;
ist identisch mit
REGISTER = REGISTER | WERT;
Das gleiche gilt für die anderen Bit-Operatoren "&", "^" und "~".

Autor: Oops (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>>UCSR0B = (UCSR0B|0x08);
>hinschreibe dann kann ich sichergehen das ich keine anderen Bit überschreibe.

Das ist auch korrekt so. Du überschreibst dann keine Bits.
Das ist aber nur dann wichtig, wenn Du bestimmte Parameter der UART in 
dem Programm ändern musst. Wenn aber während der gesamten Laufzeit das 
Programmes die Parameter gleich bleiben, dann ist das nicht notwendig. 
In Deinem Fall hat die Verwendung von | dazu geführt, das Du bei der 
Änderung von UART1 auf UART0 den linken Teil zu ändern vergessen hast. 
Deswegen der Hinweis.

>Die Schleife while(UCSR0A !=(UCSR0A|0x20)); Funktioniert eigentlich also
>beim debuggen hab ich hier keine Problems das ich in der schleife bleibe
>hab es aber schon geändert.
>Leider Funktioniert es noch immer nicht.

Oops, da habe ich einen Denkfehler gemacht.
>3. Wir testen auf Ungleichheit. 0x20 ist nicht ungleich 0x20 also
>bleiben wir in der Schleife.
Wir bleiben dann nicht in der Schleife. Wir bleiben nur dann in der 
Schleife wenn die Bedingung Wahr ist.
Trotzdem ist das einfach schlechter Stil. Ist nur ne Behauptung von mir. 
Kann man drüber streiten.

>Weiß wer von euch warum ich beim debuggen nicht sehe das das
>DatenRegister UDR0 geladen wird?????
>Der werd ist immer 0x00; auch nach der Zeile >> UDR0 = c;

Datenblatt, Seite 195. Beim lesen liest Du das letzte empfangene Byte. 
Da Du nichts empfängst steht da Müll bzw. ein Wert der nach dem Reset 
dort gesetzt wird.

>Der µC wird von einem extern Oszillator getaktet. Auf dem steht drauf
>8.0000M S5 Darum habe ich angenommen das er 8 Mhz hat. Die
>Initialisierung steht eh in den Funktionen über der Main. #
Dann musst Du nochmal die Initialiszierung von UBRR überprüfen.
Datenblatt, Seite 202 enthält eine Tabelle für 8MHz. Es muss 52 sein.

Gruss
Oops

Autor: Tartaruga (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok supa werd das in zukunft beachten. Weißt vielleicht auch einen 
Lösungsansatz für meine anderen kleinen problemchen??? :-)

Autor: Oops (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch eine Bemerkung zu:
while(UCSR0A !=(UCSR0A|0x20));

Das ist einfach problematisch.
Allgemein vermeidet man es Variablen zweimal zu lesen, wenn einmal 
reicht. Das ist schneller. Ausserdem ist es nicht definiert ob ein 
Compiler die Variable bzw. in dem Fall ein Register tatsächlich zweimal 
liest oder nur einmal und den vorher gelesenen Wert wiederverwendet. Je 
nachdem kann dies bei zwischenzeitlichen Änderungen unterschiedliches 
(und ungewolltes) Verhalten bewirken.

Deswegen ist das schlechter Stil.

Gruss
Oops

Autor: Oops (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Weißt vielleicht auch einen Lösungsansatz für meine anderen kleinen 
problemchen??? :-)

Jetzt müsste man sich wirklich mal die Initialisierung anschauen.
Poste die mal.

Gruss
Oops

Autor: Tartaruga (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
na ich lese das UDR0 von dem I/O View stimmt das was dann im Datenblatt 
steht??? Ich hab mir gedacht das ich da sehe was das Register für einen 
Wert hat. kann es sein das der uC das "schon weggeschickt" hat obwohl 
ich durchsteppe???

Autor: Oops (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK. Du liest das im I/O View.


Wie Du siehst hat das I/O View keine Unterscheidung zwischen dem UDDR 
zum lesen des letzten geschrieben Bytes und zum lesen des letzten 
gelesenen Bytes. Woher soll es also wissen was Du sehen willst?

Gruss
Oops

Autor: Oops (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also, da fehlt noch die Schlussfolgerung.

>Woher soll es also wissen was Du sehen willst?

Es zeigt also den Inhalt an der beim Lesen des Registers gemäß der 
Spezifikation an.

Übrigens hat der UART eigene Schieberegister zum senden und Empfangen.

Gruss
Oops

Autor: Oops (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oops. Deutsch ist die Sprache.

Es muss heissen: Es zeigt also den Inhalt an der beim Lesen des 
Registers gemäß der Spezifikation dort zu lesen sein soll.

Gruss
Oops

Autor: Tartaruga (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
naja ich hab mir gedacht wenn ich mir den Taktschritt nach dem 
beschreiben des UDR0 steht dann genau dieser wert drinnen
Na ist egal es funktioniert jetz wenn auch nicht ganz einwandfrei
Ausgabe=
h4354435443544310`F5443544354435441"04354435443544354 
b$43544354435443%(`144354354435443544354b$35443544354435D"04354435 
4435440#k44354435443544!dl25443544354435"4`35443544354434(&5443544 
35443544%`4!544354435443543035443544354435$343544354435443$ 
au4435443544354$J$254435443544354h30035443544354435$"1043544354435443 
!45443544354435(03544354435443$`4354435443544`2%443544354435440 
435443544354435$41@H3544354435443$"044354435443544#540t443544354435 
4

4354 sollte geschickt werden aber warum hab ich noch störungen drinnen 
ist das normal oder .....

Autor: Oops (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>naja ich hab mir gedacht wenn ich mir den Taktschritt nach dem
>beschreiben des UDR0 steht dann genau dieser wert drinnen

Theoretisch könnte man das so in der Hardware implementieren. Ist aber 
einfach nicht so. Der entscheidende Satz ist: The USARTn Transmit Data 
Buffer Register and USARTn Receive Data Buffer Registers share
the same I/O address referred to as USARTn Data Register or UDRn. 
(Datasheet, Seite 195)

Also das es oft stimmt und dann einige Zeichen lang nicht ist ein 
starker Hinweis das einer der beiden Takte fast stimmt dann aber doch 
nicht so genau oder das einer der beiden Takte immer wieder schwankt.
Das der Abstand der Störungen regelmäßig ist (nach meinem visuellem 
Eindruck) deutet eher auf ersteres. Also eine geringe Abweichung der 
Takte die dann doch zu hoch ist.

In der Doku ist dazu auch was gesagt. Bis zu einem oder zwei Prozent 
sind glaube ich akzeptabel. Seite 192 sagt auch was zu dem akzeptablen 
Fehler.

Überprüfe mal sowhohl den absoluten Wert der Takte als auch kurzfristige 
Schwankungen. Ich nehme aber an das Deine Gegenstelle ein Terminal bzw. 
ein PC ist. Oder?

Gruss
Oops

Autor: Oops (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>naja ich hab mir gedacht wenn ich mir den Taktschritt nach dem
>beschreiben des UDR0 steht dann genau dieser wert drinnen

>Theoretisch könnte man das so in der Hardware implementieren.

Das gilt aber auch nur mit Einschränkungen. Was ist z.B. wenn gerade in 
dem Takt nach dem Schreiben, der Empfang eines Bytes abgeschlossen ist?

Gruss
Oops

Autor: Oops (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Also das es oft stimmt und dann einige Zeichen lang nicht ist ein
>starker Hinweis das einer der beiden Takte fast stimmt dann aber doch
>nicht so genau oder das einer der beiden Takte immer wieder schwankt.
>Das der Abstand der Störungen regelmäßig ist (nach meinem visuellem
>Eindruck) deutet eher auf ersteres. Also eine geringe Abweichung der
>Takte die dann doch zu hoch ist.

Also bei einigem Nachdenken möchte ich das doch ein wenig relativieren.
Der UART hat eine eigene Clock-Recovery. Wenn er überhaupt empfängt und 
dann manchmal nicht dann ist der Takt in der Zeit innnerhalb der 
Toleranz.

Ich würde doch eher auf Schwankungen eines der beiden (oder beider) 
Takte tippen.

Hast Du einen Zähler oder ein Oszi mit f-Messfunktion?

Gruss
Oops

Autor: Tartaruga (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein das habe ich mom nicht zur Verfügung. Aber das was ich bekomme 
reicht mir für meinen Zweck. Es ist nur fürs Debugging gedacht das ich 
die Messwerte in eine Datei stecken kann.

Ich Danke allen für eure Hilfe. Ich bin so froh dass es dieses Forum 
gibt ihr habt mir bei meiner Bachelorarbeit sehr weiter geholfen und ich 
fürchte ihr werdet es noch tun

also vielen vielen dank

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.