www.mikrocontroller.net

Forum: Mikrocontroller und Elektronik STM32F4 Servo PWM


Autor: Moritz M. (avrprogger)
Datum:

Hallo,

ich möchte gerne ein PWM Signal mit einem STM32F4 erzeugen. Das Signal
soll einen Frequenz von 50Hz haben und eine Puls von 1500µs länge.

Hat jemand vielleicht einen Code-Ausschnitt für mich wo ein Timer
Initalisiert und gestartet wird? Am besten wenn der Timer auch noch per
DMA geladen wird.

Moritz
Autor: RP6Conrad (Gast)
Datum:

Bei mein discovery board (STM32F100) lauft das mit Timer 1 in PWM mode
(hat 4 Channels, damit kan men dan 4 verschiedene Servo-signale
erzeugen). Timer lauft an 1 MHz (forteiler), zaehlt bis 19999 (= 20ms),
dan fangt er wieder an. Die 4 channels stellt men dan ein auf 1000 bis
2000 (= 1 bis 2 ms). Auflosung ist dan 1µs. Code config Timer 1 : (GPIO
und clock Timer 1 auch noch configurieren !)
void Timer_Config(void)
{
    /* -----------------------------------------------------------------------
    TIM1 Configuration: generate 2 PWM signals with 2 different duty cycles:
    TIM1CLK = 24 MHz, Prescaler = 23, TIM1 counter clock = 1 MHz
    TIM1 ARR Register = 19999=> TIM1 Frequency = TIM1 counter clock/(ARR + 1)
    TIM1 Frequency = 50 Hz.
    TIM1 Channel1 pulse lenght = TIM1->CCR1 value gives servo between 1000 and 2000 µs
    TIM1 Channel4 pulse lenght = TIM1->CCR4 value gives servo between 1000 and 2000 µs
  ----------------------------------------------------------------------- */
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  TIM_OCInitTypeDef  TIM_OCInitStructure;
  /* Time base configuration TIM1*/
  TIM_TimeBaseStructure.TIM_Period = 19999;//PWM freq. = 1MHz/20000 = 50Hz
  TIM_TimeBaseStructure.TIM_Prescaler = 23;// Timer loopt aan 24 MHz/24 = 1MHz
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
  /* PWM1 Mode configuration: TIM 1, Channel1 */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  TIM_OC1Init(TIM1, &TIM_OCInitStructure);
  TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
  /* PWM1 Mode configuration: TIM 1, Channel4 */
  TIM_OC4Init(TIM1, &TIM_OCInitStructure);
  TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);
}
Autor: Moritz M. (avrprogger)
Datum:

Hallo,

viele Dank für das Beispiel. Hat jemand viellecht noch ein Beispiel für
STM32F4?

Moritz
Autor: Moritz M. (avrprogger)
Datum:

Hallo,

hat jemand vielleicht einen Kompletten source code, wo ein TIMER
Initalisiert wird? Weiß jemand wovon der TIMCLK1 abgeleitet wird?

Moritz
Autor: Julian (Gast)
Datum:

Beim F1er gabs in der Firmwarebibliothek Beispiele für alle
Peripherieeinheiten, beim F4er nicht?

Andersrum wird hier ein Schuh draus: zeige, was du bisher geschafft hast
und wir helfen dir Fehler zu finden. Für dich was schreiben wird hier
niemand! Aber zwischen den Zeilen lese ich eine gewisse Unlust zur
selbstständigen Arbeit heraus...
Autor: Moritz M. (avrprogger)
Datum:

Hallo,

ja ich möchte schon selber etwas programmieren doch leider weiß ich noch
nichts über die Timer (Deshalb frage ich ja). Am einfachsten für mich
ist es aus fertigem code zu lernen. Bei der Lib sind auch einige
Beispiele dabei dabei, allerdings erklärt die nicht woher der Takt der
Timer kommt, was die verschidenen Vorteile Bedeuten und wozu die gut
sind usw... .

In den Reference Manual und dem Datasheet werde ich auch nicht schlauer.

Moritz
Autor: Markus K. (markus_k64) Flattr this
Datum:

Hi Moritz

mir ist das Benutzen eines Timers heute erfolgreich mit dem STM32F4
Board gelungen.

Das folgende Beispiel nutzt TIM4 mit PWM. Das "Ergebnis" wird auf der
grünen onboard LED ausgegeben. Die LED wird entsprechend heller und
dunkler.
#include "stm32f4xx_conf.h"

#define MOTORPWMTIMER      TIM4
#define MOTORPWMTIMCLOCK    RCC_APB1Periph_TIM4
#define MOTORPWMPORTCLOCK    RCC_AHB1Periph_GPIOD
#define MOTORPWMAF         GPIO_AF_TIM4
#define MOTORPWMPORT      GPIOD
#define MOTORPWMBIT        GPIO_Pin_12
#define MOTORPWMTIMBIT      GPIO_PinSource12


// Private typedefs ----------------------------------------------------------
GPIO_InitTypeDef     GPIO_InitStructureLED;
GPIO_InitTypeDef     GPIO_InitStructureTimer;
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
TIM_OCInitTypeDef    TIM_OCInitStructure;


// Private variables ---------------------------------------------------------
uint32_t TimerCounterClock = 0;
uint32_t TimerOutputClock = 0;
uint16_t PrescalerValue = 0;
uint32_t PulseDurationInMicroSeconds = 0;

int i;


// the prototypes ------------------------------------------------------------
int main(void);

// Timer init for PWM
void TimerInit(void);

void Delay(__IO uint32_t nCount);


