Forum: Mikrocontroller und Digitale Elektronik STM8 An welchen Pin wird der Interrupt ausgelöst und Interrupt zählen


von Micha J. (micha_j)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

wie finde ich heraus, welche GPIO Pinnummer am Port B einen externen 
Interrupt auslöst?
Mein Ansatz war, dass ich zuerst die ersten vier Bits vom GPIOB-Port in 
einer Variablen speichere und maskiere dann das Bit vom gesuchten Pin. 
Aber wie man auf dem Bild sehen kann, wird auch der counter_Pin0 
fälschlicherweise gezählt, wenn durch den Pin 1 ein Interrupt auslöst 
wird.
Ich habe zur Positionsbestimmung 4 Sensoren und jeder der Sensoren 
liefert 4 Interrupts. Aber durch die Problematik wie im Bild, zähle ich 
nicht 4 Interrupts an Pin0, sondern zum Beispiel 11.
1
INTERRUPT_HANDLER(EXTI_PORTB_IRQHandler, 4)
2
{
3
    data = (uint8_t)GPIOB->IDR& 0xF;
4
5
    if((GPIO_PIN_0 & data )== GPIO_PIN_0) {
6
      counter_Pin0++;
7
    }
8
    if((GPIO_PIN_1 & data )== GPIO_PIN_1) {
9
      counter_Pin1++;
10
    }
11
}
Wie löse ich es, dass ich mehrfaches Zählen verhindere und herausfinde, 
welcher Interrupt auslöst?

Viele Grüße und Danke
Michael

von Achim M. (minifloat)


Lesenswert?

Hi, für mich sieht das irgendwie so aus, als hättest du drei Probleme 
auf einmal

1. Die Interruptquelle prellt. Da kannst du nur Hardware-Filter dagegen 
einsetzen.

2. Die Zuordnung, welcher der Pins der erste war und damit den Interrupt 
ausgelöst hat, geht verloren. Da gibt es auf die Weise wie von dir 
gelöst, kein Mittel dagegen. Ob der STM8 'auslösender-Pin-Latches' hat, 
weiß ich nicht.

3. Dein Bild zeigt, dass der Interrupt  auf negative Flanke reagieren 
soll. Bei der Zählmimik zählst du aber alle Pins hoch, die beim Lesen 
des IDR auf 1 standen. Klar kommen da zuviel Counts raus und es werden 
fast nur die gezählt, die nicht der Auslöser waren. Eigentlich müsstest 
du die Eingänge, die auf 0 stehen, um die Trigger zu zählen. Was du aber 
genau willst, ist mir wegen 2. Nicht klar.

mfg mf

: Bearbeitet durch User
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Micha J. schrieb:
> habe zur Positionsbestimmung 4 Sensoren
Welche denn? Gibt es dazu eine Typbezeichnung oder ein Datenblatt?

: Bearbeitet durch Moderator
von Peter D. (peda)


Lesenswert?

Sind die Pins floatend, dann kann alles mögliche passieren. Die Pins 
müssen immer mit gültigem Pegel gespeist werden. Sind da Kontakte oder 
Open-Drain Quellen dran, muß ein Pullup/-down angeschlossen oder enabled 
werden.

von Peter D. (peda)


Lesenswert?

Achim M. schrieb:
> 1. Die Interruptquelle prellt. Da kannst du nur Hardware-Filter dagegen
> einsetzen.

Prust. Hätte fast den Kaffee verschüttet.

von Peter D. (peda)


Lesenswert?

Micha J. schrieb:
> Mein Ansatz war, dass ich zuerst die ersten vier Bits vom GPIOB-Port in
> einer Variablen speichere und maskiere dann das Bit vom gesuchten Pin.

Damit zählst Du alle Pins, die high sind.
Typisch will man aber nur die Flanke zählen. D.h. Du must Dir den alten 
Zustand in einer Variable merken und nur die 0->1 Wechsel zählen.

von Achim M. (minifloat)


Lesenswert?

Peter D. schrieb:
> Achim M. schrieb:
>
>> Die Interruptquelle prellt. Da kannst du nur Hardware-Filter dagegen
>> einsetzen.
>
> Prust. Hätte fast den Kaffee verschüttet.

