mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik STM32F407VG Externe Interrupts triggern nicht unabhängig


Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich habe ein Problem mit den externen Interrupts auf meinem STM32F407VG 
Discovery Board. Für meine Anwendung benötige ich Acht externe 
Interrupts, die ich zu je vier auf die Interruptvektoren EXTI15_10_IRQn 
und EXT9_5_IRQn aufgeteilt habe:

EXTI15_10_IRQn (PB11, PB12, PB13, PB14)
EXTI9_5_IRQn (PD6, PD7, PD8, PD9)

Die Interrupts werden getriggert, aber es werden mehr als die 
gewünschten ISRs ausgeführt. Wird der mit PD6 verbundene Interrupt 
getriggert, wird der Code für diesen Fall ausgeführt und danach der Code 
für ein Trigger-Event auf PD7. Es scheint als ob das Pending Bit nicht 
zurückgesetzt wird, obwohl die entsprechende Funktion aufgerufen wird. 
Es werden mehrere Eine Logik konnte ich hinter diesem Verhalten nicht 
ausmachen, aber es ist wiederholbar. Sporadisch kommt es sogar zu einer 
Auführung von Interruptroutinen im anderen Interruptvektor.

Als IDE nutze ich EmBitz und die SPL von ST. Anfänglich wurden die ISRs 
ohne Signal ausgelöst, aber das konnte ich schon beheben, im Internet 
habe ich schon ausführlich gesucht, konnte das verbleibende Problem 
bisher aber nicht lösen, jetzt hoffe ich wirklich, dass Ihr mir helfen 
könnt!

Die relevanten Teile des Source Codes sind angehangen.

Viele Grüße,
Matthias


Code:
void ConfigReferenceInterrupts( void )
{
    /** Initialisierung */
    EXTI_InitTypeDef EXTI_Reference_PD6_InitStruct;
    EXTI_InitTypeDef EXTI_Reference_PD7_InitStruct;
    EXTI_InitTypeDef EXTI_Reference_PD8_InitStruct;
    EXTI_InitTypeDef EXTI_Reference_PD9_InitStruct;

    NVIC_InitTypeDef NVIC_Reference_InitStruct;


    RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOD, ENABLE);

    GPIO_Initializer.GPIO_Mode = GPIO_Mode_IN;
    GPIO_Initializer.GPIO_OType = GPIO_OType_PP; //PP = push-pull mode
    GPIO_Initializer.GPIO_Pin = REFERENCEPIN_LEFT | REFERENCEPIN_RIGHT | REFERENCEPIN_BOTTOM | REFERENCEPIN_TOP;
    GPIO_Initializer.GPIO_PuPd = GPIO_PuPd_DOWN;
    GPIO_Initializer.GPIO_Speed = GPIO_Speed_2MHz;

    GPIO_Init(REFERENCE_PORT, &GPIO_Initializer);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

    /** PD6 */
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOD, EXTI_PinSource6 );
    EXTI_Reference_PD6_InitStruct.EXTI_Line = EXTI_Line6;
    EXTI_Reference_PD6_InitStruct.EXTI_LineCmd = ENABLE;
    EXTI_Reference_PD6_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_Reference_PD6_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
    EXTI_Init(&EXTI_Reference_PD6_InitStruct);

    /** PD7 */
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOD, EXTI_PinSource7 );
    EXTI_Reference_PD7_InitStruct.EXTI_Line = EXTI_Line7;
    EXTI_Reference_PD7_InitStruct.EXTI_LineCmd = ENABLE;
    EXTI_Reference_PD7_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_Reference_PD7_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
    EXTI_Init(&EXTI_Reference_PD7_InitStruct);

    /** PD8 */
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOD, EXTI_PinSource8 );
    EXTI_Reference_PD8_InitStruct.EXTI_Line = EXTI_Line8;
    EXTI_Reference_PD8_InitStruct.EXTI_LineCmd = ENABLE;
    EXTI_Reference_PD8_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_Reference_PD8_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
    EXTI_Init(&EXTI_Reference_PD8_InitStruct);

    /** PD9 */
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOD, EXTI_PinSource9 );
    EXTI_Reference_PD9_InitStruct.EXTI_Line = EXTI_Line9;
    EXTI_Reference_PD9_InitStruct.EXTI_LineCmd = ENABLE;
    EXTI_Reference_PD9_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_Reference_PD9_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
    EXTI_Init(&EXTI_Reference_PD9_InitStruct);


    NVIC_Reference_InitStruct.NVIC_IRQChannel = EXTI9_5_IRQn;
    NVIC_Reference_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x00;
    NVIC_Reference_InitStruct.NVIC_IRQChannelSubPriority = 0x01;
    NVIC_Reference_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init( &NVIC_Reference_InitStruct );
}


/** Die übrigen vier Interrupts sind vollkommen analog zu den dargestellten Interrupts auf PORTD konfiguriert, deshalb habe ich sie hier ausgelassen um den Code übersichtlicher zu halten, auf Wunsch kann diese Funktion aber auch gerne nachgereicht werden */


