Forum: Compiler & IDEs Interruptproblem ISR(USART_RXC_vect)


von Daniel M. (Gast)


Lesenswert?

Habe folgendes Problem:
Ich möchte empfangene Zeichen wieder zurücksenden. Das ganze soll über
einen Interrupt - wenn Zeichen empfangen - erfolgen.

Sobald der µC ein Zeichen empfängt sendet er wahllos Zeichen in einer
Endlosschleife zurück.

Ich muss erwähnen, dass ich gerade von Assembler auf GCC umsteige.
Also kein GCC-Profi

#include <avr/io.h>
#include <avr/iom8515.h>
#include <avr/interrupt.h>

ISR(USART_RXC_vect)
{
  unsigned char Zeichen;
  Zeichen = UDR;
  while (!(UCSRA & (1<<UDRE)));     // warten bis Senden moeglich
  UDR = Zeichen;                          // sende Zeichen
}


int main(void)
{
  UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);    // UART TX,RX und INTRx
einschalten
  UBRRH  = 0;                                // Highbyte ist 0
  UBRRL  = 51;                              // Lowbyte ist 51 ( dezimal
)
  while (!(UCSRA & (1<<UDRE)));     // warten bis Senden moeglich
  UDR = '38';                          // sende Zeichen
  sei();
  while(1)
  {
      /*Endlosschleife*/
  }
}

von Marian (Gast)


Lesenswert?

Probiere es mal so:
int main(void)
{
  UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);    // UART TX,RX und INTRx
einschalten
  UBRRH  = 0;                                // Highbyte ist 0
  UBRRL  = 51;                              // Lowbyte ist 51 (
dezimal
  sei();
  while (!(UCSRA & (1<<UDRE)));     // warten bis Senden moeglich
      UDR = '38';                          // sende Zeichen
  while(1) /*Endlosschleife*/
  {
  }
}

So müsste er einmal am anfang die '38'schicken und dann immer das
zeichen schicken was er empfangen hat.

Das mit dem wahllos senden müsste man allerdings anders gestalten.

von Marian (Gast)


Lesenswert?

Achso was ich noch fragen wollte!

Hat denn dein Compiler nicht gemeckert ?

von Daniel M. (Gast)


Lesenswert?

Danke erstmal,

aber was soll daran besser sein, wenn ich vor Senden der '38' die
Globalen Interrupts zulasse?

Mit meinem Programm(s.o.) sendet er wahllos Zeichen sobald er etwas
empfängt. Zudem ist das erste Zeichen was er antwortet, nicht das
gleiche welcher er über RxD erhalten hat.

Mit deiner Änderung sendet er kein Zeichen zurück.

Zudem habe ich einen Kontrollport(PortB) aktiviert. Wenn er in
Interuptroutine springen soll schaltet er die LED um.
-> Macht er nicht, d.h er springt nicht in die Interruptroutine!

Aber warum?

Nochmal mein Programm:

#include <avr/io.h>
#include <avr/iom8515.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

ISR(USART_RXC_vect)
{
  PORTB=0xF0;
  register unsigned char akku;
  akku = UDR;
  while (!(UCSRA & (1<<UDRE)));     // warten bis Senden moeglich
  UDR = akku;                          // sende Zeichen
}


int main(void)
{
  UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);    // UART TX,RX und INTRx
einschalten
  UBRRH  = 0;                                // Highbyte ist 0
  UBRRL  = 51;                              // Lowbyte ist 51 ( dezimal
)
  DDRB=0xFF;
  PORTB=0x0F;
  while (!(UCSRA & (1<<UDRE)));     // warten bis Senden moeglich
  UDR = '38';                          // sende Zeichen
  sei();
  while(1)
  {
      /*Endlosschleife*/
  }
}

von Daniel M. (Gast)


Lesenswert?

"Build succeeded with 0 Warnings..."

Ich denke mal das ist in Ordnung.

Warum meinst du er solle meckern?

