Forum: Mikrocontroller und Digitale Elektronik ARM STM32F302 CUBEMX PWM Freq ändern


von kennis.b (Gast)


Lesenswert?

Hallo und einen schönen Abend :)
Ich würde gerne einen Schrittmotor mit einem STM32F302 ansteuern. Ich 
habe mir gedacht ich mache das mit der PWM- Funktion indem ich die 
Frequenz anpasse und die Impulsdauer dazu dann einfach ein bestimmter 
Prozentsatz ist (Mein Schrittmotortreiber benötigt nur Impulse). Die 
Funktion die ich geschrieben habe funktioniert leider nur in einem 
bestimmten Frequenz Bereich. Bei kleinen Frequenzen schaltet das PWM 
einfach ab. Soweit ich nun schon in Foren lesen konnte muss beim Ändern 
des Prescalers der Channel aus und wieder eingeschaltet werden damit 
alle benötigten Bits gesetzt werden. Ich finde nur einfach keine Lösung 
die bei mir funktioniert. Am liebsten würde ich es über eine HAL 
Funktion machen und nicht die einzelnen Register selber setzen müssen.
Vielleicht hat ja einer von euch noch eine Idee was ich tun könnte.
Vielen Dank schonmal :)

1
void TIM_set_freq(TIM_HandleTypeDef* timHandle, double freq)
2
{
3
  TIM_CCxChannelCmd(timHandle->Instance,TIM_CHANNEL_1,TIM_CCx_DISABLE);
4
5
  if (freq > 0)
6
  {
7
    long long Prescaler = SystemCoreClock / freq / 10 ;
8
    uint32_t Period = 10;
9
10
    while (Prescaler > 1000)
11
    {
12
      Prescaler /= 10;
13
      Period *= 10;
14
    }
15
16
    __HAL_TIM_SET_AUTORELOAD(timHandle,Period - 1);
17
    __HAL_TIM_SET_COMPARE(timHandle,TIM_CHANNEL_1, (Period - 1) / 5);
18
    __HAL_TIM_SET_PRESCALER(timHandle, Prescaler - 1);
19
20
    TIM_CCxChannelCmd(timHandle->Instance,TIM_CHANNEL_1,TIM_CCx_ENABLE);
21
22
    
23
24
    TIM_CCxChannelCmd(timHandle>Instance,timHandle->Channel,1);
25
26
27
                HAL_TIM_PWM_Start(timHandle,TIM_CHANNEL_1);
28
  }
29
  else
30
  {
31
               
32
  }

von Christopher J. (christopher_j23)


Lesenswert?

kennis.b schrieb:
> Soweit ich nun schon in Foren lesen konnte muss beim Ändern
> des Prescalers der Channel aus und wieder eingeschaltet werden damit
> alle benötigten Bits gesetzt werden. Ich finde nur einfach keine Lösung
> die bei mir funktioniert.

Das ist eventuell bei den HAL-Funktionen der Fall, den Controller 
interessiert das aber nicht. Wenn du den Prescaler änderst, dann wird 
der beim nächsten Update-Event aktualisiert. Das Verhalten ist somit wie 
mit einem gebufferten ARR, d.h. wenn ARPE=1, mit dem Unterschied, das 
man es nicht ausschalten kann.

Schnapp dir mal das Reference-Manual und lies dir das Kapitel über 
"General-purpose Timer" durch.


kennis.b schrieb:
> long long Prescaler = SystemCoreClock  freq  10 ;
>     uint32_t Period = 10;
>
>     while (Prescaler > 1000)
>     {
>       Prescaler /= 10;
>       Period *= 10;
>     }

Ich würde die Typen aus stdint.h verwenden, also uint32_t Prescaler = 
... Außerdem ist long long viel zu groß und für die Rechnerei empfiehlen 
sich  Zweierpotenzen statt Zehnerpotenzen.

von kennis.b (Gast)


Lesenswert?

Christopher J. schrieb:
> Wenn du den Prescaler änderst, dann wird
> der beim nächsten Update-Event aktualisiert. Das Verhalten ist somit wie
> mit einem gebufferten ARR, d.h. wenn ARPE=1, mit dem Unterschied, das
> man es nicht ausschalten kann.

Also sollte ich das ARPE bit einfach komplett auf 1 setzen damit der 
Prescaler dann automatisch eingeladen wird (gerade gesehen,dass das auch 
in cubemx geht) oder sollte ich besser das UDIS Bit auf 0 setzen und 
dann auf den nächsten Überlauf warten? (das kann ja gegebenenfalls sehr 
lange dauern)




Christopher J. schrieb:
> Ich würde die Typen aus stdint.h verwenden, also uint32_t Prescaler =
> ...
1
 long long Prescaler = SystemCoreClock / freq / 10 ;

Irgendwie hat er das geteilt durch wohl nicht übernommen. Int dachte ich 
wäre nicht so schön wegen der Rechner Genauigkeit. Es mag aber auch 
sein, dass es bei dem verhältnismäßigen großen SystemCoreClock keine 
Rolle spielt.

Christopher J. schrieb:
> Außerdem ist long long viel zu groß und für die Rechnerei empfiehlen
> sich  Zweierpotenzen statt Zehnerpotenzen.

Ja das werde ich noch ändern, vielen dank schonmal :)

von Christopher J. (christopher_j23)


Lesenswert?

Ja, UDIS auf 0 setzen hilft, obwohl das eigentlich sowieso der 
Resetzustand sein sollte aber CubeMX ... ARPE betrifft den Prescaler 
nicht, sondern nur den ARR-Wert.

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.