/** Interrupt-Handler */
void EXTI9_5_IRQHandler( void )
{

    if (EXTI_GetITStatus(EXTI_Line6) != RESET) //Sekundaer rechts -> PD6
    {
        Reference_right_reached = true;

        EXTI_ClearITPendingBit(EXTI_Line6);
        NVIC_ClearPendingIRQ(EXTI9_5_IRQn);
    }

    if (EXTI_GetITStatus(EXTI_Line7) != RESET) //Sekundaer links -> PD7
    {
        Reference_left_reached = true;

        EXTI_ClearITPendingBit(EXTI_Line7);
        NVIC_ClearPendingIRQ(EXTI9_5_IRQn);
    }

    if (EXTI_GetITStatus(EXTI_Line8) != RESET) //Z Top -> PD8
    {
        Reference_top_reached = true;

        EXTI_ClearITPendingBit(EXTI_Line8);
        NVIC_ClearPendingIRQ(EXTI9_5_IRQn);
    }

    if (EXTI_GetITStatus(EXTI_Line9) != RESET) //Z Bottom -> PD9
    {
        Reference_bottom_reached = true;

        EXTI_ClearITPendingBit(EXTI_Line9);
        NVIC_ClearPendingIRQ(EXTI9_5_IRQn);
    }

    EXTI_ClearITPendingBit(EXTI_Line6);
    EXTI_ClearITPendingBit(EXTI_Line7);
    EXTI_ClearITPendingBit(EXTI_Line8);
    EXTI_ClearITPendingBit(EXTI_Line9);
    NVIC_ClearPendingIRQ(EXTI9_5_IRQn);
}


void EXTI15_10_IRQHandler( void )
{
    if (EXTI_GetITStatus(EXTI_Line11) != RESET ) //->Secondary Encoder A  // !=RESET
    {
        if( GPIO_ReadInputDataBit( SECONDARY_ROTARY_PORT, SECONDARY_ROTARY_B ) == 0x00 )
        {
            secondary_counter++;
        } else {
            secondary_counter--;
        }

        EXTI_ClearITPendingBit(EXTI_Line11);
        NVIC_ClearPendingIRQ(EXTI15_10_IRQn);
    }

    if (EXTI_GetITStatus(EXTI_Line12) != RESET ) //->Secondary Encoder B
    {
        if( GPIO_ReadInputDataBit( SECONDARY_ROTARY_PORT, SECONDARY_ROTARY_A ) == 0x00 )
        {
            secondary_counter--;
        } else {
            secondary_counter++;
        }

        EXTI_ClearITPendingBit(EXTI_Line12);
        NVIC_ClearPendingIRQ(EXTI15_10_IRQn);
    }


    if (EXTI_GetITStatus(EXTI_Line13) != RESET ) //->Primary Encoder A
    {
        if( GPIO_ReadInputDataBit( PRIMARY_ROTARY_PORT, PRIMARY_ROTARY_B ) == 0x00 )
        {
            primary_counter++;
        } else {
            primary_counter--;
        }

        EXTI_ClearITPendingBit(EXTI_Line13);
        NVIC_ClearPendingIRQ(EXTI15_10_IRQn);
    }

    if (EXTI_GetITStatus(EXTI_Line14) != RESET ) //->Primary Encoder B
    {
        if( GPIO_ReadInputDataBit( PRIMARY_ROTARY_PORT, PRIMARY_ROTARY_A ) == 0x00 )
        {
            primary_counter--;
        } else {
            primary_counter++;
        }

        EXTI_ClearITPendingBit(EXTI_Line14);
        NVIC_ClearPendingIRQ(EXTI15_10_IRQn);
    }

        EXTI_ClearITPendingBit(EXTI_Line11);
        EXTI_ClearITPendingBit(EXTI_Line12);
        EXTI_ClearITPendingBit(EXTI_Line13);
        EXTI_ClearITPendingBit(EXTI_Line14);
}

Autor: STM Apprentice (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Musst du vielleicht mal deine Schaltung zeigen, sowohl
Schaltplan als auch Aufbau.

Wenn nicht, dann wird's halt ein Stochern im Nebel.

(Beim Motorrad: am Öl kann's nicht gelegen haben, war ja keins drin)

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Das Entwicklungsboard ist momentan noch nicht an seine Schaltung 
angeschlossen. Die entsprechenden Kabel sind lediglich mit Jumper Wires 
auf ein Steckbrett geführt, wo ich manuell einen 5V Pegel auf die Pins 
legen kann um den Interrupt zu triggern. Die Konfiguration des User 
Buttons über einen externen Interrupt funktioniert mit diesem 
Beispielcode problemlos, ich vermute deshalb, dass es irgendein Problem 
mit den Flags in den Interruptvektoren für Pins 5-9 und Pins 10-15 ist.
void EXTI_Initialize(void)
{
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);

    EXTI_InitTypeDef EXTI_InitStruct;
    EXTI_InitStruct.EXTI_Line = EXTI_Line0;
    EXTI_InitStruct.EXTI_LineCmd = ENABLE;
    EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
    EXTI_Init(&EXTI_InitStruct);

    NVIC_InitTypeDef NVIC_InitStruct;
    NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x00;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x00;
    NVIC_Init(&NVIC_InitStruct);
}

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matthias schrieb:
> wo ich manuell einen 5V Pegel auf die Pins legen kann um den Interrupt
> zu triggern.

Wie legst Du da die 5V an? Kurz Litze dranhalten? Dann kannst Du schon 
mehr als einen Interrupt erzeugen. So eine ruhige Hand hat keiner. Sind 
die Pins alle 5V-fest? Warum nutzt Du nicht die invertierte Logik und 
legst GND an?

Immerhin nutzt Du die internen Pulldowns, sonst hätte ich auf 
Übersprechen auf die benachbarten offenen Inputs getippt.

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja im Moment mache ich das von Hand, werde heute mal versuchen ein paar 
Schalter mit RC-Debouncing dranzulegen und prüfen, ob sich was ändert. 
Was mich verwundert ist aber nicht, dass mehrere Interrupts getriggert 
werden, sondern das ein Interrupt an einem Pin offensichtlich die Flags 
für mehrere Pins setzt.

Konkret führt beispielsweise ein High-Pegel auf PB12 dazu, dass in der 
ISR auch die if-Bedingungen für PB13 und PB14 erfüllt werden.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.