AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

ISR in C erstellen

Ein Thema von Elko · begonnen am 28. Jul 2009 · letzter Beitrag vom 29. Jul 2009
Antwort Antwort
Elko

Registriert seit: 2. Feb 2008
52 Beiträge
 
Delphi 7 Personal
 
#1

ISR in C erstellen

  Alt 28. Jul 2009, 16:45
Hallo,
kann mir jemand erklären wie man eine ISR in C erstellt? Ich habe hier auch eine fertige ISR, jedoch weiß ich nicht, was die einzelnen Elemente bedeuten
Code:
static void T1_isr (void) interrupt 3
{   TL1 = 0xC0;      // L-Register laden insgesamt: 0xF831
   TH1 = 0x07;      // H-Register laden

// ... Quelltext

}

Gruß,
elko

PS: Das ist eine Timer-ISR, wenn ich mich nicht täusche
Keyboard not found. Press any key to continue.
  Mit Zitat antworten Zitat
Benutzerbild von OldGrumpy
OldGrumpy

Registriert seit: 28. Sep 2006
Ort: Sandhausen
941 Beiträge
 
Delphi 2006 Professional
 
#2

Re: ISR in C erstellen

  Alt 28. Jul 2009, 18:05
Zitat von Elko:
Code:
static void T1_isr (void) interrupt 3
Eine Interrupt Service Routine ist eine statische (static) Routine, die keinen Rückgabewert hat (void), und einem bestimmten logischen Interrupt zugeordnet ist (interrupt 3). Die Nummer entspricht in der Regel einem Index auf eine Tabelle von Interruptvektoren (Funktionsadressen an die bei Auftreten eines Interrupts gesprungen wird), je nach Architektur gibts da unterschiedliche Tabellen, manche trennen Software- und Hardware-Interrupts (Software-Interrupts werden durch bestimmte Prozessoranweisungen ausgelöst, Hardware-Interrupts durch entsprechende Ereignisse innerhalb des Prozessors oder Signale von aussen an bestimmten Pins), aber ansonsten gibts da nicht viel zu berichten. Die Besonderheiten werden hier vom C-Compiler erledigt der durch das Schlüsselwort "interrupt" halt weiss, dass das keine normale Routine ist.

Wichtig ist halt normalerweise:

Eine ISR darf keine Register verändern (ausser wenn das explizit gewünscht wird, siehe Interrupts in DOS), wenn die Hardware also nicht selber die Register sichert, muss der Programmierer sich darum kümmern. In der Regel werden dazu alle relevanten Registerinhalte einfach auf den Stack gepackt und am Ende der ISR wieder zurückgeholt. Alternative Konzepte verwenden eine Art Bankswitching um Register zwischen "Normal" und "Interrupt" zu trennen.

Der Rest ist eigentlich relativ trivial, je nach Plattform muss man nur wissen welche Interrupts wie benutzbar sind und ggf. noch auf die Prioritäten schauen (manche Architekturen erlauben Interrupts mit unterschiedlicher Priorität, ein Interrupt einer bestimmten Priorität kann dann nur von Interrupts höherer Priorität unterbrochen werden).

Zitat von Elko:
Code:
{   TL1 = 0xC0;      // L-Register laden insgesamt: 0xF831
   TH1 = 0x07;      // H-Register laden

// ... Quelltext

}
Und das ist nun nichts spezifisches für eine ISR, da wird irgendein 16-Bit-Register mit zwei 8-Bit-Werten gefüllt. Ist das zufällig etwas für Atmel?

Zitat von Elko:
PS: Das ist eine Timer-ISR, wenn ich mich nicht täusche
Das kann so gut wie alles mögliche sein, was es nun wirklich ist, ergibt sich erst aus der Kombination von Hardwaredokumentation (Prozessorhandbuch) und komplettem Source
"Tja ja, das Ausrufezeichen... Der virtuelle Spoiler des 21. Jahrhunderts, der Breitreifen für die Datenautobahn, die k3wle Sonnenbrille fürs Usenet. " (Henning Richter)
  Mit Zitat antworten Zitat
Elko

Registriert seit: 2. Feb 2008
52 Beiträge
 
Delphi 7 Personal
 
#3

Re: ISR in C erstellen

  Alt 28. Jul 2009, 21:51
Hey, danke für die Info!
Ich programmiere zur Zeit für den AN2131 von Cypress. Das ist ein USB-Controller... Leider komme ich mit der Entwicklungsumgebung von Keil, MVision3 noch nicht ganz klar (bezüglich dem Debugger).
Diese ISR bringt normalerweise eine LED an einem Port zum Blinken (den Quelltext hab ich oben rausgenommen). Mein Problem liegt jetzt darin, dass -wenn man die ISR nich auskommentiert- folgendes eigentlich winzige Programm nicht funktioniert...
Code:
void main()
{

// ...

while (1)
{          
      var1=3;       
      OUTC=var0;
      var0=hallo();
      OUTC=var0;
}

}

          
unsigned char hallo(){
return 7;
}


//————————————————————————————————————————————————————————————————
// Timer für ms- Zähler   (bringt die LED A4 blinken)

