Forum: Mikrocontroller und Digitale Elektronik STM32 - Veränderbare Frequenz erzeugen


von Blumenpol (Gast)


Lesenswert?

Ich möchte mit einem der Timer des STM32F1 eine veränderliche Frequenz 
erzeugen. (Ich möchte hingegen keine PWM, also ein Signal fester 
Frequenz aber mit veränderlichem Duty-Cycle erzeugen).

Nach längerer Lektüre des Reference-Manuals meine ich folgendes 
feststellen zu können:

1. Bei einem Overflow und dem Update-Event des Timer (also dem erreichen 
des in das Auto-Reload-Register geladenen Wertes) kann ein Interrupt 
ausgelöst werden. Es kann aber hardwaremäßig kein Pin getoggelt werden 
(abgesehen von Code in der Int-Routine der das tun könnte, aber das wäre 
eben nicht per Hardware).

2. Beim erreichen des Wertes in einem der Compare Register kann 
hardwaremäßig ein Pin getoggelt werden (OCx).


Da ich, wiegesagt, eine veränderliche Frequenz (mit festem Duty-Cycle 
von 50%) erzeugen möchte und das, wenn möglich per Hardware des Timers, 
bleibt mir also scheinbar nur die Möglichkeit eins der Compare-Register 
auf die Hälfte der Periodendauer und das Autoreload-Register auf die 
Periodendauer einzustellen und beim Compare den OCx zu toggeln.

Das aber würde bedeuten, das bei einer Frequenzänderung immer beide 
Register, sowohl das Compare-Register als auch das Auto-Reload-Register 
geändert werden müssen.

Ich frage mich nun, ob ich etwas übersehen habe oder ob es tatsächlich 
keine andere Möglichkeit gibt.

Hat jemand Informationen oder Tips dazu?

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Blumenpol schrieb:
> Es kann aber hardwaremäßig kein Pin getoggelt werden
> (abgesehen von Code in der Int-Routine der das tun könnte, aber das wäre
> eben nicht per Hardware).

Das ist wahr, aber was spricht dagegen, es mit einer Zeile im IRQ 
Handler zu tun ?

Blumenpol schrieb:
> bleibt mir also scheinbar nur die Möglichkeit eins der Compare-Register
> auf die Hälfte der Periodendauer und das Autoreload-Register auf die
> Periodendauer einzustellen und beim Compare den OCx zu toggeln.

Ja, auch richtig. Im Centered Mode mit Hoch- und runterzählendem Timer 
hast du vermutlich das schönste Signal. Warum willst du das nicht machen 
?
Es gäbe noch die Möglichkeit, den frequenzbestimmenden Timer mit kurzem 
OC laufen zu lassen und ein externes Flipflop sorgt dann für die 50% 
duty. Dazu muss der Timer mit dem doppelten der gewünschten Frequenz 
laufen.

von Blumenpol (Gast)


Lesenswert?

>Das ist wahr, aber was spricht dagegen, es mit einer Zeile im IRQ Handler zu tun 
?

Zunächst nichts.

Ich will die vorhandenen Möglichkeiten nutzen bzw. wissen ob es sie 
gibt. Zur Erzeugung einer PWM lasse ich die Hardware den Ausgangspin 
toggeln weil sie es kann. Sonst, im allgemeinen, aus keinem besonderen 
Grund.

Wenn ich nur ein Register zu ändern bräuchte um die Frequenz zu 
einzustellen, dann würde ich das tun, anstatt zwei Register zu ändern.


Ich bin mir nur nicht ganz sicher ob das Ergebnis meiner Lektüre richtig 
und vollständig ist. Deswegen hätte ich gerne entweder eine Bestätigung 
oder einer Widerlegung gehabt. Das wäre nett.

von Blumenpol (Gast)


Lesenswert?

Also, es geht doch.

Man muss nur den Compare Wert auf 0 setzen und dafür einen Pin-Toggle 
programmieren. Über die Periode, also das Auto-Reload-Register bestimmt 
man dann die halbe Periodendauer.

von A. B. (funky)


Lesenswert?

hi,

