Forum: Mikrocontroller und Digitale Elektronik Timer2 stm32f107vc


von Ma B. (drumstick)


Lesenswert?

Guten Tag zusammen!


Ich arbeite mit dem STM32F107VC, uVision von Keil

Ich möchte mit dem Timer2 arbeiten, habe ihn als downcounter 
eingestellt. Bei underflow möchte ich einen Interrupt auslösen.

Das Problem ist, dass bei jedem Zählschritt ein Event, also ein 
Interrupt ausgelöst wird! Habe aber das 2 Bit von CR2 gesetzt:

Bit 2 URS: Update request source:   1: Only counter overflow/underflow 
generates an update interrupt or DMA request if enabled.
1
// Timer2
2
3
    TIM2    ->  CR1     =   0x0000001C;//
4
    TIM2    ->  CR2     =   0x00000000;//CONTROLLREG2;                     // Reset Controllregister 2
5
    TIM2    ->  PSC     =   0x00000000;//PRESCALE;                         // Prescaler
6
    TIM2    ->  ARR     =   0x0000FFFF;//AUTORELOAD;                       // Auto-Reload Register
7
    TIM2    ->  CCMR1   =   0x00000000;//COMPAREMODREG1;                   // Compare Mode Register 1  Outputcompare Mode
8
    TIM2    ->  CCMR2   =   0x00000000;//COMPAREMODREG2;                   // Compare Mode Register 2  Output Compare 1 Mode; Output Compare 2 Mode 
9
    TIM2    ->  CCER    =   0x00000000;//COMPAREENABLEREG;                 // Compare Enable Register; Compare 1 Output Enable; Compare 2 Output Enable
10
    TIM2    ->  SMCR    =   0x00000000;//SLAVEMODECONTROLLREG;             // Slave Mode Controll Register
11
    TIM2    ->  CCR1    =   0x00000000;//COMPAREREG1;                      // Compare Register 1
12
    TIM2    ->  CCR2    =   0x00000000;//COMPAREREG2;                      // Compare Register 2
13
    TIM2    ->  SR      =   0x00000000;//STATUSREG;                        // Status Register: Interrupt Flagbits
14
    TIM2    ->  DIER    =   0x00000001;//INTERRUPTENABLEREG;               // Interrupt Enable Register: Interrupt Compare 1 und Compare 2 enable
15
    TIM2    ->  EGR     =   0x00000000;//EVENTGENERATREG;                  // Event Generator Register: Update generation; Compare 1 Generation / Compare 2 Generation 
16
    TIM2    ->  BDTR    =   0x00000000;//BRAKDEATTIMEREG;                  // Lock off, break inputs disable

Was habe ich übersehen oder weis jemand, was falsch ist??

Vielen dank und Gruss!

von Ma B. (drumstick)


Lesenswert?

Warum wird nicht erst bei underflow ein Interrupt ausgelöst? Seltsam ist 
auch, dass egal welchen Wert ich ins PSC oder ins ARR lade, der 
Interrupt jede 1us ausgelöst wird!? die Register sind doch richtig 
eingestellt, warum funktioniert das nicht??


Vielen Dank und Gruss!!

M. B.

von Matthias K. (matthiask)


Lesenswert?

Wie sieht der Interrupt-Handler aus? Löscht Du dort auch das PendingBit 
von Timer 2?

von Ma B. (drumstick)


Lesenswert?

1
void TIM2_IRQHandler(void)
2
{
3
4
    if(TIM2 ->  SR & (1 << 0))
5
    {
6
7
        TIM2 ->  SR |= (1 << 0);
8
    
9
        GPIOE   ->  BSRR    |=   (1 << 8);                     // AD-Wert an Port E ausgeben
10
        GPIOE   ->  BSRR    |=  0xFF000000;
11
    
12
    }
13
14
}

Ja, so sollte es gehen. Mache das auch bei anderen Interrupts so!

Danke und Gruss!

M.B.

von Ma B. (drumstick)


Lesenswert?

Aber Du hast glaub recht, das wird garnicht zurückgesetzt! Mache dies 
aber immer so!????

Gruss

M.B.

von Ma B. (drumstick)


Lesenswert?

Ich kanns nicht löschen!! Wird das jederzeit wieder gesetzt?? Kann ich 
mir aber nicht vorstellen!!
1
TIM2    ->  SR |= (1 << 0);

dieser Befehl sollte das Statusbit doch löschen??

danke und Gruss!

M.B.

von Mike R. (thesealion)


Lesenswert?

M. B. schrieb:
1
TIM2    ->  SR |= (1 << 0);
>
> dieser Befehl sollte das Statusbit doch löschen??

Was kommt denn Raus, wenn du z.b. 0xFF mit 0x00 bitweise oder 
verknüpfst? :)

Mit einem "oder" kannst du nichts löschen, nur setzen.

das löschen des Bits solltest du mal so probieren
1
TIM2    ->  SR &= ~(1 << 0);

Wobei ich jetzt nicht nachgesehen habe, ob das Bit (hier Bit 0) das 
richtige ist.

von Matthias K. (matthiask)


Lesenswert?

Hier die Variante mit der FW-Lib, kannst ggf. mal in den entsprechenden 
Routinen dort nachsehen:
1
//***********************************************************************************************
2
// Timer 2 Interrupt-Handler
3
//***********************************************************************************************
4
void TIM2_IRQHandler(void) {
5
  if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
6
    // Überlauf des Zählregisters
7
    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
8
  }
9
}

von (prx) A. K. (prx)


Lesenswert?

M. B. schrieb:

> dieser Befehl sollte das Statusbit doch löschen??

Nicht jeder Controller löscht Interrupt-Flags indem man sie setzt. 
Manche zwar schon, aber verallgemeinern lässt sich das nicht.

Abgesehen von der Code/Kommentar-Schere in
> GPIOE   ->  BSRR    |=   (1 << 8);      // AD-Wert an Port E ausgeben
> GPIOE   ->  BSRR    |=  0xFF000000;
kann man einen AD-Wert beispielsweise auch eleganter ausgeben, hier mal 
für 12 Bits auf GPIOE0..11
  GPIOE->BSRR = (0x0FFF << 16+0) | (value & 0x0FFF) << 0;
Was speziell in einer ISR etliche Takte einspart.

Das BSRR zu erst lesen ist schon vom Ansatz her sinnfrei und überdies 
auch nicht vorgesehen.

von Ma B. (drumstick)


Lesenswert?

danke für die Tipps, jetzt klappts auch!

Gruss

M.B.

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.