Forum: Mikrocontroller und Digitale Elektronik Atmega2560 USART Interrupt


von simon (Gast)


Lesenswert?

Hallo an alle,

Irgendwie verzweifel ich grad. Ich versuche für meinen ATMega2560 mit 
dem Entwicklungboard Arduino MEGAAdk mein USART1 mit einem Receive 
Interrupt zu konfigurieren.

Analog beim ATmega 8 klappt es...

Wäre schön, wenn ihr mir helfen könnten.

Hier mein Code:
1
#include "usart.h"
2
3
4
//The setup function is called once at startup of the sketch
5
void setup()
6
{
7
  USART_init_();
8
//  SetINT_init();
9
//  sei();
10
11
}
12
13
// The loop function is called in an endless loop
14
void loop()
15
{
16
17
}
18
19
ISR(USART1_RX_vect)          // USART1_RX_vect ?? funzt noch nicht!!!
20
{
21
22
  Sende_Char('n');
23
24
}
----------------------------------------------------------------

meine usart.c:
1
#include <stdint.h>
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <stdlib.h>
5
#include <stdio.h>
6
7
/*Die UART-Schnittstellen werden Initialisiert
8
 * */
9
void USART_init_(void) {
10
  UCSR1B = (1 << RXEN1) | (1 << TXEN1) | (1 << RXCIE1) | (1 << TXCIE1); //Enable Receiver and Transmitter 1, RX Complete Interrupt Enable 1,  TX Complete Interrupt Enable 1
11
  UCSR2B = (1 << RXEN2) | (1 << TXEN2) | (1 << RXCIE2) | (1 << TXCIE2); //Enable Receiver and Transmitter 2, RX Complete Interrupt Enable 2,  TX Complete Interrupt Enable 2
12
  UCSR3B = (1 << RXEN3) | (1 << TXEN3) | (1 << RXCIE3) | (1 << TXCIE3); //Enable Receiver and Transmitter 3, RX Complete Interrupt Enable 3,  TX Complete Interrupt Enable 3
13
14
  UCSR1C = (1 << UCSZ11) | (1 << UCSZ10);                         //8 Databits
15
  UCSR2C = (1 << UCSZ21) | (1 << UCSZ20);                         //8 Databits
16
  UCSR3C = (1 << UCSZ31) | (1 << UCSZ30);                         //8 Databits
17
18
  UBRR1 = 25;                   //Einstellen der Baudrate 38400
19
  UBRR2 = 25;                   //Einstellen der Baudrate 38400
20
  UBRR3 = 25;                   //Einstellen der Baudrate 38400
21
22
}
23
24
/*Set Interrupts (global)
25
 * */
26
void SetINT_init(void) {
27
  sei();
28
}
29
30
/*Funktion zum �bertragen eines chars
31
 * */
32
void Sende_Char(char c) {
33
  /*Wert:   xxxx xxxx
34
   *Maske:  0001 0000  &
35
   *      ---------
36
   *Ergebnis:  000x 0000
37
   *Ergebnis:  !(true oder false)
38
   * */
39
  while (!(UCSR1A & (1 << UDRE1)))
40
    ;  //Warten bis USART zum schreiben bereit ist
41
  UDR1 = c;            
42
}
43
44
/*Funktion zum Empfangen eines chars
45
 * */
46
uint8_t Lese_Zeichen() {
47
  uint8_t z;
48
  if (UCSR1A & (1 << RXC1))  //Pr�fe, ob Datenbyte empfangen wurde
49
    z = UDR1;
50
  else
51
    z = 0xFF;// Der Wert 0xFF spielt bei Strings keine Bedeutung deshalb kann er als Leerzeichen interpretiert werden
52
  return z;
53
}
54
55
/*Funktion zur �bergabe der Zeichenkette
56
 *die �bertragen werden soll
57
 */
58
void Sende_String(char *s) {
59
  while (*s)            //bis string ausgelesen gelesen
60
  {
61
    Sende_Char(*s);        //Funktionsaufruf
62
    s++;            //speicherstelle erh�hen
63
  }
64
  s = 0;              //Speicherstelle zur�cksetzen
65
}



BITTE UM HILFE!!!

von Karl H. (kbuchegg)


Lesenswert?

simon schrieb:


> Irgendwie verzweifel ich grad. Ich versuche für meinen ATMega2560 mit
> dem Entwicklungboard Arduino MEGAAdk mein USART1 mit einem Receive
> Interrupt zu konfigurieren.