Ja, wenn man es nicht mit deiner tollen Entprellroutine, weil nicht ohne 
Pin-interrupt lösen kann, ist das wohl so. Wie kommt der TO denn sonst 
auf ein "11-statt-4"?

Gegen die übliche Beratungsresistenz wegen IRQ-oder-Polling braucht man 
nicht mehr anzugehen. Kostet nur Zeit und Nerven und kommt jede Woche 
mindestens einmal.

Peter D. schrieb:
> Typisch will man aber nur die Flanke zählen.
Dazu fehlt erstmal die Info, welche Flanken der TO überhaupt zählen will 
und auch wie schnell es gehen muss.

mfg mf

von neuer PIC Freund (Gast)


Lesenswert?

Wenn EXTI_CR unangefasst bleibt, müsste der Interrupt auf "Falling edge 
and low level" stehen.

Dazu noch 6.2.2 aus RM0016:
1
When external level-triggered interrupts are latched, if the given level is still present at the end of the interrupt routine, the interrupt remains activated except if it has been inactivated in the routine.

Da könnte die ISR häufiger als erwünscht aufgerufen werden.

von Micha J. (micha_j)


Angehängte Dateien:

Lesenswert?

Achim M. schrieb:
> 1. Die Interruptquelle prellt. Da kannst du nur Hardware-Filter dagegen
> einsetzen.
Die Interruptquelle prellt nicht. Wenn ich eine volle Umdrehung fahre, 
dann wird die ISR auch 16 mal ausgeführt.

Lothar M. schrieb:
> Micha J. schrieb:
>> habe zur Positionsbestimmung 4 Sensoren
> Welche denn? Gibt es dazu eine Typbezeichnung oder ein Datenblatt?

Es handelt sich um den TLE4905
https://www.infineon.com/cms/en/product/sensor/magnetic-sensors/magnetic-position-sensors/hall-switches/tle4905l/


Peter D. schrieb:
> Sind die Pins floatend, dann kann alles mögliche passieren. Die Pins
> müssen immer mit gültigem Pegel gespeist werden. Sind da Kontakte oder
> Open-Drain Quellen dran, muß ein Pullup/-down angeschlossen oder enabled
> werden.

Die Hallsensoren werden als Input mit Pullup initialisiert, damit sie 
nicht floaten. Ein Interrupt wird bei einer negativen Flanke 
ausgewertet.
GPIO_Init(GPIOB, GPIO_PIN_0, GPIO_MODE_IN_PU_IT)
EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOB, EXTI_SENSITIVITY_FALL_ONLY);

Ich habe eine neue Abbildung hinzugefügt. Die Interrupts werden auch 
nicht niemals gleichzeitig getriggert. D.h. dass ich mir quasi nur das 
zu änderne Bit anschauen brauche.

Der Tipp von Peter D. hat mir geholfen, dass ich den alten Werte 
speichern muss und einen Vergleich mit den neuen Wert durchführe. Mit 
XOR kann ich das Bit sehen, welches gewechselt hat. Dann überprüfe, 
welches Bit sich geändert hat.
1
INTERRUPT_HANDLER(EXTI_PORTB_IRQHandler, 4)
2
{
3
  /* In order to detect unexpected events during development,
4
     it is recommended to set a breakpoint on the following instruction.
5
  */
6
  hall1 = (uint8_t)GPIOB->IDR& 0xF;
7
  
8
  switch(hall1^hall_alt) // 
9
  {
10
    case 0x1: h1_counter++; break; // Pin0
11
    case 0x2: h2_counter++; break; // Pin1
12
    case 0x4: h3_counter++; break; // Pin2
13
    case 0x8: h4_counter++; break; // Pin3
14
    default: break;
15
  }
16
  
17
  counter_IT++; // ISR Counter nur zu Testzwecken
18
  hall_alt = hall1;  // alter Wert wird gespeichert
19
}

Jetzt habe ich trotzdem ein eigenartiges Verhalten. Bei den ersten zwei 
Hallsensoren zählt er 4 fallende Flanken, aber bei h3_counter und 
h4_counter nur 2. Außerdem nach x-Versuchen (ca. 5-6 mal) zählt er 
völlig falsch und hat falsche Werte und dann die richtigen für h1_ und 
h2_counter.

Viele Grüße
Michael

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.