Forum: Mikrocontroller und Digitale Elektronik Frage zum UART (ISR Vector)


von Ein freundlicher türkischer Mitbürger (Gast)


Lesenswert?

Guten Abend zusammen.

Ich möchte mich mal kurz auf diesen Code Ausschnitt beziehen, den ich 
mal irgendwann irgendwo gefunden habe, um zu erfahren, ob ich das 
richtig verstanden habe.

Die Funktion (?) ISR(UART_RX_vect) wird jedesmal aufgerufen, wenn von 
dem computer zum (MAX232->) Atmega8 Daten fließen. In UDR sind 
warscheinlich die empfangenen Daten drin. Sind es eizelne 
Chars(=Zeichen) die gesendet werden ?

Diese einzelnen Chars werden in die Variable temp_str rein gepackt, 
welche maximal 10 Zeichen enthalten kann.
NextChar dient dann hier wie eine Art "laufvariable", welches die 
einzelnen Indizies für temp_str darstellt.

rx_flag ist dann sowas wie eine Status Variable, also wenn sie auf 1 
gesetzt wird, heißt es das alle Daten erfollgreich in temp_Str 
reingespeichert wurden. Was ich nicht so ganz verstehe ist die Bedingung 
==0x0D bzw. 13. d.h. das die If Bedingung abbricht wenn irgendein ein 
Element von temp_Str[] den Wert 13 erreicht. Steht die 13 in Relation 
mit der maximalen Anzahl der Zeichen die temp_Str aufnehmen kann oder 
ist das "zufall"?

Bedanke mich im Voraus !


char temp_str[10];
int NextChar;
int rx_flag;
1
ISR(UART_RX_vect) { 
2
3
 temp_str[NextChar] = UDR; 
4
 
5
 if (temp_str[NextChar] == 0x0D) 
6
 { 
7
   rx_flag=1; 
8
   NextChar=0; 
9
 } 
10
 else 
11
 { 
12
 NextChar++; 
13
 } 
14
}

von Ein freundlicher türkischer Mitbürger (Gast)


Lesenswert?

Aha.. die Hexdezimal stehen für die ASCII Zeichen.. mein gott... 
manchmal sieht man den Wald voller Bäume nicht.

von Falk B. (falk)


Lesenswert?

@ Ein freundlicher türkischer Mitbürger (Gast)

>warscheinlich die empfangenen Daten drin. Sind es eizelne
>Chars(=Zeichen) die gesendet werden ?

Ja.

>Diese einzelnen Chars werden in die Variable temp_str rein gepackt,
>welche maximal 10 Zeichen enthalten kann.

Ja, aber . . .

>NextChar dient dann hier wie eine Art "laufvariable", welches die
>einzelnen Indizies für temp_str darstellt.

Ja, das ist der Index. Allerdings fehl ein Schutz gegen Überlauf. Wenn 
dauernd Zeichen ankommen und kein 0x0D dabei ist, wirst du dir ganz fix 
deinen Speicher überschrieben und der uC stürzt ab.

>rx_flag ist dann sowas wie eine Status Variable, also wenn sie auf 1
>gesetzt wird, heißt es das alle Daten erfollgreich in temp_Str
>reingespeichert wurden.

ja.

>mit der maximalen Anzahl der Zeichen die temp_Str aufnehmen kann oder
>ist das "zufall"?

nöö, das ist der ASCII-Code für RETURN bzw. Enter. Klassische 
Schnittstelle zum PC auf einfacher Terminalbasis.

Machs besser so.

1
char temp_str[10];
2
int NextChar;
3
int rx_flag;
4
5
ISR(UART_RX_vect) { 
6
7
 temp_str[NextChar] = UDR; 
8
 
9
 if (temp_str[NextChar] == 0x0D) 
10
 { 
11
   rx_flag=1; 
12
   NextChar=0; 
13
 } 
14
 else 
15
 { 
16
   if (NextChar < (size_of(temp_str)-1) ) NextChar++; 
17
 } 
18
}

MfG
Falk

von Ein freundlicher türkischer Mitbürger (Gast)


Lesenswert?

@ Falk Brunner.

Vielen Dank für die schnelle Antwort und für deinen Tipp.

Ist in deiner Version diese Zeile:

if (NextChar < (size_of(temp_str)-1) ) NextChar++;

für den Schutz vor einem Überlauf ?

von Falk B. (falk)


Lesenswert?

Ja.

von Ein freundlicher türkischer Mitbürger (Gast)


Lesenswert?

Ich bekomme jetzt folgende Fehlermeldungen:

main.c:54: warning: 'UART_RX_vect' appears to be a misspelled signal 
handler
main.c: In function 'UART_RX_vect':
main.c:64: warning: implicit declaration of function 'size_of'

interrupt.h Header habe ich includiert...

von Ein freundlicher türkischer Mitbürger (Gast)


Lesenswert?

aha.. es heißt sizeof nicht size_of...

von Falk B. (falk)


Lesenswert?

@ Ein freundlicher türkischer Mitbürger (Gast)

>main.c:54: warning: 'UART_RX_vect' appears to be a misspelled signal
>handler

