WCM Forum

WCM Forum (http://www.wcm.at/forum/index.php)
-   Home Cockpit - Das Forum für die "Bastler" (http://www.wcm.at/forum/forumdisplay.php?f=55)
-   -   AVR-Interrupts in C (http://www.wcm.at/forum/showthread.php?t=214427)

philharmony 26.04.2007 22:59

Der Grund war ganz einfach der, dass ich wie du schon erkannt hattest, die SIGNAL(SIG_INT0) benutzt habe, die der controller gar nicht kennt, denn sie heisst eben
SR(_VECTOR(1))
Wenn die die io.h im WINAVR-Verzeichnis zu finden ist, wie kann dann AVR-Studio darauf zugreifen? Oder gehören die Progs zusammen (weiss garnicht mehr ob ich die zs installiert habe oder einzeln)
Ich arbeite nur mitm AVR-Studio weil die Simulation damit eben möglich ist...

EDIT:
In der m8535.h stehen dann wiederrum Folgende Bezeichner:

Zitat:

/* External Interrupt 0 */
#define INT0_vect _VECTOR(1)
#define SIG_INTERRUPT0 _VECTOR(1)

/* External Interrupt 1 */
#define INT1_vect _VECTOR(2)
#define SIG_INTERRUPT1 _VECTOR(2)
Scheinen also alle möglichen Ausdrücke zu gehen...

AlTonno 30.04.2007 20:36

WinAVR ist eine avr-gcc-Distribution, die als Plug-In im AVR Studio arbeitet und das C-programmiern dort erst möglich macht.


Und wie du schon erkannt hast, die Interrupt-Routinen können entweder mit

ISR (INT0_vect) oder
ISR (SIG_INTERRUPT0) oder eben 'direkt' (ohne den Umweg über ein Define) mit
ISR (_VECTOR(1))

bezeichnet werden... durch die Defines muss man aber den Vektor nicht manuell anpassen, wenn man das Programm auf einem anderen Controller verwenden will.

lg

philharmony 01.05.2007 21:32

Ok, "klick" häts ´gmacht ;)
Als nächstes werde ich mich mal mit dem 2-Wire-Serial und mit USB-Steinen beschäftigen, dann hab ich alles zusammen was ich für diverse Panels brauche, fängt langsam richtig an Spass zu machen.
btw: hab HIER (Anfang unteres Drittel der Seite) was gefunden zur Drehrichtungserkennung von Phasenverschobenen Drehencodern. Der Beitrag mit dem "Greycode", hat das mal jemand versucht? ich verstehe da die super-kurz-kompakt C-Befehle nicht,
zb
Zitat:

DDRC &= ~ (DREH_A + DREH_B + DREH_TAST);
PORTC |= (DREH_A + DREH_B + DREH_TAST);
etc.
Mir ist auhc das Prinzip noch nicht ganz klar wie das gehn soll, aber es ist auf jeden Fall wenn ich es zum laufen kriege deutlich kürzer als meine bisherige REDEC-Programmierung...

AlTonno 01.05.2007 21:41

Die Auswertung von Greycode-Encodern erfolg im Prinzip durch periodisches Einlesen der zwei Phasen und vergleichen mit dem vorherigen Zustand... je nach Ergebnis dieses Vergleiches kann man dann auf die Drehrichtung rückschließen. Den c't-Artikel mag ich jetzt nicht lesen, aber ich vermut mal, dass wird dort eh sehr ausführlich erklärt ;)


Zum C-Code...

i += 2;
bedeutet nix anderes als
i = i + 2;

das gleiche gilt natärlich auch für andere Operanden (wie eben "&", "|", "-" usw)
Und das "~" invertiert den darauf folgenden Ausdruck bitweise.

lg

philharmony 02.05.2007 08:58

Habe den Graycode mal Zeile für Zeile auf Papier durchlaufen und komme zu folgendem Problem: Wenn ich langsam drehe, und in der 11-Position (beide Flanken high) mehrere Takte durchlaufen, dann Zählt er doch pro Takt um einen hoch.
Dazu noch das Problem dass dieses Beispiel pro Raste um 2 hochzählt (laut Beschreibung, ich komme sogar teilweise auf 3), was mache ich nun wenn ich um je einen hochzählen möchte?

philharmony 03.05.2007 23:20

Aahhaaaa, jetzt ises klar:
Der Kern liegt in dem
Zitat:

graycode >= 2;
Es wird also der jeweils vorherige Wert um zwei Stellen weitergeschoben un dann der aktuelle an die vohrherigen.
Dadurch entsteht ein vierstelliger Code mit zwei Stellen aktueller und zwei Stellen alter Wert. In der Tabelle staht dann für jede möglich Vorher-Nachher-Kombination die entsprechende Reaktion.
Wenn ich jetzt pro Raste nur um einen hoch- oder runterzählen will, dann muss in der Tabelle einfach überall eine Null stehen und nur bei zb
"vorher 00 und dann 01"-> wert++
und bei
"vorher 00 und dann 10"-> wert--

Is ja total genial und wirklich deutlich kürzer und schneller als meine "REDEC" und wenn ich es richtig sehe entfällt damit sogar ein entprellen, oder?

fluchtpunkt 04.05.2007 09:52

Hallo erstmal,


Zitat:

Original geschrieben von philharmony
Aahhaaaa, jetzt ises klar:
Der Kern liegt in dem
Zitat:

graycode >= 2;

also... graycode >=2; ist ein Vergleich ob graycode groesser oder gleich 2 ist. Was das an der Stelle soll versteh ich nicht, wird wohl ein Schreibfehler sein, gemeint war sicher graycode >>=2;


Und noch ein Hinweis zu den Interrupts, Variablen die im Interrupt geaendert werden solltest du als volatile deklarieren.
Statt "int i;" einfach "volatile int i;" schreiben. So zwingt man den Compiler vor jedem Lesezugriff auf die Variable den aktuellen Wert aus dem Speicher zu lesen und bei jedem Schreibzugriff den Wert in den Speicher zurueckzuschreiben, so verhindert man das der Compiler zu sehr optimiert.

Kleines Beispiel:
Code:

int main(void)
{
  while(1)
  {
    x++;
    if ( x >= 1000 )
      do_something();
  }
}

Der Compiler wuerde x einmal in ein Register laden und dann immer mit diesem Register rechnen.
Wenn nun ein Interrupt eintritt der wie folgt aussieht
Code:

ISR(TIMER1_COMPA_vect)
{
  x = 1000;
}

Wird zwar der Speicher von x auf 1000 gesetzt, da das main-Programm allerdings x immer nur aus dem Register liest wird es nie merken das x auf 1000 gesetzt wurde.
Hoffe das war ein wenig verstaendlich.

Mehr Informationen gibts zB hier: http://www.mikrocontroller.net/artic...R-GCC-Tutorial

philharmony 04.05.2007 13:23

Zitat:

graycode >=2
Bedeutet dann aber "um 2 verschieben" oder?
Sonst macht die ganze Überlegung keinen Sinn...
Mit dem volatile ist nach deine super Erklärung nun auch klar.
Es geht voran.
Jetzt fehlen eben nur noch dach 2wire-Serial und die USB-Vernetzung.
Dazu werd ich Euch dann sicher demnächst wieder löchern...

philharmony 04.05.2007 21:35

Hm, wisst Ihr welche *.h ich noch includen muss damit die Befehle sbi und cbi funktionieren? (set/clear bit)
Mit io.h gehts erkennt er die nicht...

AlTonno 05.05.2007 09:45

Die Funktionen sbi/cbi finden sich nur mehr in alten avr-libc Versionen... heutzutage verwendet man diese Funktionen nicht mehr.

Stattdessen werden einzelne Bits sehr übersichtlich und ISO-C konform so gesetzt:

REG |= (1<<BIT);
z.B. PORTB |= (1<<PB2);

und so gelöscht

REG &= ~(1<<BIT);
also z.B. PORTB &= ~(1<<PB2);


Das ist zwar etwas mehr Schreibarbeit, kann aber im späteren Entwicklungsstadium und bei größeren Programmen wirklich seeeeeeehr hilfreich sein.


lg


Alle Zeitangaben in WEZ +2. Es ist jetzt 07:33 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
© 2009 FSL Verlag