Forum: Mikrocontroller und Digitale Elektronik STM32: Timer reseten


von Thomas B. (escamoteur)


Lesenswert?

Hi,

ich habe folgendes Problem:

Per EXTI empfange ich von einem Client Daten. Wenn dieser keine mehr 
hat, hält der einfach seine Clock an.

Ich hab mir nun gedacht, nimm nen Timer, der bei jedem ankommenden 
Signal auf 0 zurückgesetzt wird, so dass der Timer IRQ nur dann 
ausgelöst wird, wenn der Abstant zwischen zwei Signalen größer ist als 
das Timerinterval.

So weit so schön, aber obwohl ich bei jeder ankommenden Flanke

  TIM_SetCounter(TIM2, 0);

mache, schert sich der Timer keinen Deut drum und löst stur in seinem 
Interval den Interrupt aus.

Oder muss man den Timer auf eine andere Art zurücksetzen?

Gruß
Thomas

von Hannes S. (Gast)


Lesenswert?

Also eigentlich sollte das mit TIM_SetCounter() schon funktionieren. Ich 
bin mir aber nicht sicher, ob das beschreiben des CNT registers nicht 
auch einen Update IRQ auslöst...

Die "richtige" Art, den Counter rückzusetzen wäre über das UG Bit im EGR 
register, denn dabei wird auch der Prescaler zurückgesetzt. Allerdings 
hat letzteres nur ernsthafte Auswirkungen, wenn Du mit einem großen 
Prescaler und kleinem Reload Wert arbeitest.

Aber Achtung: Beim Rücksetzen über UG wird definitiv ein Update IRQ 
ausgelöst. Also am besten vorher abschalten.

von Thomas B. (escamoteur)


Lesenswert?

Hmm, wenn es so wäre, würde bei jeder Clock Flanke ein TIMER IRQ 
auslösen, dies ist jedoch nicht der Fall. Die Timer IRQs kommen 
regelmäßig entsprechend der Einstellung des Timers.

von Lutz (Gast)


Lesenswert?

Es sollte eigentlich so funktionieren, da man das Counterregister auch 
bei laufendem Timer lesen und schreiben kann.
Ohne Code wird das dann nix, da der Fehler vermutlich dort liegt.

von Thomas B. (escamoteur)


Angehängte Dateien:

Lesenswert?

Ok, dann kommt hier der code

Initiallisierung von Timer und ETXI IRQs
1
// Timer to detect if transponder was removed    
2
#define TIMER_TAKT 10000                                            /* Timer wird mit 10kHz getaktet */
3
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
4
  uint16_t PrescalerValue;
5
6
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);              // TIMER 2 Takt freigeben
7
8
  PrescalerValue = (uint16_t) (SystemCoreClock / TIMER_TAKT) - 1;   // Vorteiler berechnen
9
10
  // Timer Grundkonfiguration
11
  TIM_TimeBaseStructure.TIM_Period = 100;                         // Timer zählt von 0 ... 100: also alle 10ms
12
  TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
13
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
14
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
15
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);                   // Timer einstellen
16
17
  //Timer Vorteiler-Taktkonfiguration
18
  TIM_PrescalerConfig(TIM2, PrescalerValue, TIM_PSCReloadMode_Immediate); // Auto-Reload
19
20
  
21
  // Timer aktivieren
22
  TIM_Cmd(TIM2, ENABLE);
23
  
24
  NVIC_InitTypeDef NVIC_InitStructure;
25
 /* Enable the Interrupt */
26
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
27
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
28
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
29
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
30
  NVIC_Init(&NVIC_InitStructure);
31
32
  TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
33
  
34
  
35
  //Init IRQ for MLX90109
36
  RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;                     // enable clock for Alternate Function
37
  AFIO->EXTICR[2] &= 0xFFF0;            //clear used pin
38
  AFIO->EXTICR[2] |= (0x00);           // set pin 8 PORT A
39
40
41
42
  EXTI_InitTypeDef EXTI_InitStructure;
43
  EXTI_InitStructure.EXTI_Line= EXTI_Line8;
44
  EXTI_InitStructure.EXTI_Mode= EXTI_Mode_Interrupt;
45
  EXTI_InitStructure.EXTI_Trigger= EXTI_Trigger_Falling;
46
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
47
  EXTI_Init(&EXTI_InitStructure);
48
49
50
51
 /* Enable the Interrupt */
52
  NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
53
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
54
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
55
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
56
  NVIC_Init(&NVIC_InitStructure);

IRQ-Handler für Clock Signal
1
void EXTI9_5_IRQHandler(void)
2
{
3
  TIM_SetCounter(TIM2, 0); // reset watchdog counter as we still receive clock ticks
4
  
5
  if (RFID.isValidID) // this tag was already read and not removed since
6
  {
7
    EXTI_ClearFlag(EXTI_Line8);
8
    return;
9
  }
10
11
//hier ist code der die Daten verarbeitet aber nichts mit er Hardware anstellt
12
13
  EXTI_ClearFlag(EXTI_Line8);
14
}

Timer IRQ-Handler:
1
void TIM2_IRQHandler(void)
2
{
3
  if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)                 // check interrupt source
4
  {
5
    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
6
   Target.LEDOn(LED_RED);
7
//    Delay(0xAFFFF);
8
9
    /* Turn off LD1 */
10
    Target.LEDOff(LED_RED);
11
12
    RFID.isValidID = false;
13
  }
14
 }
15
}

Die LED Toggle ich nur, damit ich mit dem LA sehen wenn ein Timer IRQ 
ausgelöst wurde.
Sieht man auch schön auf dem LA Screenshot.

