Forum: Mikrocontroller und Digitale Elektronik AN2131 Interrupts in C verwenden


von Sebastian Lenz (Gast)


Lesenswert?

Hallo,

bin durch google auf dieses tolle Forum hier gestoßen, nur das was ich
suche hab ich hier nicht gefunden.

Ich suche mal einen Beispiel-Code für den AN2131 von Cypress (in C) der
den Interrupt von Port B6 benutzt. Laut Referenz ist das INT6 aber ich
hab weder in der Headerdatei so etwas in der Art gefunden, noch weiß
ich wie ich an den ran kommen soll.

mfg
Sebastian

p.S.: Achtung! Anfänger auf dem µC Gebiet, mach das zu liebe meines
Elektronik Lehrers, der sich mit Programmieren überhaupt nicht auskennt
;)

von Peter D. (peda)


Lesenswert?

Schau mal in Deiner Keil-Installation im Verzeichnis "Examples" nach,
da sollten Interruptbeispiele drin sein oder auf der Keil Webseite gibt
es auch ne Menge Informationen.

http://www.keil.com/discuss/


Peter

von Thomas (Gast)


Lesenswert?

#define IE6_VECTOR  12 // 0x63 External Interrupt 6

danach kannst du mit

void Irq6 (void) interrupt IE6_VECTOR
{
   ...
}

den Interrupt benutzen.

von Sebastian L. (quizzmaster)


Lesenswert?

Vielen Dank, so ein Beispiel hab ich gebraucht, da wär ich nie im Leben
drauf gekommen :)

Gibts dafür Lektüre, wo man sowas nachlesen bzw. mal lernen kann?
WEil ich will vielleicht auch noch mit dem Nachfolger mir eine Platine
basteln und dazu wär so etwas sehr Hilfreich.

Technische Referenz hilft mir ja nur im Bezug auf INT6 weiter, aber
nicht mehr.

von Sebastian L. (quizzmaster)


Lesenswert?