Der heisst bei einigen AVRs USART_RX_vect

>main.c: In function 'UART_RX_vect':
>main.c:64: warning: implicit declaration of function 'size_of'

dafür braucht man stddef.h

MFG
Falk

von Ein freundlicher türkischer Mitbürger (Gast)


Lesenswert?

@Frank:

hab jetzt #include <stddef.h> und USART... versucht aber Warnung noch 
immer Vorhanden und Warnungen solltem an als Fehler wahrnehmen ;-)

von Ein freundlicher türkischer Mitbürger (Gast)


Lesenswert?

Eine andere Frage, welche mich interessieren würde ist, ob ich den RXCIE 
Bit setzen muss, wenn ich den ISR benutze ? Laut AVRGCC Tutorial, ja.
Ich wundere mich weil ich den initialisierungs Code des UARTS ohne die 
Bit Setzung von RXCIE im Netz gefunden hatte, wo aber auch ISR benutzt 
wurde.

So war es vorher:
1
void uart_init(void){ 
2
UBRRH = (unsigned char) (UBRR_BAUD>>8); 
3
    UBRRL = (unsigned char) (UBRR_BAUD & 0x0ff); 
4
    UCSRB = (1<<RXEN) | (1<<TXEN); 
5
    UCSRC = (1<<UCSZ1)|(1<<UCSZ0); 
6
}

So habe ich es geändert, indem ich (1<<RXCIE) hinzugefügt habe.

Ist das notwendig ??

void uart_init(void)
{
  UBRRH = (unsigned char) (UBRR_BAUD>>8);
  UBRRL = (unsigned char) (UBRR_BAUD & 0x0ff);
  UCSRB = (1<<RXEN) | (1<<TXEN) | (1<<RXCIE);
  UCSRC = (1<<UCSZ1) | (1<<UCSZ0);
}

von Falk B. (falk)


Lesenswert?

Ja.

Wegen des Namens der ISR kannst du im Datenblatt des Controllers 
nachschauen, die sind beim AVR GCC gleich dem Datenblatt.

MFG
Falk

von Ein freundlicher türkischer Mitbürger (Gast)


Lesenswert?

@Frank:

Fehler gefunden... ich habe ein leerzeichen zwischen ISR und der Klammer 
(USART_RXC_vect) vergessen.

Keine Warnungen/Keine Fehler.

Bedanke mich sehr für deine Unterstützung und wünsche dir noch einen 
schönen Sonntag !

von Ein freundlicher türkischer Mitbürger (Gast)


Lesenswert?

Entschuldigung, ich meinte es lag an dem C das hinter RX ran muss.

Für einen Atmega8 gilt daher: ISR (USART_RXC_vect)

von Uwe (Gast)


Lesenswert?

Hi!
Mal was zu:
>if (temp_str[NextChar] == 0x0D)
Wenn du auf die Entertaste haust senden die meisten Programme 0x0D 0x0A.
Das 0x0A würde den Puffer schon mit dem 1. Zeichen füllen, also wenns 
dumm kommt und der Puffer noch nicht verarbeitet ist, ist das 1. Zeichen 
futsch. Brauchen wirst du es vermutlich eh nicht. Am besten mit 
ausfiltern.
Eventuell solltest du überhaupt testen ob der Puffer schon verarbeitet 
ist.
So in der Art if rx_flag==1 dann Fehlermeldung(Flag).

Viel Erfolg, Uwe

von Ein freundlicher türkischer Mitbürger (Gast)


Lesenswert?

Hallo Uwe !

Ich habe anstelle von Entertaste(CR) Semikolon(0x3B) benutzt. Ich werde 
die Befehle sowieso per Programm senden, wahrsch. eine kleine C 
Konsolenanwendung.

Derzeit quäle ich mich noch mit dem Senden von Daten an den PC. Es kommt 
zwar etwas an, aber es gefällt mir noch nicht :-).

von Ein freundlicher türkischer Mitbürger (Gast)


Angehängte Dateien:

Lesenswert?

Ich bin es nochmal.... egal was ich sende es kommen immer "Rechteck" 
Zeichen bzw. als Hexdezimal 00 an.

Was mache ich da falsch ? Mein Code ist im Anhang mitdabei.

Danke.

von Ein freundlicher türkischer Mitbürger (Gast)


Lesenswert?

Ich weiß, dass ich beim Senden eines Zeichens (uart_IAmAlive(const char 
*s)) einen Parameter übergebe mit diesen jedoch nicht arbeite. Ich 
wollte nur schauen, ob das senden von dem Zeichen 'T' funktioniert.

von Falk B. (falk)


Lesenswert?

@ Ein freundlicher türkischer Mitbürger (Gast)

>Was mache ich da falsch ? Mein Code ist im Anhang mitdabei.

Eine globale Variable mit dem Namen i ist sehr gefährlich. Die gehört 
als static in die ISR, denn nur dort wird sie verwendet.

Wegen Problemen zum UART fragen Sie Ihren Arzt oder Apotheker.

http://www.mikrocontroller.net/articles/AVR_Checkliste#UART.2FUSART

