Forum: Mikrocontroller und Digitale Elektronik STM32F4 Timer PWM + Interrupt


von Florian K. (f-kae)


Lesenswert?

Hallo zusammen,
ich möchte gerne auf meinem STM32F407VGT am Pin PC7 einen akustischen 
Signalgeber per PWM ansteuern.
Grundsätzlich funktioniert das auch schon allerdings möchte ich per 
Interrupt nach mehrmaligem ausführen des Signals, den Timer wieder 
austellen.

Hier erst einmal der Code:
1
volatile uint8_t beeps = 0;
2
3
void BuzzerInit(void)
4
{
5
  GPIO_InitTypeDef GPIO_InitStructure;
6
  TIM_TimeBaseInitTypeDef TIM_TimeBase_InitStructure;
7
  TIM_OCInitTypeDef TIM_OC_InitStructure;
8
  NVIC_InitTypeDef NVIC_InitStructure;
9
10
  GPIO_InitStructure.GPIO_Pin = buzzerPin;
11
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
12
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
13
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
14
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
15
  GPIO_Init(buzzerPort, &GPIO_InitStructure);
16
  
17
  GPIO_PinAFConfig(buzzerPort, GPIO_PinSource7, GPIO_AF_TIM8);
18
  
19
  TIM_TimeBase_InitStructure.TIM_ClockDivision = 0;
20
  TIM_TimeBase_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
21
  TIM_TimeBase_InitStructure.TIM_Prescaler = 41999; // 168.000.000 / 42.000 = 4000 (1s = 4000 Ticks)
22
  TIM_TimeBase_InitStructure.TIM_Period = 1599; // 1600 / 4000 = 0,4 (Überlauf nach 0,4 Sekunden)
23
  TIM_TimeBaseInit(TIM8, &TIM_TimeBase_InitStructure);
24
  
25
  
26
  TIM_OC_InitStructure.TIM_OCMode = TIM_OCMode_PWM2;
27
  TIM_OC_InitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
28
  TIM_OC_InitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set;
29
  TIM_OC_InitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
30
  TIM_OC_InitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
31
  TIM_OC_InitStructure.TIM_OutputState = TIM_OutputState_Enable;
32
  TIM_OC_InitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
33
  TIM_OC_InitStructure.TIM_Pulse = 1199;  // Buzzer 0,1s an 0,3s aus
34
  TIM_OC2Init(TIM8, &TIM_OC_InitStructure); //Channel 2
35
  
36
  TIM_OC2PreloadConfig(TIM8, TIM_OCPreload_Enable);
37
  TIM_ARRPreloadConfig(TIM8, ENABLE);
38
  
39
  /* Main Output Enable */
40
  TIM_CtrlPWMOutputs(TIM8, ENABLE);
41
42
  /* Enable Timer-Update */
43
  TIM_ITConfig(TIM8, TIM_IT_Update, ENABLE); //DIESE ZEILE ERZEUGT MEIN PROBLEM!!!!!
44
45
46
  /* TIM8 Update Interrupt */
47
  NVIC_InitStructure.NVIC_IRQChannel = TIM8_UP_TIM13_IRQn;
48
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
49
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0E;
50
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0E;
51
  NVIC_Init(&NVIC_InitStructure);
52
  
53
}
54
55
void BuzzerBeep(uint8_t beeptimes)
56
{
57
  beeps = beeptimes;
58
    
59
  /* TIM8 counter enable */
60
  TIM_Cmd(TIM8, ENABLE);
61
}
62
63
void TIM8_UP_TIM13_Handler(void)
64
{
65
  //TIM_ClearFlag(TIM8, TIM_FLAG_Update);
66
  //TIM_ClearITPendingBit(TIM8, TIM_IT_Update);
67
  LedYellowOn();
68
  
69
  if (beeps > 1)
70
  {
71
     beeps--;
72
  }
73
  else
74
  {
75
     beeps = 0;
76
     /* TIM8 counter disable */
77
     TIM_Cmd(TIM8, DISABLE);
78
  }
79
}

Sobald ich die Zeile zur Aktivierung des Interrupt-Updates einfüge, 
bleibt das Programm hängen... Ich verstehe echt nicht was hier das 
Problem ist.

Den Handler habe ich noch zu keinem Zeitpunkt erreicht!!!


Timer8 und GPIOC werden schon vorher mit Clock versorgt.

von Florian K. (f-kae)


Lesenswert?

Kann mir hier niemand weiter helfen?

von asdfg (Gast)


Lesenswert?

Deinen TIM8_UP_TIM13_Handler in der Vektortabelle
an der richtigen Stelle eingetragen?

von Christian (Gast)


Lesenswert?

Hast du mal einen anderen IRQ Channel ausprobiert? Zb.

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;

und dann

void TIM8_IRQHandler(void){
  TIM_ClearITPendingBit(TIM8, TIM_IT_Update);
  ...
}

von Christian (Gast)


Lesenswert?

Achso ich sehe jetzt erst dass dein Problem wo anders auftaucht. Vergiss 
es ;)

von Christian (Gast)


Lesenswert?

Warum ist das hier auskommentier?

[c]
  //TIM_ClearFlag(TIM8, TIM_FLAG_Update);
  //TIM_ClearITPendingBit(TIM8, TIM_IT_Update);
[\c]