von inoffizieller WM-Rahul (Gast)


Lesenswert?

>UDR = '38';
Wie soll das gehen?

'' (Hochkommata) beschreiben einen Character (einzelnes Zeichen).
38 sind aber zwei Zeichen.

Wenn, dann müsste es
 UDR = "38";
heissen.

Das wird aber auch nicht funktionieren, da man immer nur ein Zeichen
(acht bit / ein Byte) zur Zeit ins UDR schreiben kann.
Vielleicht meinst du ja UDR = 38; Damit wird dann die Dezimalzahl 38
ins UDR geschrieben. Das dürfte laut ASCII ein "&" sein.

von Sven (Gast)


Lesenswert?

Habe Dein Programm mit einem Mega16 getestet und es funktioniert
einwandfrei.

Eine Warnung gibt der Compiler bei UDR = '38'; , da nur ein Zeichen
angegeben werden darf. Dafür müssen aber mit der Compileroption -Wall
alle Warnungen ausgegeben werden.
Besser UDR = 38; entspricht dem Zeichen '&'.

Stimmen denn die Baudraten überein?

Gruß Sven

von Sven (Gast)


Lesenswert?

Außerdem fügst Du die interrupt.h und signal.h ein, was auf eine ältere
Compilerversion schließen lässt.
Die Interruptfunktion implementierst Du aber mit ISR, was in der
aktuelle Compilerversion benutzt werden muss.

Die Implementierung der ISR muss natürlich der Version des
angewendetetn Compilers entsprechen.

von Daniel M. (Gast)


Lesenswert?

Ich kann 0x38 oder '38' schreiben und erhalte in meinem
Terminalprogramm das gleiche Ergebnis.
Steht das Terminal auf HEX-Anzeige erhalte ich jedesmal 38 und analog
erhalte ich bei ASCII-Anzeige die 8.

Aber das ist ja nicht mein Problem!!!
Mein Problem ist, er springt nicht in die Interruptroutine
ISR(USART_RXC_vect).

von Karl heinz B. (kbucheg)


Lesenswert?

Mal ne blöde Frage:
Welchen Compiler benutzt du und in welcher Form.

Das von dir gepostete geht definitiv nicht ohne
Warnings durch den Compiler.

(Ach ja: welche variablen in Register abgelegt werden sollen,
überlässt du besser dem Compiler. Streich am besten das
Schlüsselwort 'register' aus deinem C-Sprachschatz. Im besten
Fall ignoriert es der Compiler sowieso, im schlimmsten Fall
bewirkt es das Gegenteil von dem was du erreichen möchtest.)

von Daniel M. (Gast)


Lesenswert?

Ich benutze:
AVR Studio 4.12.490 SP3
GUI Version 4,12,0,490

Baudrate auf 9600-8-N-1 gestellt
Signal.h hatte ich nur implementiert, wegen test von SIGNAL(UART...).
Habe ich schon wieder entfernt.

>Die Implementierung der ISR muss natürlich der Version des
angewendetetn Compilers entsprechen.

Wie soll ich das verstehen. GCC ist Neuland für mich. Ich habe die
ganze Zeit in Assembler entwickelt. Als Info nutze ich das Tutorial
dieser Homepage.

von Karl heinz B. (kbucheg)


Lesenswert?

Noch was.
Für welchen µC soll das eigentlich sein?

von Peter (Gast)


Lesenswert?

UDR = '38'  // '38' sind zwei Zeichen, nämmlich '3' und '8'

#include <avr/iom8515.h>  // brauchts Du nicht zu includen.

Üblicherweise wird die CPU im makefile definiert, dann werden mit dem
<avr/io.h> automatisch die richtigen CPU-Definitionen reingehohlt!

Gruss von mir

von Daniel M. (Gast)


Lesenswert?

Ich habe mir den WinAVR-20060421 installiert.

Als µC nutze ich den ATMega16 mit einem 8MHz internen Takt

von Karl heinz B. (kbucheg)


