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


von Matthias (Gast)


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:
1
void ConfigReferenceInterrupts( void )
2
{
3
    /** Initialisierung */
4
    EXTI_InitTypeDef EXTI_Reference_PD6_InitStruct;
5
    EXTI_InitTypeDef EXTI_Reference_PD7_InitStruct;
6
    EXTI_InitTypeDef EXTI_Reference_PD8_InitStruct;
7
    EXTI_InitTypeDef EXTI_Reference_PD9_InitStruct;
8
9
    NVIC_InitTypeDef NVIC_Reference_InitStruct;
10
11
12
    RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOD, ENABLE);
13
14
    GPIO_Initializer.GPIO_Mode = GPIO_Mode_IN;
15
    GPIO_Initializer.GPIO_OType = GPIO_OType_PP; //PP = push-pull mode
16
    GPIO_Initializer.GPIO_Pin = REFERENCEPIN_LEFT | REFERENCEPIN_RIGHT | REFERENCEPIN_BOTTOM | REFERENCEPIN_TOP;
17
    GPIO_Initializer.GPIO_PuPd = GPIO_PuPd_DOWN;
18
    GPIO_Initializer.GPIO_Speed = GPIO_Speed_2MHz;
19
20
    GPIO_Init(REFERENCE_PORT, &GPIO_Initializer);
21
22
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
23
24
    /** PD6 */
25
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOD, EXTI_PinSource6 );
26
    EXTI_Reference_PD6_InitStruct.EXTI_Line = EXTI_Line6;
27
    EXTI_Reference_PD6_InitStruct.EXTI_LineCmd = ENABLE;
28
    EXTI_Reference_PD6_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
29
    EXTI_Reference_PD6_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
30
    EXTI_Init(&EXTI_Reference_PD6_InitStruct);
31
32
    /** PD7 */
33
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOD, EXTI_PinSource7 );
34
    EXTI_Reference_PD7_InitStruct.EXTI_Line = EXTI_Line7;
35
    EXTI_Reference_PD7_InitStruct.EXTI_LineCmd = ENABLE;
36
    EXTI_Reference_PD7_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
37
    EXTI_Reference_PD7_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
38
    EXTI_Init(&EXTI_Reference_PD7_InitStruct);
39
40
    /** PD8 */
41
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOD, EXTI_PinSource8 );
42
    EXTI_Reference_PD8_InitStruct.EXTI_Line = EXTI_Line8;
43
    EXTI_Reference_PD8_InitStruct.EXTI_LineCmd = ENABLE;
44
    EXTI_Reference_PD8_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
45
    EXTI_Reference_PD8_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
46
    EXTI_Init(&EXTI_Reference_PD8_InitStruct);
47
48
    /** PD9 */
49
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOD, EXTI_PinSource9 );
50
    EXTI_Reference_PD9_InitStruct.EXTI_Line = EXTI_Line9;
51
    EXTI_Reference_PD9_InitStruct.EXTI_LineCmd = ENABLE;
52
    EXTI_Reference_PD9_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
53
    EXTI_Reference_PD9_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
54
    EXTI_Init(&EXTI_Reference_PD9_InitStruct);
55
56
57
    NVIC_Reference_InitStruct.NVIC_IRQChannel = EXTI9_5_IRQn;
58
    NVIC_Reference_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x00;
59
    NVIC_Reference_InitStruct.NVIC_IRQChannelSubPriority = 0x01;
60
    NVIC_Reference_InitStruct.NVIC_IRQChannelCmd = ENABLE;
61
    NVIC_Init( &NVIC_Reference_InitStruct );
