Forum: Mikrocontroller und Digitale Elektronik STM32 Timer6 - nervt


von Thomas T. (runout)


Angehängte Dateien:

Lesenswert?

Hallo Gemeinde,

ich möchte einen "einfachen" 16-bitTimer (TIM6) in Betrieb nehmen.
Target ist STM32L496.
Er soll einen 4kHz-Interrupt erzeugen.

Das Teil läuft ein nicht los.

Weder mit HAL-Gedöns:
  htim6.Instance = TIM6;
  htim6.Init.Prescaler = 11999;0,25ms
  htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim6.Init.Period = 1;
  htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  HAL_TIM_Base_Init(&htim6)

noch mit Schhreiben in die Register ()

  TIM6->PSC = 47999;
  TIM6->ARR = ms;
  TIM6->CR1 |= TIM_CR1_CEN;
  while (!(TIM6->SR & TIM_SR_UIF));

Ich frage im SysTick mit "__HAL_TIM_GET_COUNTER(&htim6);"
den Counterwert ab. Leider immer = 0.

Habe ich im Clocck-Tree noch irgendwas vergessen?
Wird der Timer-Clock von "HSI48 RC" hergenommen.
Arbeite jetzt mal die AN4776 von ST durch.

Der Timer 6 sollte für sowas Einfaches doch geeignet sein
oder müssen es "full-features"-Timer sein.

Grüße
Runout

von Bimbo. (Gast)


Lesenswert?

Was ist deine Clk Frequency für die Timer Perihperie? Vermeide Magic 
Numbers! Hast du den Clock im RCC Register aktiviert?
1
TIM6->PSC = F_CLK_VOM_TIMER / DEINEFREQUENZ - 1; 
2
TIM6->ARR = 0xffff;
3
TIM6->CR1 |= TIM_CR1_CEN;
4
//while (!(TIM6->SR & TIM_SR_UIF)); //Was soll das hier?

Hast du anschließend den NVIC parametriert? Und dran denken, im 
Interrupt das UIF per Software zurückzusetzen. Zusätzlich sehe keine 
Registeranweisung um den Überlaufinterrupt zu aktivieren!

von Kalle (Gast)


Lesenswert?

Ruf doch einfach mal die HAL-Funktion zum Starten des Timers auf, statt 
das über Register zu machen. Vielleicht geht es dann oder du kriegst 
einen Fehler mit dem du was anfangen kannst

von Bimbo. (Gast)


Lesenswert?

Try this, ohne Gewähr dass es funktioniert:
1
voi initTIM6(){
2
  #define SET_ICPR(a) NVIC->ICPR[(a)/32] |= (1<<((a)%32));
3
  #define SET_ISER(a) NVIC->ISER[(a)/32] |= (1<<((a)%32));
4
  #define SET_IP(a,b) NVIC->IP[(a)/4] |= ((b<<4)<<(8*((a)%4)));
5
  TIM6->PSC = F_CPU / 4000 - 1;
6
  TIM6->ARR = 0xffff;  //Timer für Bildwiederholrate
7
  TIM6->DIER |= TIM_DIER_UIE;        //OVF Interrupt enable
8
  TIM6->CR1 |= TIM_CR1_CEN;        //Timer 3 aktivieren
9
  SET_ICPR(TIM6_IRQn);
10
  SET_ISER(TIM6_IRQn);
11
  SET_IP(TIM6_IRQn, 1);
12
}
13
14
void TIM6_IRQHandler(){
15
  TIM6->SR &= ~TIM_SR_UIF;
16
  //Geiler Scheiss hier
17
}

von Bimbo. (Gast)


Lesenswert?

Korrektur:
1
#define SET_ICPR(a) NVIC->ICPR[(a)/32] |= (1<<((a)%32));
2
#define SET_ISER(a) NVIC->ISER[(a)/32] |= (1<<((a)%32));
3
#define SET_IP(a,b) NVIC->IP[(a)/4] |= ((b<<4)<<(8*((a)%4)));
4
5
void initTIM6(){
6
  //TIM6->PSC = F_CPU / 4000 - 1;
7
  TIM6->ARR = F_CPU / 4000 - 1;  
8
  TIM6->DIER |= TIM_DIER_UIE;        
9
  TIM6->CR1 |= TIM_CR1_CEN;       
10
  SET_ICPR(TIM6_IRQn);
11
  SET_ISER(TIM6_IRQn);
12
  SET_IP(TIM6_IRQn, 1);
13
}
14
15
void TIM6_IRQHandler(){
16
  TIM6->SR &= ~TIM_SR_UIF;
17
  //Geiler Scheiss hier
18
}

von Markus M. (adrock)


Lesenswert?

Das wichtigste dürfte das sein:

"Hast du den Clock im RCC Register aktiviert?"

Ist ein beliebter Fehler. Ist erstmal ungewohnt dass man wirklich jedes 
Stück Peripherie wirklich explizit erst einmal einschalten muss beim 
STM32.

von Bimbo. (Gast)


Lesenswert?

Markus M. schrieb:
> Ist ein beliebter Fehler. Ist erstmal ungewohnt dass man wirklich jedes
> Stück Peripherie wirklich explizit erst einmal einschalten muss beim
> STM32.

Finde ich ein gutes Feature. Also noch folgende Zeile einfügen 
(ungefähr):
1
RCC->AHBIRGENDWAS |= RCC_AHBIRGENDWAS _TIM6EN;

von Martin B. (ratazong)


Lesenswert?

mit HAL Gedöns sollte es klappen. Am einfachsten, wenn du cubeMX das 
machen lässt.

bei mir generiert CubeMX
static void MX_TIM6_Init(void)
{

  TIM_MasterConfigTypeDef sMasterConfig;

  htim6.Instance = TIM6;
  htim6.Init.Prescaler = 0;
  htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim6.Init.Period = 200;
  if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
  {
    _Error_Handler(_FILE_, _LINE_);
  }

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != 
HAL_OK)
  {
    _Error_Handler(_FILE_, _LINE_);
  }

}
und im *it.c file auch gleich die IRQ routine.

Du setzt den Prescaler ziemlich hoch, so dass .25 ms Zählrate rate 
rauskommen, dann die Period auf 1. Das dürfte nicht zum gewünschten 
Ergebnis führen. Warum nicht umgedreht?

vielleicht brauchst Du auch noch 
HAL_TIMEx_MasterConfigSynchronization(), der Timer6 ist irgendwie mit 
dem DAC verheiratet.

von Martin B. (ratazong)


Lesenswert?

Ach ja und das Starten nicht vergessen:
HAL_TIM_Base_Start(tim6);

von Thomas T. (runout)


Lesenswert?

Hallo Gemeinde,

danke für die Tipps.
Ja richtig, das Starten hat fehlt.

HAL_TIM_Base_Start_IT(&htim6); - fehlte
HAL_TIM_PeriodElapsedCallback() wird jetzt aufgerufen.

Werde aber auch "Bimbo. (Gast)" seine "gestraffte" Variante 
ausprobieren.

Danke
Runout

von Bimbo. (Gast)


Lesenswert?

Thomas T. schrieb:
> Werde aber auch "Bimbo. (Gast)" seine "gestraffte" Variante
> ausprobieren.


Diese habe ich wie gesagt nicht geprüft. Sollte aber funktionieren, nur 
folgende Zeile musst du selber anpassen:
1
RCC->AHBIRGENDWAS |= RCC_AHBIRGENDWAS_TIM6EN;

Wobei F_CPU = Taktfrequenz der Timers.

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.