Lesenswert?

Welche Version vom WinAvr hast du installiert?

von Karl heinz B. (kbucheg)


Lesenswert?

> ATMega16

Und warum includest du dann
#include <avr/iom8515.h>

Du hast keinen mega8515.

von Daniel M. (Gast)


Lesenswert?

Sorry ich meinte Atmega8515,

ich versuche gerade dass ganze auf einem Atmega16 zu testen, denn
vielleicht ist der 8515 defekt.


WinAVR-20060421 ist das nicht die aktuellste Version?

von Karl heinz B. (kbucheg)


Lesenswert?

> WinAVR-20060421 ist das nicht die aktuellste Version?
Doch ist sie.


Wenn ich allerdings bei mir mega8515 einstelle, dann
sagt mir der Compiler:

> ../UART.c:6: warning: `USART_RXC_vect' appears to be a misspelled
> signal handler

Liest du eigentlich die Warnungen vom Compiler?

von Karl heinz B. (kbucheg)


Lesenswert?

Und schmeiss den Include

#include <avr/iom8515.h>

raus. Der Prozessortyp wird im AVR-Studio unter
'Project' - 'Configuration Options' eingestellt.
Wenn du ihn nachträglich änderst auch den Punkt 'Debug' -
'Select Platform and Device' nicht vergessen.

Du inkludierst immer nur avr/io.h

von Daniel M. (Gast)


Lesenswert?

Ich sehe jetzt diese Meldung auch.

Das Fenster zeigt bei mir nur 5 Zeilen an und wenn die Meldung "Build
succeeded with 0 Warnings..." angezeigt wird, gehe ich davon aus, dass
keine Fehler vorhanden sind.
Seltsam ist nur, wenn ich es ein zweites mal kompiliere erscheint diese
Warnung nicht mehr.

Habe die Schreibweise IST(USART_RXD_VECT) in ...vect) und es
funktioniert.

Danke an Alle die mir geholfen haben

von Daniel M. (Gast)


Lesenswert?

Wenn ich aber interrupt.h entferne erhalte ich Fehler, wegen sei().

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Du sollst auch <avr/signal.h> entfernen, nicht <avr/interrupt.h>.

von Daniel M. (Gast)


Lesenswert?

Schon klar. Habe ich so auch gemacht.

Anderes Problem:
Kann ich in der Interruptroutine ein Funktion starten?
In der Zeit sollen auch keine anderen Interrupts aktiviert werden.

von Karl heinz B. (kbucheg)


Lesenswert?

Sicher kannst du.
Eine Interrupt Funktion ist auch nur eine Funktion
wie jede andere, nur dass sie halt 'von der Hardware
aufgerufen wird' und nicht von deinem Program selbst.

Ob du das machen sollst, ist eine andere Frage:
Alte Grundregel: Interrupt Funktionen sollten so schnell
wie möglich durchlaufen. D.h. wenn deine Funktion viel
Arbeit zu erledigne hat, dann ist es keine gute Idee sie
aufzurufen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Kommt hinzu, dass der Compiler dann die worst-case-Annahme macht
und alle Register, die von dieser Funktion laut ABI zerstört
werden könnten vorher retten muss.  Ausnahme: die Funktion ist
static deklariert und ist so kurz (oder "static inline"), dass
sie vom Compiler gleich inline erweitert wird.

von Marian (Gast)


Lesenswert?

@Daniel: Jo sorry, sehe jetzt auch das es keinen anderen Sinn macht was
ich schrieb. Ich hatte die eine Klammer falsch interpretiert und sie
eigentlich nur rausgenommen wobei die ja nur im Kommentar stand (*an
den kopf hau*)

Aber wieso sendet er bei dir verschiedene Zeichen? Du schreibst doch
dein empfangenes Zeichen in die Variable Zeichen und schreibst sie
danach wieder ins UDR. D.h. er sendet das was du ihm vorher schickst
oder nich?

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.