62
}
63
64
65
/** 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 */
66
67
68
/** Interrupt-Handler */
69
void EXTI9_5_IRQHandler( void )
70
{
71
72
    if (EXTI_GetITStatus(EXTI_Line6) != RESET) //Sekundaer rechts -> PD6
73
    {
74
        Reference_right_reached = true;
75
76
        EXTI_ClearITPendingBit(EXTI_Line6);
77
        NVIC_ClearPendingIRQ(EXTI9_5_IRQn);
78
    }
79
80
    if (EXTI_GetITStatus(EXTI_Line7) != RESET) //Sekundaer links -> PD7
81
    {
82
        Reference_left_reached = true;
83
84
        EXTI_ClearITPendingBit(EXTI_Line7);
85
        NVIC_ClearPendingIRQ(EXTI9_5_IRQn);
86
    }
87
88
    if (EXTI_GetITStatus(EXTI_Line8) != RESET) //Z Top -> PD8
89
    {
90
        Reference_top_reached = true;
91
92
        EXTI_ClearITPendingBit(EXTI_Line8);
93
        NVIC_ClearPendingIRQ(EXTI9_5_IRQn);
94
    }
95
96
    if (EXTI_GetITStatus(EXTI_Line9) != RESET) //Z Bottom -> PD9
97
    {
98
        Reference_bottom_reached = true;
99
100
        EXTI_ClearITPendingBit(EXTI_Line9);
101
        NVIC_ClearPendingIRQ(EXTI9_5_IRQn);
102
    }
103
104
    EXTI_ClearITPendingBit(EXTI_Line6);
105
    EXTI_ClearITPendingBit(EXTI_Line7);
106
    EXTI_ClearITPendingBit(EXTI_Line8);
107
    EXTI_ClearITPendingBit(EXTI_Line9);
108
    NVIC_ClearPendingIRQ(EXTI9_5_IRQn);
109
}
110
111
112
void EXTI15_10_IRQHandler( void )
113
{
114
    if (EXTI_GetITStatus(EXTI_Line11) != RESET ) //->Secondary Encoder A  // !=RESET
115
    {
116
        if( GPIO_ReadInputDataBit( SECONDARY_ROTARY_PORT, SECONDARY_ROTARY_B ) == 0x00 )
117
        {
118
            secondary_counter++;
119
        } else {
120
            secondary_counter--;
121
        }
122
123
        EXTI_ClearITPendingBit(EXTI_Line11);
124
        NVIC_ClearPendingIRQ(EXTI15_10_IRQn);
125
    }
126
127
    if (EXTI_GetITStatus(EXTI_Line12) != RESET ) //->Secondary Encoder B
128
    {
129
        if( GPIO_ReadInputDataBit( SECONDARY_ROTARY_PORT, SECONDARY_ROTARY_A ) == 0x00 )
130
        {
131
            secondary_counter--;
132
        } else {
133
            secondary_counter++;
134
        }
135
136
        EXTI_ClearITPendingBit(EXTI_Line12);
137
        NVIC_ClearPendingIRQ(EXTI15_10_IRQn);
138
    }
139
140
141
    if (EXTI_GetITStatus(EXTI_Line13) != RESET ) //->Primary Encoder A
142
    {
143
        if( GPIO_ReadInputDataBit( PRIMARY_ROTARY_PORT, PRIMARY_ROTARY_B ) == 0x00 )
144
        {
145
            primary_counter++;
146
        } else {
147
            primary_counter--;
148
        }
149
150
        EXTI_ClearITPendingBit(EXTI_Line13);
151
        NVIC_ClearPendingIRQ(EXTI15_10_IRQn);
152
    }
153
154
    if (EXTI_GetITStatus(EXTI_Line14) != RESET ) //->Primary Encoder B
155
    {
156
        if( GPIO_ReadInputDataBit( PRIMARY_ROTARY_PORT, PRIMARY_ROTARY_A ) == 0x00 )
157
        {
158
            primary_counter--;
159
        } else {
160
            primary_counter++;
161
        }
162
163
        EXTI_ClearITPendingBit(EXTI_Line14);
164
        NVIC_ClearPendingIRQ(EXTI15_10_IRQn);
165
    }
166
167
        EXTI_ClearITPendingBit(EXTI_Line11);
168
        EXTI_ClearITPendingBit(EXTI_Line12);
169
        EXTI_ClearITPendingBit(EXTI_Line13);
170
        EXTI_ClearITPendingBit(EXTI_Line14);
171
}

von STM Apprentice (Gast)


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)

von Matthias (Gast)


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.
1
void EXTI_Initialize(void)
2
{
3
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
4
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
5
6
    GPIO_InitTypeDef GPIO_InitStruct;
7
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
8
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
9
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
10
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
11
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
12
    GPIO_Init(GPIOA, &GPIO_InitStruct);
13
14
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
15
16
    EXTI_InitTypeDef EXTI_InitStruct;
17
    EXTI_InitStruct.EXTI_Line = EXTI_Line0;
18
    EXTI_InitStruct.EXTI_LineCmd = ENABLE;
19
    EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
20
    EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
21
    EXTI_Init(&EXTI_InitStruct);
22
23
    NVIC_InitTypeDef NVIC_InitStruct;
24
    NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;
25
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
26
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x00;
27
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x00;
28
    NVIC_Init(&NVIC_InitStruct);
29
}

von Frank M. (ukw) (Moderator) Benutzerseite


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.

von Matthias (Gast)


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.

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.