Hast du es denn ohne Interrupt schon mal probiert.
Und da am besten mal einfach nur Senden lassen, damit du am PC siehst ob 
und wenn ja was am PC ankommt (sprich ob die ganze Taktung inkl Baudrate 
stimmt)

> Analog beim ATmega 8 klappt es...

Gewöhn dich an die Vorstellung, dass man Code nicht einfach von einem µC 
auf einen anderen übernehmen kann. Man kann die Grundidee und Codeteile 
übernehmen, aber dann behandelt man den Code so, wie wenn man ihn neu 
schreiben müsste. D.h. ALLES wird mit dem Datenblatt kontrolliert.
Insofern ist es irrelevant, ob das mit dem Mega8 funktioniert hat oder 
nicht. Das ist ein neues Programm und das soll auf einem 2560 laufen. 
Und nur das zählt.


> void setup()
> {
>   USART_init_();
> //  SetINT_init();
> //  sei();
>
> }

OHne freigegbenen Interrupts wirds aber nichts mit dem Receive Interrupt

> void USART_init_(void) {
>   UCSR1B = (1 << RXEN1) | (1 << TXEN1) | (1 << RXCIE1) | (1 << TXCIE1);
> //Enable Receiver and Transmitter 1, RX Complete Interrupt Enable 1,  TX
> Complete Interrupt Enable 1
>   UCSR2B = (1 << RXEN2) | (1 << TXEN2) | (1 << RXCIE2) | (1 << TXCIE2);
> //Enable Receiver and Transmitter 2, RX Complete Interrupt Enable 2,  TX
> Complete Interrupt Enable 2
>   UCSR3B = (1 << RXEN3) | (1 << TXEN3) | (1 << RXCIE3) | (1 << TXCIE3);
> //Enable Receiver and Transmitter 3, RX Complete Interrupt Enable 3,  TX
> Complete Interrupt Enable 3

Es ist keine so gute Idee, alle Interrupts auf Verdacht freizugeben. Vor 
allen Dingen dann nicht, wenn man keine ISR dazu hat. Denn wenn der 
Interrupt auftritt, und es keine ISR dafür gibt, dann wird das mit einem 
Prozessor-Reset quittiert. Insofern hast du zwar den Transmit Complete 
Interrupt freigegeben, aber keine ISR dafür. Ergo ....

von simon (Gast)


Lesenswert?

Hallo Karl Heinz Buchegger,

Vielen Dank für deine Antwort.

Das Senden vom Mikrocontroller aus funktioniert einwandfrei. ich habe 
dazu einfach in die loop() die Funktion Sende_Char('h'); geschrieben.



Meine Korrekturen:
1
void USART_init_(void) {
2
  UCSR1B = (1 << RXEN1) | (1 << TXEN1) | (1 << RXCIE1); // | (1 << TXCIE1); //Enable Receiver and Transmitter 1, RX Complete Interrupt Enable 1,  TX Complete Interrupt Enable 1
3
  UCSR1C = (1 << UCSZ11) | (1 << UCSZ10) | (1<<UMSEL10);          //8 Databits, Synchron
4
  UBRR1 = 25;                   //Einstellen der Baudrate 38400
5
  
6
}

und
1
ISR(USART_RX_vect)          // USART1_RX_vect ?? funzt noch nicht!!!
2
{
3
4
  Sende_Char('n');
5
6
}
7
ISR(USART_UDRE_vect)          // USART1_RX_vect ?? funzt noch nicht!!!
8
{
9
10
  Sende_Char('m');
11
12
}

leider funktioniert es immer noch nicht.

Hast du noch weitere Tipps?

von Karl H. (kbuchegg)


Lesenswert?

Die ISR kann nicht
1
ISR(USART_RX_vect)

USART_RX_vect heissen!
Du hast mehere UARTS und jede hat ihren eigenen Interrupt Vektor. Die 
Erwartung ist also, dass die Nummer der UART für die diese ISR zuständig 
ist, sich im Namen der ISR niederschlägt.

Du hast ja hier
1
   UCSR1B = (1 << RXEN1) | (1 << TXEN1) | (1 << RXCIE1);
auch überall die '1' für die UART mit der Nummer 1 drinnen.


Hast du keine Compiler Warnung bekommen?

von simon (Gast)


Lesenswert?

Nein, habe ich nicht, da es USART0 glaube ich nicht gibt da ist USART. 
das habe ich behoben, dennoch keine Änderung...  :(

Ich bin dir schon jetzt sehr dankbar für deine Hilfe.

... :-(

von Karl H. (kbuchegg)


Lesenswert?

simon schrieb:

> das habe ich behoben, dennoch keine Änderung...  :(

Was hast du behoben?

Hast du auch die Interrupts mittels sei() freigegeben?


Tu dir selbst einen Gefallen und zeig IMMER deinen kompletten Code. Häng 
das File einfach als Attachment an, das ist schon ok.
Aber dadurch, dass du uns auf dieser Seite des Monitors Rätselraten 
lässt, was und wie du deinen Code verändert hast, wird die Sache nicht 
besser.

von Cyblord -. (cyblord)


Lesenswert?

sei() ist auskommentiert und kommt in setInt() nochmal vor, welche aber 
nicht aufgerufen wird. Was machst du da eigentlich fürn crap?
Was hat die "usart.c" mit deinen Interrupts und vorallem dem I-Bit zu 
tun? Das gehört da nicht rein. Kapsle deinen Code ordentlich. Jedes 
Modul hat ne bestimmte Aufgabe. Die Aufgabe der uart.c ist bestimmt 
NICHT die Interrupts global zu schalten.
Wäre so es so schwer in die main vor der Hauptschleife ein sei() zu 
machen? In deiner Arduino/Sketch Deppenumgebung wäre das dann wohl die 
setup(). Das sei() dort wieder entkommentieren.

von simon (Gast)


Angehängte Dateien:

Lesenswert?

Hallo, danke für eure Tipps.

Ich denke ich ahbe sie alle mit eingebunden.  Im Anhang findet ihr 
meinen Code.

Und hier die das Main-Programm

// Do not remove the include below
#include "rs232.h"
#include "usart.h"
1
ISR(USART0_RX_vect)          // USART1_RX_vect ?? funzt noch nicht!!!
2
{
3
  UDR0 = 'x';
4
}
5
6
//The setup function is called once at startup of the sketch
7
void setup()
8
{
9
  USART_init_();
10
  sei();
11
12
13
}
14
15
// The loop function is called in an endless loop
16
void loop()
17
{
18
19
}

AAUSGABE: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Nur zur Erklärung:
ich möchte mit einem Terminal-Programm ein Zeichen senden. dann soll die 
ISR() sich melden und ggf etwas senden.

Ich bin euch für die Hilfe sehr dankbar!


Viele Grüße,

von simon (Gast)


Lesenswert?

Hat denn niemand noch eine Idee??

bitte...

von Stefan E. (sternst)


Lesenswert?

simon schrieb:
> Hat denn niemand noch eine Idee??

Zu was denn genau? Den ganzen x-en etwa?
Das liegt daran, dass du in der RX-ISR das Datenregister nicht ausließt.

von Karl H. (kbuchegg)


Lesenswert?

simon schrieb:
> Hat denn niemand noch eine Idee??
>
> bitte...


Ja.
Lernen

AVR-Tutorial
AVR-GCC-Tutorial



Was ist denn momantan hier im Forum los?
Einer nach dem anderen schlägt mit 0 Wissen auf und erwartet, dass wir 
ihm seine Probleme lösen, weil er/sie nicht in die Tutorien und/oder 
Datenblatt sehen will um mal ein wenig nachzulesen.

von Cyblord -. (cyblord)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Was ist denn momantan hier im Forum los?
> Einer nach dem anderen schlägt mit 0 Wissen auf und erwartet, dass wir
> ihm seine Probleme lösen, weil er/sie nicht in die Tutorien und/oder
> Datenblatt sehen will um mal ein wenig nachzulesen.

Das Bachelor-System macht sich langsam bemerkbar. Und/Oder G8 ;-)

gruß cyblord

von Melk-Elko (Gast)


Lesenswert?

cyblord ---- schrieb:
> Das Bachelor-System macht sich langsam bemerkbar. Und/Oder G8 ;-)

Da brennt die Hütte. Bitte mal auf's Thema konzentrieren.

von simon (Gast)


Lesenswert?

Vielen Dank Stefan Ernst.

Da habe ich wirklich einen Denkfehler gehabt.

Nun funktioniert es.

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.