STM32F2/4 Rotary Encoder: Wie "nur ein Interrupt pro Schritt"?

OP Persönliche Seite #6705259
Lesenswert?

Moin,

jemand Erfahrung mit dem TIMER Rotary Encoder der STM32F2/F4? Mich 
wundert, dass
- der Counter immer 2 oder 4 weiterzählt, je nach SMS=1,2 oder 3
- viel zu viele IRQs generiert werden, mind. 1 pro Counter, aber auch 
"zufällig" sehr viel mehr als der Stand vom CNT Register

Habe das ganze mit der HAL gelöst, in der Hoffnung, es portierbar zu 
halten. Die structs werden im Konstruktor auf null gesetzt.
Sinnhaftigkeit von C++ auf µC? Ganz einfach: Ist mein Testprojekt, um 
genau das herauszufinden :-)
1
bool CRotary::Rotary_Initialize()
2
{
3
  __TIM3_CLK_ENABLE();
4
  __GPIOB_CLK_ENABLE();
5
  
6
  GPIO_InitStruct.Pin = GPIO_PIN_4 | GPIO_PIN_5;
7
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
8
  GPIO_InitStruct.Pull = GPIO_PULLUP;
9
  GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
10
  GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
11
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
12

13
  timer.Instance = TIM3;
14
  timer.Init.Period = 0xFFFF;
15
  timer.Init.CounterMode = TIM_COUNTERMODE_UP;
16
  timer.Init.Prescaler = 0;
17
  timer.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
18

19
  encoder.EncoderMode = TIM_ENCODERMODE_TI12;
20
  encoder.IC1Filter = 0x0F;
21
  encoder.IC1Polarity = TIM_INPUTCHANNELPOLARITY_RISING;
22
  encoder.IC1Prescaler = TIM_ICPSC_DIV1;
23
  encoder.IC1Selection = TIM_ICSELECTION_DIRECTTI;
24
  encoder.IC2Filter = 0x0F;
25
  encoder.IC2Polarity = TIM_INPUTCHANNELPOLARITY_FALLING;
26
  encoder.IC2Prescaler = TIM_ICPSC_DIV1;
27
  encoder.IC2Selection = TIM_ICSELECTION_DIRECTTI;
28

29
  if (HAL_TIM_Encoder_Init(&timer, &encoder) != HAL_OK)
30
    return false;
31

32
  HAL_NVIC_SetPriority(TIM3_IRQn, 0, 1);
33
  HAL_NVIC_EnableIRQ(TIM3_IRQn);
34

35
  if(HAL_TIM_Encoder_Start_IT(&timer, TIM_CHANNEL_1) != HAL_OK)
36
    return false;
37
 
38
  return true;
39
}
#6705413
Lesenswert?

Random .. schrieb:
> der Counter immer 2 oder 4 weiterzählt, je nach SMS=1,2 oder 3

Das wäre merkwürdig. Normalerweise kenne ich das SMS Register so, dass 
es angibt auf was für Flanken es reagieren soll. Also einfach, zweifach 
oder vierfach Flankenauswertung.
Aber eine Flanke bleibt ein Count!

Random .. schrieb:
> viel zu viele IRQs generiert werden

Erste Mal, wofür brauchst du die Interrupts überhaupt? Oft tut es ein 
Polling des Count Registers z.B. alle 1 bis 100ms.

Random .. schrieb:
> mind. 1 pro Counter, aber auch "zufällig" sehr viel mehr als der Stand
> vom CNT Register

Da liegt wahrscheinlich dein Problem. Hast du dir Mal die Signale 
angesehen mit einem Oszi oder Logic Analyzer? Wahrscheinlich prellt da 
irgendwas oder was anderes stimmt mit deinen Signalen nicht.

Wie sieht der Aufbau aus?
Was für einen Encoder nimmst du?
Und wie ist er angeschlossen?
#6705451
Lesenswert?

Hi,

 ich hatte das mal mit dem F103 gemacht; der Timer im F4 ist an der 
Stelle aber m.W. gleich:

https://github.com/PhischDotOrg/stm32f1-blinkenbike/blob/master/RotaryEncoder.hpp

Verwendet hatte ich diesen billigen KY-040 Rotary Encoder.

Ergänzend zu den Kommentaren im Source Code: Die Entprellung wird in dem 
Setup letztlich von der Timer Hardware gemacht. Hier wird der Input 
Filter / Edge Detector ausgenutzt. In meinem Projekt wird der Rotary 
Encoder von einem Menschen bedient; dreht also nicht soo schnell. Ich 
hatte den Filter deshalb sehr "langsam" / "tiefpassig" (wie sagt man 
denn da richtig?) eingestellt. Siehe Zeile #111.

Wenn ich mich recht erinnere, dann hab' ich die Sequenz mehr oder 
weniger aus dem Datenblatt abgeschrieben.

Vielleicht hilft's ja.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren