Forum: Mikrocontroller und Digitale Elektronik Interruptroutine funzt nicht


von Tom (Gast)


Lesenswert?

Hallo zusammen,

ich habe ein kleines Problem.

Der unten stehende Quellcode sollte folgende Bedienungsmöglichkeiten 
realisieren:

Es wird ein Gerät gebaut, welches über Taster am Gerät oder wahlweise 
über RS232 über Kontroll-Rechner (LabView, dSpace...) bedient werden 
soll. Mein Vorhaben wäre, in der Arbeitsschleife die Tasten zu pollen 
bzw. über eine EMPFÄGER-INTERRUPTROUTINE Zeichen über RS232 zu 
empfangen, diese zu vergleichen und ebenfalls Befehle ausführen. 
(Befehle RS232 und Taster sind identisch). Leider mache ich die 
Einbindung der Interruptroutine falsch.

Könnt Ihr mir bitte weiterhelfen? Ich hab auch im Tutorial nichts 
passendes gefunden.

Vielen Dank im Voraus.

Gruß

Tom

************************************************************************ 
***

//HEADERDATEIEN
#include <avr/io.h>    //Deklarationen
#include <avr/interrupt.h>    //Headerdatei mit Interruptfunktionen
#include <avr/own_timestep.h>  //Eigene Headerdatei mit Delay-Fkt. usw.
#include <avr/own_uart.h>    //Eigene Headerdatei mit RS232-Fkt.
#include <avr/own_ref.h>    //Eigene Headerdatei mit der kompletten 
Referenzfunktion

//FESTLEGUNG UNABHÄNGIGER TYPENNAMEN
typedef unsigned int uint16;
typedef signed int sint16;
typedef unsigned char uint8;
typedef signed char sint8;

//GLOBALE VARIABLEN UND STRINGS
uint8 eingabe = 0;  //Hilfsvariable für RS232-Steuerung
uint8 enter = 0;  //Hilfsvariable für RS232-Steuerung
uint8 init[] = "\n\n\rRS232 initialisiert.\n\rSystem referenziert\n\r";
uint8 command[] = "\n\rBitte einen Befehl auswaehlen: \n\r\t1: 
Referenzfahrt\n\r\t2: Messfahrt 0 bis 360 \n\r\t3: Messpunkt +\n\r\t4: 
Messpunkt - \n\n\r\tAuswahl bitte mit Enter bestaetigen\n\r\t";
uint8 falsch[] = "\n\n\r\t!!FALSCHE EINGABE!!\n\r\t";

//SERVICEROUTINE FÜR EMPFÄNGERINTERRUPT
SIGNAL(SIG_UART_RECV)
{
         //Einlesen zweier Werte über RS232 und Übergabe an 
Hilfsvariablen
  getche();
  eingabe = got_cha;
  getche();
  enter = got_cha;
  cli();  //Alle Interrupts global sperren
}

//HAUPTFUNKTION
int main (void)
{
  //Portzuweisungen
  DDRA = 0x7f;
  DDRB = 0xff;
  DDRC = 0x00;
  DDRD = 0x80;

  initusart();  //UART initialisiert; Funktion in own_uart.h

  UCSRB |= RXCIE;  //Empfängerinterrupt frei
  sei();  //Alle Interrupts global frei

  //AUFFORDERUNG FÜR REFERENZFAHRT
  while(PINC & (1<<PC3))
  {
    PORTD &= ~(1<<PD7);
    delay(50000);
    PORTD |= (1<<PD7);
    delay(50000);
    PORTD &= ~(1<<PD7);
  }

  referenz();

  //BILDSCHIRMAUSGABE ÜBER RS232
  uint8 *pinit;  //String Init
  pinit = init;

  uint8 *pcommand;  //String Eingabeaufforderung
  pcommand = command;

  uint8 *pfalsch;  //String Falsche Eingabe
  pfalsch = falsch;

  //Bildschirmausgabe RS232 initialisiert
  while(*pinit != 0)
  {
    putch(*pinit++);
  }

  //Bildschirmausgabe Eingabeaufforderung
  while(*pcommand != 0)
  {
    putch(*pcommand++);
  }

  putch(0x07);  //Akustisches Signal


    // *** ARBEITSSCHLEIFE ***
  while(1)
  {
    //MÖGLICHKEIT ERNEUTER REFERENZIERUNG
    if(!(PINC & (1<<PC3)))// Taste "Ref"
      {
        referenz();
      }

    //MESSFAHRT 0° bis 360°
    if(!(PINC & (1<<PC2)))// Taste "Messfahrt 0° bis 360°"
      {
        uint16 i;
        for(i = 6400; i>0; i--)
        {
          Step_plus_micro();
        }
        PORTA &= ~(1<<PA2) & ~(1<<PA3) & ~(1<<PA4) & ~(1<<PA5);
      }

    //POLLEN DER EINGABE ÜBER KONTROLL-RECHNER
    if((eingabe == 0x31) && (enter == 0x0d))
    {
        referenz();
        eingabe = enter = 0;
    }
  }
  return 0;
}

von Boxi B. (boxi)


Lesenswert?

UCSRB |= (1<<RXCIE);

nicht


UCSRB |= RXCIE;

?

von Boxi B. (boxi)


Lesenswert?

in einer ISR verwendete Variablen sollten volatile deklariert werden

von Tom (Gast)


Lesenswert?

Hallo Boxi Boxitec,

vielen vielen Dank für Deine Hilfe. Natürlich gehts jetzt.

Ohne Schmarrn, ich schau schon mind. eine Stunde meinen Code an und hab 
nix gefunden.

Danke und Gruß

Tom

von Johannes M. (johnny-m)


Lesenswert?

Boxi Boxitec wrote:
> in einer ISR verwendete Variablen sollten volatile deklariert werden
Damit es keine Missverständnisse gibt: Nur Variablen, die sowohl in 
einer ISR als auch im Hauptprogramm verwendet werden (was auf die hier 
vermutlich gemeinte Variable "eingabe" allerdings zutrifft), sollten 
volatile sein. Variablen, die ausschließlich in einer ISR verwendet 
werden, dagegen nicht.

@Tom:
> eingabe = enter = 0;
Bist Du ganz sicher, dass das so sein soll?

Abgesehen davon hat Boxi recht: UCSRB |= RXCIE ist falsch, es sei denn, 
Du hast RXCIE irgendwo umdefiniert...

von Boxi B. (boxi)


Lesenswert?

unser blödes hirn sieht halt immer nur das, was es schreiben wollte, 
nicht was geschrieben wurde...

von Falk B. (falk)


Lesenswert?

@ Tom (Gast)

>Könnt Ihr mir bitte weiterhelfen? Ich hab auch im Tutorial nichts
>passendes gefunden.

Sicher? Glaub ich nicht. Vor allem, weil di den Interrupt in der alten 
Schreibweise deklariert hast.
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#ISR

Ausserdem fehlt der Quelltext für deine Funktionen, da kann man keine 
Aussagen treffen.

cli() am Ende eines Interrupts ist reichlich sinnlos.
Wozu eigene delay-Funktionen? Gibt es fertig getestet.
Lass den Unsinn mit den eigenen typedefs. Stdint hält wunderbare Typen 
bereit, uint8_t etc.

Aber der Hammer ist. Du hast das Prinzip des UART RX Interrupts noch 
nicht verstanden. Zweimal getche() im Interrupt ist Nonsense!

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Programmieren_mit_Interrupts

MFG
Falk

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.