von Lutz (Gast)


Lesenswert?

Thomas Burkhart schrieb:
> //Init IRQ for MLX90109
>   RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;   // enable clock for Alternate Function
>   AFIO->EXTICR[2] &= 0xFFF0;            //clear used pin
betrifft EXTI4 an PA4.

>   AFIO->EXTICR[2] |= (0x00);           // set pin 8 PORT A
wie das?

Du meinst nicht zufällig EXTICR[3], wenn Du wirklich PA8  nutzen willst?

Thomas Burkhart schrieb:
> EXTI_InitStructure.EXTI_LineCmd = ENABLE;
>   EXTI_Init(&EXTI_InitStructure);
Muß die Reihenfolge nicht gedreht werden? Erst initialisieren, dann 
einschalten?

Thomas Burkhart schrieb:
> /* Enable the Interrupt */
>   NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
Jetzt EXTI9?

Sorry, aber nach dem Mittagsschlaf brauche ich erstmal einen Kaffee, um 
dem folgen zu können.

von Thomas B. (escamoteur)


Lesenswert?

Lutz schrieb:
> Thomas Burkhart schrieb:
>> //Init IRQ for MLX90109
>>   RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;   // enable clock for Alternate Function
>>   AFIO->EXTICR[2] &= 0xFFF0;            //clear used pin
> betrifft EXTI4 an PA4.
>
>>   AFIO->EXTICR[2] |= (0x00);           // set pin 8 PORT A
> wie das?
>
> Du meinst nicht zufällig EXTICR[3], wenn Du wirklich PA8  nutzen willst?

Das ARRAY EXTICR[] beginnt bei 0, die Registernummerierung aber bei 1, 
daher 2 und nicht 3.


>> EXTI_InitStructure.EXTI_LineCmd = ENABLE;
>>   EXTI_Init(&EXTI_InitStructure);
> Muß die Reihenfolge nicht gedreht werden? Erst initialisieren, dann
> einschalten?

Wieso, das erste setzt ja nur ein Feld in der InitStruktur und schaltet 
noch gar nichts ein.

>
> Thomas Burkhart schrieb:
>> /* Enable the Interrupt */
>>   NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
> Jetzt EXTI9?

EXTI9 - 5 teilen sich einen IRQ, da ich EXTI8 brauche muss ich den 
nehmen.

Gruß
Tom


> Sorry, aber nach dem Mittagsschlaf brauche ich erstmal einen Kaffee, um
> dem folgen zu können.

von Lutz (Gast)


Lesenswert?

Thomas Burkhart schrieb:
> Das ARRAY EXTICR[] beginnt bei 0, die Registernummerierung aber bei 1,
> daher 2 und nicht 3.

Donnerwetter. Kein Wunder, daß man sich bei dieser Logik der Lib 
vergrüßt. Ich hätte nach dem Datenblatt eigentlich sowas wie
AFIO->EXTICR3 = ...
o.ä. erwartet. Aber ein Array, dessen Index nicht mit der Registernummer 
im Datenblatt übereinstimmt .... Kann ja nur zu Fehlern führen. Find ich 
nicht gut, aber interessiert wohl leider niemanden.

Thomas Burkhart schrieb:
>>>   AFIO->EXTICR[2] |= (0x00);           // set pin 8 PORT A
>> wie das?
Aber was bringt denn hier ein verODERn des Registerinhalts mit 0?

Thomas Burkhart schrieb:
>>> EXTI_InitStructure.EXTI_LineCmd = ENABLE;
>>>   EXTI_Init(&EXTI_InitStructure);
>> Muß die Reihenfolge nicht gedreht werden? Erst initialisieren, dann
>> einschalten?
>
> Wieso, das erste setzt ja nur ein Feld in der InitStruktur und schaltet
> noch gar nichts ein.
Oh ja, gesegnet sei der Kaffee, dann liest man es auch richtig und sieht 
nicht nur ENABLE ...

Thomas Burkhart schrieb:
> EXTI9 - 5 teilen sich einen IRQ, da ich EXTI8 brauche muss ich den
> nehmen.
So viel Kaffee kann ich doch gar nicht trinken.
P.S.: Diese ganze Peinlichkeit bleibt unter uns, bitte nicht 
weitererzählen.
Kurzum: Ich kann da leider nicht helfen.

von Thomas B. (escamoteur)


Lesenswert?

:-) :-)

Das Odern mit Null macht natürlich nichts, aber sollte nur zeigen, dass 
an dieser Stelle normalerweise der entsprechende Pin gesetzt würde.

von Thomas B. (escamoteur)


Lesenswert?

Keiner sonst ne Idee?

von Hannes S. (Gast)


Lesenswert?

Hab mal schnell das TIM_SetCounter(TIM2, 0); bei mir ausprobiert: Timer 
wird zurückgesetzt, wenn ich das in einer schlafe mache kommen keine 
Update IRQs mehr (allerdings auf F207 getestet).

Was mir aber auffällt: Wieso sind auf dem LA screenshot nur 3 Nadeln in 
einem abstand von 70ms bzw. 40ms? Du sagtest doch, dass der Timer 
ungerührt mit dem Intervall weiterläuft. Und das wäre ja eigentlich 
10ms?

von Thomas B. (escamoteur)


Lesenswert?

Du hast recht, dass ist mir in der Zwischezeit auch aufgefallen, es 
scheint also nur machmal zu passieren, dass noch ein IRQ durchkommt.

Danke fürs ausprobieren.

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.