int main(void)
{
  /*!< At this stage the microcontroller clock setting is already configured, 
     this is done through SystemInit() function which is called from startup
     file (startup_stm32f4xx.s) before to branch to application main.
     To reconfigure the default setting of SystemInit() function, refer to
      system_stm32f4xx.c file
  */

  // /dev/tty.usbserial-A900J1T0

  // call my new USART init
  usartInit();

  
  // call timer init for PWM
  TimerInit();


  // Timer base configuration
  //   Don't know why, but this code has to be here (not in a seperate method)
  TIM_TimeBaseStructure.TIM_Period = (uint16_t) (TimerCounterClock / TimerOutputClock);
  TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t) ((SystemCoreClock /2) / TimerCounterClock) - 1;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  // basic timer init
  TIM_TimeBaseInit(MOTORPWMTIMER, &TIM_TimeBaseStructure);

  // configure PWM mode and duration
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = PulseDurationInMicroSeconds; // set the duty cycle / pulse here!
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  TIM_OC1Init(MOTORPWMTIMER, &TIM_OCInitStructure);
  TIM_OC1PreloadConfig(MOTORPWMTIMER, TIM_OCPreload_Enable);

  // preload timer config
  TIM_ARRPreloadConfig(MOTORPWMTIMER, ENABLE);

  // enable timer / counter
  TIM_Cmd(MOTORPWMTIMER, ENABLE);


  //
  //  motor pwm test ! ! !
  //
  while(1)
  {
    for (i=1; i<70; i++)
    {
      Delay(0x03FFFF);
      TIM_Cmd(MOTORPWMTIMER, DISABLE);

      PulseDurationInMicroSeconds = i;

      TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
      TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
      TIM_OCInitStructure.TIM_Pulse = PulseDurationInMicroSeconds; // set the duty cycle / pulse here!
      TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
      TIM_OC1Init(MOTORPWMTIMER, &TIM_OCInitStructure);
      TIM_OC1PreloadConfig(MOTORPWMTIMER, TIM_OCPreload_Enable);

      TIM_ARRPreloadConfig(MOTORPWMTIMER, ENABLE);

      TIM_Cmd(MOTORPWMTIMER, ENABLE);
    }

    for (i=70; i>2; i--)
    {
      Delay(0x03FFFF);
      TIM_Cmd(MOTORPWMTIMER, DISABLE);

      PulseDurationInMicroSeconds = i;

      TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
      TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
      TIM_OCInitStructure.TIM_Pulse = PulseDurationInMicroSeconds; // set the duty cycle / pulse here!
      TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
      TIM_OC1Init(MOTORPWMTIMER, &TIM_OCInitStructure);
      TIM_OC1PreloadConfig(MOTORPWMTIMER, TIM_OCPreload_Enable);

      TIM_ARRPreloadConfig(MOTORPWMTIMER, ENABLE);

      TIM_Cmd(MOTORPWMTIMER, ENABLE);
    }
  }
}


/**
  * @brief  Configure the timer for PWM.
  * @param  None
  * @retval None
  */
void TimerInit(void)
{
  // set timer frequencies
  TimerCounterClock = 1000000; //  1 MHz
  TimerOutputClock = 10000;    // 10 kHz = 100 µs period

  // set pulse duration in mili seconds (HIGH time)
  // can be up to from 0 to 99 (due to a TimerOutputClock of 10 kHz)
  PulseDurationInMicroSeconds = 50;

  // Timer clock enable
  RCC_APB1PeriphClockCmd(MOTORPWMTIMCLOCK, ENABLE);

  // Port clock enable
  RCC_AHB1PeriphClockCmd(MOTORPWMPORTCLOCK, ENABLE);

  // Set PWM Port, Pin and method
  GPIO_InitStructureTimer.GPIO_Pin = MOTORPWMBIT;
  GPIO_InitStructureTimer.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructureTimer.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructureTimer.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructureTimer.GPIO_PuPd = GPIO_PuPd_UP ;
  GPIO_Init(MOTORPWMPORT, &GPIO_InitStructureTimer); 

  // Connect TIM pin to AF
  GPIO_PinAFConfig(MOTORPWMPORT, MOTORPWMTIMBIT, MOTORPWMAF);
}


/**
  * @brief  Delay Function.
  * @param  nCount:specifies the Delay time length.
  * @retval None
  */
void Delay(__IO uint32_t nCount)
{
  while(nCount--)
  {
  }
}


Ich hoffe, ich habe nichts vergessen hier rein zu kopieren...
Gib mir Bescheid, wenn es nicht läuft. Wie du am englischen Kommentar
siehst, funktioniert der Code innerhalb der main Methode komischerweise
nicht, wenn ich ihn in eine separate Funktion schiebe. Warum habe ich
noch nicht herausgefunden...

Das Beispiel aber läuft soweit gut. Das Delay muss natürlich auch nicht
sein. Nur der Vollständigkeit halber.

Gruß,

Markus

--
http://www.robotiklabor.de
http://www.direcs.de
Autor: Markus K. (markus_k64) Flattr this
Datum:

PS.:

Wenn nicht Channel 1 des Timers verwendet wird, müssen die Zeilen
      TIM_OC1Init(MOTORPWMTIMER, &TIM_OCInitStructure);
      TIM_OC1PreloadConfig(MOTORPWMTIMER, TIM_OCPreload_Enable);

natürlich angepasst werden. Für Channel 2 dann z.B.
      TIM_OC2Init(MOTORPWMTIMER, &TIM_OCInitStructure);
      TIM_OC2PreloadConfig(MOTORPWMTIMER, TIM_OCPreload_Enable);

Und so weiter...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel




Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder GIF-Format hochladen.
Siehe Bildformate

Mit dem Abschicken erkennst du die Nutzungsbedingungen an.

webmaster@mikrocontroller.netImpressumNutzungsbedingungenWerbung auf Mikrocontroller.net