static void T1_isr (void) interrupt 3
{//   TL1 = 0xC0;      // L-Register laden insgesamt: 0xF831
//   TH1 = 0x07;      // H-Register laden
   TL1 = 0xC0;      // L-Register laden insgesamt: 0xF831
   TH1 = 0xA0;      // H-Register laden
   if (LED_BLINK)
   {
      if (LED_COUNT-- == 0)   // Zähler zurücksetzen
      {   LED_COUNT = 50;      // Schleifenzähler neu setzen
         OUTA ^= 0x10;      // LED umschalten
      }
   }
}
Viele Grüße,
elko
Keyboard not found. Press any key to continue.
  Mit Zitat antworten Zitat
Benutzerbild von Die Muhkuh
Die Muhkuh

Registriert seit: 21. Aug 2003
7.332 Beiträge
 
Delphi 2009 Professional
 
#4

Re: ISR in C erstellen

  Alt 28. Jul 2009, 22:34
Hi,

Dein Timerinterrupt wird ca. alle 25 Millisekunden aufgerufen.

TH1 und THL1 stehen für Timer 1 High und Timer 1 Low.

Die Werte erben A0C0, was umgerechnet 41152. Ich gehe mal davon aus, dass der Timer im 16 Bit Modus arbeitet, somit findet bei 2^16 ein Interrupt statt, also alle 24,384 Millisekunden. Da nun in der If-Abfrage was von wegen 50x runterzählen ist, blinkt die LED im 50x 24,384 Millisekunden Takt, also alle 1,2 Sekunden.

Wie schaltest Du den Interrupt ein?
  Mit Zitat antworten Zitat
Elko

Registriert seit: 2. Feb 2008
52 Beiträge
 
Delphi 7 Personal
 
#5

Re: ISR in C erstellen

  Alt 28. Jul 2009, 23:18
Hi,
Zitat:
Wie schaltest Du den Interrupt ein?
tja, das ist eine sehr gute Frage... ich probiere jetzt noch mal ein bisschen rum, aber von den verschiedenen Registern habe ich leider sehr wenig Ahnung... Im folgenden findest Du das "Basisprogramm", auf dem ich alle C-Programme für den AN2131 aufgebaut habe. Darin ist dann logischerweise auch enthalten, wie deer Interrupt eingeschaltet wird. Es wäre echt super, wenn Du mir die mit " //*****" markierten Zeilen erklären könntest! Das stellt für mich teilweise nämlich echt ein Rätsel dar, weil es im Netz auch nur sehr wenig Anfängergerechte Erklärungen gibt
Aber ich finde es toll, wie du auf die 25 ms gekommen bist! Das könnte sehr gut mit der Blinkfrequenz übereinstimmen!

Code:
/*------------------------------------------------------------------------------
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;

/*------------------------------------------------
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;
      }
   }
}
Wieso muss man den Timer-Interrupt eigentlich einschalten? Würde der Timer ansonsten laufen, wie vorgesehen, aber kein Interrupt und damit auch keine ISR ausgelöst?

Viele Grüße,
elko
Keyboard not found. Press any key to continue.
  Mit Zitat antworten Zitat
Benutzerbild von OldGrumpy
OldGrumpy

Registriert seit: 28. Sep 2006
Ort: Sandhausen
941 Beiträge
 
Delphi 2006 Professional
 
#6

Re: ISR in C erstellen

  Alt 29. Jul 2009, 12:33
Die Zeilen die du da markiert hast, konfigurieren die Hardware indem in spezielle Register bestimmte Werte geschrieben werden. Du solltest dringend mal die Dokumentation zu dem Chip lesen, da stehen auch alle Register mit Beschreibung drin. Jedes Register hat einen bestimmten Zweck und wird mit einer Abkürzung versehen, diese Abkürzungen stehen dann auch mit den entsprechenden zugehörigen Adressen in z.B. einem Headerfile, so dass man mit diesem Konzept im Code gut lesbar direkt schreiben kann "MeinRegisterName = 0x1234;" oder was auch immer. Prinzipiell gilt beim Reset so eines Microcontrollers: Alle Interrupts sind erstmal gesperrt (spezielle Ausnahmen bestätigen die Regel) und alle Timer sind angehalten. So verhindert man dass der Controller beim Anlegen der Versorgungsspannung irgendwelchen Unsinn macht. Das darauf laufende Programm muss dann explizit jede genutzte Resource passend konfigurieren. Das wird in den Zeilen gemacht die Du markiert hast. Die Registernamen die Du dort siehst, findest Du in der Dokumentation zu dem Prozessor wieder, dort ist dann auch beschrieben was jedes Register für eine Aufgabe hat. Faustregel: Alles was Du benutzen willst, musst Du erstmal passend einstellen.

Nachtrag: Das Manual gibts zum Beispiel hier, besonders interessant für Dich sind erstmal die sogenannten SFRs (Special Function Registers).
"Tja ja, das Ausrufezeichen... Der virtuelle Spoiler des 21. Jahrhunderts, der Breitreifen für die Datenautobahn, die k3wle Sonnenbrille fürs Usenet. " (Henning Richter)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:22 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz