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
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
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.
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.
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
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.
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
case0x1:h1_counter++;break;// Pin0
11
case0x2:h2_counter++;break;// Pin1
12
case0x4:h3_counter++;break;// Pin2
13
case0x8: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