von Ein freundlicher türkischer Mitbürger (Gast)


Lesenswert?

Da ich kein neuen Thread öffnen möchte, könnte ich kurz eine neben Frage 
hier stellen, wenn das in Ordnung sein sollte, ansonsten tut es mir leid 
:).

Wenn ich bei der Schrittmotorsteuerung RN STEP 297/298 Kombination die 
Referenzspannung ändern möchte um z.b. den maximalen Motorstrom 
festzulegen muss ich dann die Verbindung der Schrittmotorsteuerplatine 
zur AVR Platine trennen ? Ich frage, weil ich an den Spindeltrimmer (Zum 
eisntelen der Referenzspannung) gedreht habe wie bekloppt und sich 
dieser nicht geändert hat, erstnachdem ich die die Verbindung zwischen 
Steuerplatine und AVR getrennt habe.


Zu UART: Das Tutorial bezüglich UART habe ich mir bereits angeguckt, nur 
sehe ich da kein Unterschied... ich korrigiere es mal die gefährliche 
Variable i ;-).

Danke !

von Ein freundlicher türkischer Mitbürger (Gast)


Lesenswert?

Also ich habe jetzt folgenden Code gestestet:
1
#include <avr/io.h>
2
#include <stdlib.h>
3
#include <util/delay.h>
4
#include <avr/interrupt.h>
5
#include <stddef.h>
6
7
8
9
10
#define BAUD 9600UL
11
#define UBRR_BAUD ((F_CPU/(16UL*BAUD))-1)
12
13
14
15
16
int main(void)
17
{
18
19
// Uart initialisieren
20
21
  
22
  UCSRB |= (1<<TXEN);                            // UART TX einschalten
23
  UCSRC |= (1<<URSEL)|(1 << UCSZ1)|(1 << UCSZ0); // Asynchron 8N1 
24
  
25
  UBRRH = (unsigned char) (UBRR_BAUD>>8);
26
 UBRRL = (unsigned char) (UBRR_BAUD & 0x0ff);
27
  
28
// Fertig mit initialisieren
29
30
31
  // Lass uns mal was senden :)
32
  while(1)
33
  {
34
  while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich                   */
35
    {
36
    }
37
  UDR = 'x';    
38
  }
39
  
40
return 0;
41
}

Und habe dieses Phänomen festgestellt:

Erst treffen nur '/////////////////////... zeichen an.. wenn ich die 
Verbindung neuaufbaue kommen diese Zeichen @ßßßßßßßßßßßß.. und beim 
dritten mal erst die gewünschten xxxxxx.  Was ist da faul ? Icb bin 
jetzt genau nachdem Tutorial gegangen.

Danke :)

von Falk B. (falk)


Lesenswert?

@  Ein freundlicher türkischer Mitbürger (Gast)

>Erst treffen nur '/////////////////////... zeichen an.. wenn ich die
>Verbindung neuaufbaue kommen diese Zeichen @ßßßßßßßßßßßß.. und beim
>dritten mal erst die gewünschten xxxxxx.

>  Was ist da faul ? Icb bin jetzt genau nachdem Tutorial gegangen.

Hast du auch das gelesen?

http://www.mikrocontroller.net/articles/AVR-Tutorial:_UART#Senden_von_Zeichen

"Hinweis

Wenn man das nachfolgende Programm laufen lässt und Hyperterminal 
startet, scheint es problemlos zu funktionieren. Wenn man aber das RS232 
Kabel zwischenzeitlich abzieht und wieder ansteckt wird es oft 
passieren, dass nur noch wirre Zeichen auf dem PC erscheinen. Das liegt 
daran, dass der PC aus einem ununterbrochen Zeichenstrom nicht den 
Anfang eines Zeichens erkennen kann. Darum muss in solchen Fällen 
periodisch eine kleine Pause von der Länge mindestens eines Zeichens 
eingelegt werden, damit der PC sich wieder synchronisieren kann."

MfG
Falk

von Ein freundlicher türkischer Mitbürger (Gast)


Lesenswert?

Oh tut mir leid.. hab den Link total übersehen... nach ein paar Stunden 
vor dem Rechner kann das schonmal passieren. Werde mir genau durchlesen 
und mich ggf. melden :).

Danke !

von Ein freundlicher türkischer Mitbürger (Gast)


Lesenswert?

Ich krieg das nicht hin. Ich kann zwar senden und empfanen. Ich habe 
zwischen dem senden ein _delay_ms(10) rein gekloppt und das scheint gut 
zu funktionieren. Aber mit dem ISR das klappt bei mir nicht.

von Ein freundlicher türkischer Mitbürger (Gast)


Lesenswert?

ich habe im ISR Code Block gleich, bevor eine If Abfrage kommt oder ä., 
den Befehl reingeschrieben den Motor einfach mal drehen zu lassen, um zu 
sehen ob sich überhaupt was im ISR tut und das scheint nicht so der fall 
zu sein....

von Ein freundlicher türkischer Mitbürger (Gast)


Lesenswert?

Ha ! Endlich geschaft !!! ;)

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.