könntest du evtl. die wesentlichen Quelltext auszüge zu deiner 
Timerconfig und deiner IRQ Routine mal posten?


Ich möchte auch eine variable Frequenz erzeugen und hatte es so 
verstanden, das es an PC6 mittels Timer3 möglich ist.
Hardwaremässig hinbekommen habe ich es aber nicht.

Momentan sieht es bei mir so aus (Auszüge...mein timer3 läuft mit 30MHz 
und auch die IRQ Routine wird angesprungen)
1
void TIM3_IRQHandler(void)
2
{
3
  if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)
4
  {
5
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);
6
    GPIO_ToggleBits(GPIOC, GPIO_Pin_6);
7
  }
8
}

1
void init(void){
2
3
GPIO_InitTypeDef GPIO_InitStructure;
4
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
5
  TIM_OCInitTypeDef  TIM_OCInitStructure;
6
7
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);     /* Tim3 Clock */
8
  RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOC, ENABLE);  
9
  //GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_TIM3);    /* PC6 TIM3 Chann */
10
  
11
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_6;
12
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;
13
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
14
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
15
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
16
  GPIO_Init(GPIOC, &GPIO_InitStructure);
17
18
19
  /*
20
  TIM3 Config siehe auch STM32F2xx_Clock_Configuration_V1.1.0.xls
21
    TIM3CLK = 30 MHz, Prescaler = 29, TIM3 counter clock = 1MHz
22
  */
23
24
  TIM_TimeBaseStructure.TIM_Period = 10;
25
  TIM_TimeBaseStructure.TIM_Prescaler = 29;
26
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
27
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
28
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
29
30
  /* Output Compare Active Mode configuration: Channel1 */
31
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Active;
32
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
33
  TIM_OCInitStructure.TIM_Pulse = 0;//CCR1_Val;
34
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
35
  TIM_OC1Init(TIM3, &TIM_OCInitStructure);
36
37
  TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Disable);
38
  //TIM_ARRPreloadConfig(TIM3,ENABLE);
39
  TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);
40
}


Eine veränderbare Frequenz erzeuge ich, indem ich die Periode ändere.
Aber ist das so im Sinne des Erfinders? Mein TIM_Pulse aka CCR1_Val hat 
überhaupt keinen Einfluss(was ich eigentlich erwartet hätte)

Hardwaremässig den Pin toggeln zu lassen habe ich auch nicht 
hinbekommen, obwohl ich das Datenblatt so verstanden habe das es gehen 
sollte:

1. Select the counter clock (internal, external, prescaler).
2.  Write the desired data in the TIMx_ARR and TIMx_CCRx registers.
3.  Set the CCxIE and/or CCxDE bits if an interrupt and/or a DMA request 
is to be
generated.
4.  Select the output mode. For example, you must write OCxM=011, 
OCxPE=0, CCxP=0
and CCxE=1 to toggle OCx output pin when CNT matches CCRx, CCRx preload 
is not
used, OCx is enabled and active high.
5.  Enable the counter by setting the CEN bit in the TIMx_CR1 register.


Hat jemand eine Idee, was ich da verpeile?
Eine änderbare Frequenz kann ich damit schon erzeugen, aber ich glaube, 
das ich das recht umständlich mache und nicht so wie es eigentlich 
gedacht ist

von A. B. (funky)


Lesenswert?

Wenn ich den Alternate Function Mode aktiviere, dann ist der Pin doch an 
Tim3 gekoppelt und wird als Output/input verwendet, oder? Habe da wie 
gesagt rumprobiert, aber es lief nie so wie ich es wollte(bzw. es ist 
gar nix passiert im AF Mode)

von A. B. (funky)


Lesenswert?

threadersteller? bitte melde dich ;)

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

A. B. schrieb:
> Wenn ich den Alternate Function Mode aktiviere, dann ist der Pin doch an
> Tim3 gekoppelt und wird als Output/input verwendet, oder?

Da hast vermutlich vergessen, die AFIO Clock zu aktivieren:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

von A. B. (funky)


Lesenswert?

ne, ich benutze einen STM32F2 da gibts das nicht mehr.

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.