Forum: Mikrocontroller und Digitale Elektronik UART probleme mit At90Can128


von Tartaruga (Gast)


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
1
int uart_put_c(unsigned char c){
2
3
  while(UCSR0A !=(UCSR0A|0x20));
4
  UDR0 = c;
5
  return (0);
6
7
}//int uart_put_c
8
9
10
void uart_put_s(char *s){
11
12
  while(*s){
13
  
14
  uart_put_c(*s);
15
  s++;
16
17
  }//end while *s
18
19
}//end void uart_put_s
20
21
22
23
 int main(void){
24
25
/********UART Registersettings****************/
26
27
//UCSR1A = (UCSR1A|0x02); //00 00 00 00 
28
UCSR0B = (UCSR1B|0x08); //00 00 10 00 transmit bit is enable
29
UCSR0C = (UCSR1C|0x06); //00 00 00 11 ansyncrone 8 bit
30
UBRR0L  = 47;//Baud = 9600 
31
32
/******************ENDE***********************/
33
34
35
  char bufferUART[16];
36
  uint16_t test = 2343;
37
  
38
  Registersettings();
39
40
  while(1){
41
  
42
utoa(test, bufferUART, 10);
43
uart_put_s(bufferUART);
44
45
}//end while
46
47
48
return (0);
49
}//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

von Oops (Gast)


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-Tutorial#Der_UART zu 
lesen

Gruss
Oops

von Tartaruga (Gast)


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

von Oops (Gast)


Lesenswert?

Also gut. Du hast das Tutorial also gelesen.

Ändere erstmal
1
UCSR0B = (UCSR1B|0x08); //00 00 10 00 transmit bit is enable
2
UCSR0C = (UCSR1C|0x06); //00 00 00 11 ansyncrone 8 bit
in
1
UCSR0B = 0x08; //00 00 10 00 transmitter enable
2
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

von Oops (Gast)


Lesenswert?

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

Gruss
Oops

von Stefan B. (stefan) Benutzerseite


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?

von Johannes M. (johnny-m)


Lesenswert?

> UCSR0B = (UCSR1B|0x08); //00 00 10 00 transmit bit is enable
Wenn man sowas als
1
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...

von Oops (Gast)


Lesenswert?

Sehe gerade noch was:
1
while(UCSR0A !=(UCSR0A|0x20));

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

Das Problem mit Deinem Code ist folgendes:
1. Es wird wegen
1
...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
1
...(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:
1
while(!(UCSR0A & 0x20));
sein.

Gruss
Oops

von Tartaruga (Gast)


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

von Tartaruga (Gast)


Lesenswert?

Der Compiler ist Winavr 1.4.6

von Johannes M. (johnny-m)


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:
1
REGISTER |= WERT;
ist identisch mit
1
REGISTER = REGISTER | WERT;
Das gleiche gilt für die anderen Bit-Operatoren "&", "^" und "~".

von Oops (Gast)


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

von Tartaruga (Gast)


Lesenswert?

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

von Oops (Gast)


Lesenswert?

Noch eine Bemerkung zu:
1
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

von Oops (Gast)


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

von Tartaruga (Gast)


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???

von Oops (Gast)


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

von Oops (Gast)


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

von Oops (Gast)


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

von Tartaruga (Gast)


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 .....

von Oops (Gast)


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

von Oops (Gast)


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

von Oops (Gast)


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

von Tartaruga (Gast)


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

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
Noch kein Account? Hier anmelden.