Eben hab ich das mal ausprobiert und es hat leider nicht Funktioniert
:(

Ich hab das einfach dem beigefügten Beispielprogramm hinzugefügt, muss
man da außerdem den Interrupt nicht noch aktivieren?
Hier mal mein Quelltext:

/*---------------------------------------------------------------------- 
--------
Blink.C

Copyright 1999-2003 by MmVisual - M.Müller
Erstellung BlinkLED 29.12.2001
------------------------------------------------------------------------ 
--------
Testprogramm "Blinkende LED"

LED ist an Port PA4 des Cypress- Chips angeschlossen. Es wird nur
dieser eine
Port als Ausgang definiert. Das Programm kann in den Speicher des
AN21xx geladen
und gestartet werden. Sofort muss die LED anfangen zu Blinken (ca. 3
Hz).
------------------------------------------------------------------------ 
------*/

#include <REGAN21.H>      /* Register des AN21xx  */
#include <EZREGS.H>        /* Externe Register des AN21xx  */

// Definitionen der Routinen

// Belegung des Speichers
xdata unsigned char T0LED;
xdata unsigned char LED_BLINK at 0x0101;  // LED blinken lassen
xdata unsigned char LED_COUNT at 0x0100;  // Blinkende LED - Zähler
nach Timer

xdata unsigned char iOEA at 0x0110;
xdata unsigned char iOEB at 0x0111;
xdata unsigned char iOEC at 0x0112;
xdata unsigned char iOUTA at 0x0113;
xdata unsigned char iOUTB at 0x0114;
xdata unsigned char iOUTC at 0x0115;
xdata unsigned char iPINSA at 0x0116;
xdata unsigned char iPINSB at 0x0117;
xdata unsigned char iPINSC at 0x0118;

/*------------------------------------------------
Definition für INT6 und Interrupt selbst (P B.6)
------------------------------------------------*/
#define IE6_VECTOR  12 // 0x63 External Interrupt 6

void Irq6 (void) interrupt IE6_VECTOR
{
  iOEC = 0xFF;
  iOUTC = 0xFF;

  OEC = 0xFF;
  OUTC = 0xFF;

  LED_BLINK = 0;
}

/*------------------------------------------------
The main C function.  Program execution starts
here after stack initialization.
------------------------------------------------*/
void main()
{  EA = 0;

  // Ohne die folgenden 5 Zeilen kann das USB-Board sich nicht am
USB-Port melden,
  // wenn Sie aus der IIC- Datei ein EEPROM herstellen!!!
  EUSB = 1; // Enable Firmware- USB
  USBCS = 4;
  USBIRQ = 0x1E;
  IBNIRQ = IBNIEN = TOGCTL = 0;
  EPIO[0] = 0x0A; // Enable Firmware- USB Ende

  OUTA = 0x00;    // Register vorbelegen
  OEA = 0x30;      // LED-Out ausschalten
  T2CON = 3;    // Timer 2 aus
  TR0 = 0;    // Timer 0 aus
  T1M = 0;    // Clock div 12
  CT1 = 0;    // Timer- Betrieb ein
  TH1 = 0x07;    // H-Register laden
  TL1 = 0xC0;    // L-Register laden insgesamt: 0xF831
  TF1 = 1;    // Interrupt ein
  ET1 = 1;    // Timer 1 Interrupt ein
  TR1 = 1;    // Timer 1 einschalten
  EA = 1;      // Interrupt ein
  LED_COUNT = LED_BLINK = 1;  // Zähler zurücksetzen und Blinken
einschalten
  PORTACFG = 0;
  PORTBCFG = 0;
  PORTCCFG = 0;
  iOUTA = 0x00;    // Register vorbelegen
  iOEA = 0x30;      // LED-Out ausschalten

  while (1)    // IO- Werte kopieren ...
  {  OEA = iOEA;
    OEB = iOEB;
    OEC = iOEC;
    OUTA = iOUTA;
    OUTB = iOUTB;
    OUTC = iOUTC;
    iPINSA = PINSA;
    iPINSB = PINSB;
    iPINSC = PINSC;
  }
}

//————————————————————————————————————————————————————————————————
// Timer für ms- Zähler
static void T1_isr (void) interrupt 3 using 3
{  TL1 = 0xC0;    // L-Register laden insgesamt: 0xF831
  TH1 = 0x07;    // H-Register laden
  if (LED_BLINK)
  {
    if (LED_COUNT-- == 0)  // Zähler zurücksetzen
    {  LED_COUNT = 50;    // Schleifenzähler neu setzen
      iOUTA ^= 0x10;    // LED umschalten
      OUTA = iOUTA;
    }
  }
}

von Thomas (Gast)


Lesenswert?

// Belegung des Speichers
xdata unsigned char T0LED;
xdata unsigned char LED_BLINK at 0x0101;  // LED blinken lassen
xdata unsigned char LED_COUNT at 0x0100;  // Blinkende LED - Zähler

Deine Software wird warscheinlich nie funktionieren.
der Cypress hat gemeinsamen Code und XDTA Speicher!!
deine Definitionen landen also im Code Mem ab 0x0100

besser wäre
// Variablen im DMem ACHTUNG Memory Model Small einstellen
unsigned char T0LED;
unsigned char LED_BLINK ;  // LED blinken lassen
unsigned char LED_COUNT ;  // Blinkende LED - Zähler

2.
woher hast du diese komischen At Referenzen.Die XDATA SFRs liegen an
ganz andern Positionen irgendwo bei 0x1F?? beim AN2131 oder bei 0x7Fxx
bei FX1 oder FX2.

Du solltet doch mal einen Blick ins TRM Manual werfen da steht das
übrigens auch mit dem Interrupt 6  drin :-)

Thomas

von Sebastian L. (quizzmaster)


Lesenswert?

Das mit dem at hab ich aus dem Beispielprogramm, was dabei war.

