Forum: Mikrocontroller und Digitale Elektronik STM32 Input Capture triggert nicht


von Julian R. (julianr)


Lesenswert?

Ich versuche mittels STM32F103C8 ("Blue Pill" Board) und einem TSOP4836 
IR Empfänger einen RC6 Decoder zu basteln (ich weiß gibts fertige Libs 
dafür aber darum gehts nicht). Hierzu versuche ich den Timer1 im Input 
Capture mode zu verwenden. Ich verwende die HAL Low-Level Treiber, das 
meiste wurde mit CubeMX generiert.

Das Ausgangssignal ist an PA8 des STM32 angeschlossen.
Die Schaltung an sich funktioniert (ich sehe mit dem Oszi das 
demodulierte IR Signal), allerdings triggert der Input Capture Interrupt 
nicht. Mein Code sieht wie folgt aus (nur relevante Ausschnitte):
1
virtual void setup()
2
{
3
  LL_TIM_InitTypeDef TIM_InitStruct = { 0 };
4
  LL_GPIO_InitTypeDef GPIO_InitStruct = { 0 };
5
6
  /* Peripheral clock enable */
7
  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM1); 
8
  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA);
9
  
10
  /*TIM1 GPIO Configuration  PA8   ------> TIM1_CH1  */
11
  GPIO_InitStruct.Pin = LL_GPIO_PIN_8;
12
  GPIO_InitStruct.Mode = LL_GPIO_MODE_FLOATING; //genreated by CubeMX      
13
  //TEST via external GND signal
14
  //GPIO_InitStruct.Mode = LL_GPIO_MODE_INPUT;
15
  //GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
16
  LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
17
  
18
  /*Timer Capture */
19
  TIM_InitStruct.Prescaler = 5;
20
  TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
21
  TIM_InitStruct.Autoreload = 0xFFFF;
22
  TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
23
  TIM_InitStruct.RepetitionCounter = 0;
24
  LL_TIM_Init(TIM1, &TIM_InitStruct);
25
  LL_TIM_EnableARRPreload(TIM1);
26
  LL_TIM_SetClockSource(TIM1, LL_TIM_CLOCKSOURCE_INTERNAL);
27
  LL_TIM_SetTriggerOutput(TIM1, LL_TIM_TRGO_RESET);
28
  LL_TIM_DisableMasterSlaveMode(TIM1);
29
  LL_TIM_IC_SetActiveInput(TIM1, LL_TIM_CHANNEL_CH1, LL_TIM_ACTIVEINPUT_DIRECTTI);
30
  LL_TIM_IC_SetPrescaler(TIM1, LL_TIM_CHANNEL_CH1, LL_TIM_ICPSC_DIV1);
31
  LL_TIM_IC_SetFilter(TIM1, LL_TIM_CHANNEL_CH1, LL_TIM_IC_FILTER_FDIV1);
32
  LL_TIM_IC_SetPolarity(TIM1, LL_TIM_CHANNEL_CH1, LL_TIM_IC_POLARITY_FALLING);
33
}
34
35
virtual void start()
36
{
37
  NVIC_EnableIRQ(TIM1_CC_IRQn);
38
  NVIC_EnableIRQ(TIM1_UP_IRQn);
39
40
  LL_TIM_ClearFlag_UPDATE(TIM1);
41
  LL_TIM_EnableIT_UPDATE(TIM1);
42
  LL_TIM_ClearFlag_CC1(TIM1);
43
  LL_TIM_EnableIT_CC1(TIM1);
44
  
45
  LL_TIM_EnableCounter(TIM1);
46
}
47
48
extern "C" void TIM1_CC_IRQHandler()
49
{
50
  LL_TIM_ClearFlag_CC1(TIM1);
51
}
52
53
extern "C" void TIM1_UP_IRQHandler()
54
{
55
  LL_TIM_ClearFlag_UPDATE(TIM1);
56
}

Mittels Debugger sehe ich, dass der Timer läuft. Der 
TIM1_UP_IRQHandler() wird zyklisch aufgerufen. Wenn ich das Programm 
irgendwo anhalte sehe ich, dass das TIM1->CR Register hoch zählt und 
dann bei 0xFFFF resettet.

TIM1_CC_IRQHandler() wird nie aufgerufen. Ich habe zum Test auch mal den 
internen Pullup aktiviert und das Signal von Hand auf GND gelegt, 
gleiches Ergebnis. Wenn ich das CC1G Bit im TIM1->EGR Register mittels 
Debugger setzte, wird der Interrupt aufgerufen. Ich gehe also davon aus, 
dass zumindest die Interrupt-Konfiguration stimmt.
Jemand eine Idee was ich noch falsch mache?

von Julian R. (julianr)


Lesenswert?

So nachdem ich nun nochmal in die LL API Doku und das RM geschaut habe, 
konnte ich das Problem lösen (für alle die das hier via 
Google/Forensuche finden):
Der Kanal muss noch mit
1
LL_TIM_CC_EnableChannel(TIM1, LL_TIM_CHANNEL_CH1);
 aktiviert werden.
Außerdem muss der Input Pin laut RM als Floating Input konfiguriert 
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.