So wie ich es in erinnerung habe, bleibt er in dem Interrupt hängen, 
wenn man diese Befehle nicht ausführt. Vielleicht springst du ja 
einmalig in den Interrupt-Handler und bleibst da dann hängen?!

von dummy (Gast)


Lesenswert?

>Vielleicht springst du ja
>einmalig in den Interrupt-Handler und bleibst da dann hängen?!

Nicht einmalig, sondern immer wieder bis das Flag gelöscht wird.

von Christian (Gast)


Lesenswert?

dummy schrieb:
>>Vielleicht springst du ja
>>einmalig in den Interrupt-Handler und bleibst da dann hängen?!
>
> Nicht einmalig, sondern immer wieder bis das Flag gelöscht wird.

Achso nagut, dann wars so rum ;-)

von Mike R. (thesealion)


Lesenswert?

Florian K. schrieb:
>
1
> NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0E;
2
> NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0E;
3
>

Das funktioniert so auch nicht. Das NVIC Register hat insgesamt nur 4 
Bit für die Prioritäten.

Du kannst mit
1
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
 einstellen, wie sich die 4 Bit aufteilen. Aber 2 mal 15 Werte hast du 
nicht zur Verfügung.

Allerdings sollte das nicht zu einem kompletten "Aufhängen" führen.

Mike

von Florian K. (f-kae)


Lesenswert?

Hi,
nun kamen ja doch noch ein paar Antworten, schön :)


asdfg schrieb:
> Deinen TIM8_UP_TIM13_Handler in der Vektortabelle
> an der richtigen Stelle eingetragen?

Ich habe den Handler in der Datei "stm32f4xx_it.c" platziert und in der 
entsprechenenden Header-Datei bekannt gemacht.

Christian schrieb:
> Warum ist das hier auskommentier?
>
>
1
>   //TIM_ClearFlag(TIM8, TIM_FLAG_Update);
2
>   //TIM_ClearITPendingBit(TIM8, TIM_IT_Update);
3
>
>
> So wie ich es in erinnerung habe, bleibt er in dem Interrupt hängen,
> wenn man diese Befehle nicht ausführt. Vielleicht springst du ja
> einmalig in den Interrupt-Handler und bleibst da dann hängen?!

Ich habe Testweise, Teile des Codes auskommentiert. Allerdings sollte, 
wenn der Handler überhaupt erreicht wird die gelbe LED angehen 
(LedYellowOn()) aber das tut sie nicht, daher gehe ich davon aus, dass 
der Handler garnicht erreicht wird und der Fehler durch die konkrete 
Zeile oder in Kombination mit einer anderen entsteht.

Mike S. schrieb:
>> NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0E;
>> NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0E;
>>
> Das funktioniert so auch nicht. Das NVIC Register hat insgesamt nur 4
> Bit für die Prioritäten.
>
> Du kannst mitvoid NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
>  einstellen, wie sich die 4 Bit aufteilen. Aber 2 mal 15 Werte hast du
> nicht zur Verfügung.

In der SP-Library steht dazu:
1
uint8_t NVIC_InitTypeDef::NVIC_IRQChannelPreemptionPriority 
2
3
Specifies the pre-emption priority for the IRQ channel specified in NVIC_IRQChannel. This parameter can be a value between 0 and 15 as described in the table MISC_NVIC_Priority_Table A lower priority value indicates a higher priority
und
1
uint8_t NVIC_InitTypeDef::NVIC_IRQChannelSubPriority 
2
3
Specifies the subpriority level for the IRQ channel specified in NVIC_IRQChannel. This parameter can be a value between 0 and 15 as described in the table MISC_NVIC_Priority_Table A lower priority value indicates a higher priority

Ich bin immer nun immer noch nicht weiter mit dem Problem...

von Uwe B. (derexponent)


Lesenswert?

bist du dir mit dem Namen vom ISR-Handler sicher !?!

normalerweise lautet der :

"TIM8_UP_TIM13_IRQHandler"

von Florian K. (f-kae)


Lesenswert?

Uwe B. schrieb:
> bist du dir mit dem Namen vom ISR-Handler sicher !?!
>
> normalerweise lautet der :
>
> "TIM8_UP_TIM13_IRQHandler"

Ohhhh, du hast recht!

Vielen, vielen Dank schon einmal!
Ich werde es heute Abend testen und dann berichten :)

von Florian K. (f-kae)


Lesenswert?

OK,
es lag an der falschen Bezeichnung des Handlers!

Vielen Dank an Uwe B.! :D

Gruß,
Florian

von Christian (Gast)


Lesenswert?

Hat der Compiler nicht gemeckert, dass er den IRQ-Handler nicht kennt??

von Florian K. (f-kae)


Lesenswert?

Christian schrieb:
> Hat der Compiler nicht gemeckert, dass er den IRQ-Handler nicht kennt??

Naja ich hab halt meine eigene Funktion definiert, ist ja nichts 
verkehrt dran, nur der Interrupt konnte halt nicht dort reinspringen.

Die "Freischaltung" des Handlers war ja richtig:
  NVIC_InitStructure.NVIC_IRQChannel = TIM8_UP_TIM13_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0E;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0E;
  NVIC_Init(&NVIC_InitStructure);

von Christian (Gast)


Lesenswert?

Ah okay, verstehe ;)

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.