Ich probier es mal mit deiner Variante, vielleicht hilft das.

von Sebastian L. (quizzmaster)


Lesenswert?

Ich meine, ich muss den Interrupt irgendwo noch aktivieren, denn es geht
so nicht :(

Zur Info: Ich möchte den Interrupt an Port B6 benutzen.

So, hab jetzt mal nur folgenden Code:

#include <REGAN21.H>      /* Register des AN21xx  */
#include <EZREGS.H>        /* Externe Register des AN21xx  */


#define IE6_VECTOR  12 // 0x63 External Interrupt 6

void Irq6 (void) interrupt IE6_VECTOR
{
  OEC = 0xFF;
  OUTC = 0xFF;
}

void main()
{
  while (1)
  {
  }
}

von Peter Dannegger (Gast)


Lesenswert?

Das at ist dazu da, um memory mapped Peripherie anzusprechen.
Die wird ja über einen Adreßdekoder ausgewählt und deshalb muß man dem
Compiler sagen, an welcher Adresse sie sich befindet.


Für die Verwaltung des SRAM ist at nicht geeignet, daß kann der
Linker nämlich viel besser und vor allem fehlerfrei.


Peter

von Thomas (Gast)


Lesenswert?

In dem Beispiel waren das aber Offsets auf den Start im XMEM
deklarieret mit einem Macro. Das solltest du schon verstanden
haben.
Ich habe noch mal im TRM 1.9 pdf nachgeschaut (Seite 265)
zb. OEA liegt bei 0x7F96
woher kommt denn das iOEA das ist eine ganz normale C Variable

also entweder
xdata unsigned char iOEA at 0x7F96;
dann bekommst du eventuel einen Overlap error weil die Teile
ja schon mit anderen Namen im H File definiert sind
oder
extern xdata unsigned char OEA;


Thomas

von Sebastian L. (quizzmaster)


Lesenswert?

die iXXX Variablen sind an dieser stelle, weil man auf diese RAM
Adressen von außen über den USB-Port zugreifen kann und so diese auch
vom PC aus setzen und auslesen kann. trotzdem funktioniert der INT6 so
wie oben beschrieben nicht, obwohl ich in der main Funktion nur noch
eine while schleife hab

von Thomas (Gast)


Lesenswert?

na ja wo steht EA=1 ?
Du musst den Interrupt freigeben und dann EA = 1 setzen.
dann geht das schon. Auserdem muss der Portpin entsprechend
eingestellt werden.
TRM gelesen?

Thomas

von Sebastian L. (quizzmaster)


Lesenswert?

TRM hab ich dazu noch nicht gelesen, aber wo gebe ich den Interrupt
frei?

Das war eigentlich jetzt noch mein Problem, weil ich weiß auch nicht wo
genau ich da im TRM ich nachlesen muss.

Bitte Rücksicht nehmen bin auf dem Gebiet der totaler Anfänger

von Thomas (Gast)


Lesenswert?

Suche halt mal nach INT6 im PDF und lies die entsprechenen Stellen
Dann wirst du schon fündig.
Nur so lernst du auch wie man da vorgeht. Die Dokumentation von
Cypress ist wirklich gut.

Thomas

von Sebastian L. (quizzmaster)


Lesenswert?

Zitat:
<<EX6 - Enable external interrupt 6. EX6 = 0 disables external
interrupt 6
(INT6). EX6 = 1 enables interrupts generated by the INT6 pin.>>
Zitatende.

Das sagt mir jetzt, das ich EX6 = 1 machen soll, aber die Variable ist
nicht definiert :(

außerdem hab ich was von PORTBCFG gefunden, weiß aber nicht genau wie
ich das setzen soll. habs mim hexwert 40 probiert (aus dem binärwert
laut tabelle Anhand D S. 60

Vielleicht könnt ihr in diesem Fall mal ein Beispiel nennen, wie ich
auf sowas komme, danke jetzt schonmal, bis jetzt war die Hilfe perfekt!

von Thomas (Gast)


Lesenswert?

#define IE6_VECTOR  12 // 0x63 External Interrupt 6

void Irq6 (void) interrupt IE6_VECTOR
{
  OEC = 0xFF;
  OUTC = 0xFF;
  INT6 = 0;    // INT6 Flag löschen
}

void main (void)
{
   EA=0;           // Interrupts sperren
   PORTBCFG |=0x40;// alternate Function for PB6
   EIE |=0x10;     // oder EIX6 = 1; siehe EzRegs.h
   INT6 =0;        // Flag sicherheitshalber löschen
   EA=1;           // und IRQs freigeben
   while(1)
   {
      //
   }
}


jetzt sollte mit jeder LowHigh Flanke an PB6 der Interrupt kommen.
Der INT5 würde übrigens mit dem passenden Programm das gleiche auf
der HighLow Flanke machen.

Thomas

von Sebastian L. (quizzmaster)


Lesenswert?

Vielen Vielen Dank!!

hab jetzt noch ein paar Fragen ;)
-Wie komme ich auf das |= ?? Was bedeutet das?
-Was ist das bei EIE ?? EIX6 steht im TRM EIE auch, aber wie komm ich
auf das 0x10 ??


Und noch eine kleine Frage am Rande:
Der Interrupt funktioniert jetzt nur setzt er mir den Pin C3 nicht :(
keine Ahnung warum, funktionieren tut er und alle anderen tuen es auch,
nur in diesem Programm funktioniert C3 nicht :(

Ich kann mir das nicht erklären.

von Sebastian L. (quizzmaster)


Lesenswert?

sorry, aber eben geht C3, ka wieso der eben nicht ging...

von Thomas (Gast)


Lesenswert?

nun EIA ist das Extended Interrupt Enable Register
Dieses Register hat eine durch 8 teilbare Addresse und ist
deshalb auch bitaddressierbar.

im EzRegs.h findest du die Definitionen.
EIEX6 ist das Bit No. 4 im Register wehalb ich gezielt dieses
Bit mit EIA |= 0x10 gesetzt habe (2^4 = 16 = 0x10)
EIA = EIA | 0x10; wäre die ausführliche Schreibweise.
Der Inhalt von EIA wird einfach mit 0x10 ODER verknüpft und
dann zurückgeschrieben.

EA kannst du auch auf zweierlei Arten setzen
1. EA=1;
2. IE |= 0x80; // Bit 7 im IE Register

Das sind std Bit Masken Operationen
 | zum Setzen      OR
 & zum rücksetzen  AND
 ^ zum invertieren XOR

NT6 = 0; kann man auch so schreiben:
EICON &= ~0x08;

Den Rest musst du dir mit einem C Tutorial schon selbst beibringen.

von Sebastian L. (quizzmaster)


Lesenswert?

VIELEN DANK!!!

das is die perfekte erklärung, Bitoperationen kenn ich ja, aber nicht
diese kurzschreibweise und danke auch für die erklärungen der Variablen
:)

ich bin noch am überlegen ob ich mir noch den 2. band vom elektor
verlag hole C-Programmierung für 8051

von Thomas (Gast)


Lesenswert?

Lass die Finger von Elektor Büchern die taugen nix.
Ein gutes Buch wäre zum Beispiel der Batischweiler
mehr unter www.c51.de

Ansonsten kann ich eigendlich nur englische Literatur empfehlen
Um Englisch kommst du aber sowiso nicht herum.

http://www.intel.com/design/mcs51/docs_mcs51.htm#Manuals
http://www.semiconductors.philips.com/acrobat_download/various/80C51_FAM_ARCH_1.pdf
http://www.semiconductors.philips.com/acrobat_download/various/80C51_FAM_HARDWARE_1.pdf
http://www.semiconductors.philips.com/acrobat_download/various/80C51_FAM_PROG_GUIDE_1.pdf

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.