www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AT32UC3A0512-UES PWM Update Problem


Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin,

ich nutze zurzeit einen AT32UC3A0512-UES auf einem EVK1100. Ich möchte 
eigentlich nur die Spannung die ich per PWM rausgebe (benutze PWM als 
Analogausgang) im Betrieb verändern. Dazu habe ich mir folgendes 
gebastelt, was auch funktioniert.
static float V = 1.5;

int update_pwm1(void)
{
  int tmp = (int)((V-3.27)/-0.00308);


  if(tmp < 1)
  {
    tmp = 1;
  }
  else if(tmp > 1023)
  {
    tmp = 1023;
  }


  avr32_pwm_channel_t pwm_channel = { .ccnt = 0 };  // One channel config.

  pwm_channel.CMR.calg = PWM_MODE_LEFT_ALIGNED;       // Channel mode.
  pwm_channel.CMR.cpol = PWM_POLARITY_LOW;            // Channel polarity.
  pwm_channel.CMR.cpd = PWM_UPDATE_DUTY;              // Not used the first time.
  pwm_channel.CMR.cpre = AVR32_PWM_CPRE_MCK;       // Channel prescaler.
  pwm_channel.cdty = 1;   // Channel duty cycle, should be < CPRD.
  pwm_channel.cprd = 1024;  // Channel period.
  pwm_channel.cupd = tmp;

  return pwm_sync_update_channel(1, &pwm_channel);
}

int main(void)
{
  // Switch main clock to external oscillator 0 (crystal).
  pm_switch_to_osc0(&AVR32_PM, FOSC0, OSC0_STARTUP);

  init_pwm1();

  update_pwm1();

  while(1);
}

Was mich jetzt aber extremst verwirrt ist, dass folgende zwei Varianten 
nicht funktionieren und ich absolut keine warum.

Geht nicht:
static volatile float V = 1.5;

int update_pwm1(void)
{
  int tmp = (int)((V-3.27)/-0.00308);


  if(tmp < 1)
  {
    tmp = 1;
  }
  else if(tmp > 1023)
  {
    tmp = 1023;
  }


  avr32_pwm_channel_t pwm_channel = { .ccnt = 0 };  // One channel config.

  pwm_channel.CMR.calg = PWM_MODE_LEFT_ALIGNED;       // Channel mode.
  pwm_channel.CMR.cpol = PWM_POLARITY_LOW;            // Channel polarity.
  pwm_channel.CMR.cpd = PWM_UPDATE_DUTY;              // Not used the first time.
  pwm_channel.CMR.cpre = AVR32_PWM_CPRE_MCK;       // Channel prescaler.
  pwm_channel.cdty = 1;   // Channel duty cycle, should be < CPRD.
  pwm_channel.cprd = 1024;  // Channel period.
  pwm_channel.cupd = tmp;

  return pwm_sync_update_channel(1, &pwm_channel);
}

int main(void)
{
  // Switch main clock to external oscillator 0 (crystal).
  pm_switch_to_osc0(&AVR32_PM, FOSC0, OSC0_STARTUP);

  init_pwm1();

  update_pwm1();

  while(1);
}

Geht auch nicht:
//static float V = 1.5;

int update_pwm1(float V)
{
  int tmp = (int)((V-3.27)/-0.00308);


  if(tmp < 1)
  {
    tmp = 1;
  }
  else if(tmp > 1023)
  {
    tmp = 1023;
  }


  avr32_pwm_channel_t pwm_channel = { .ccnt = 0 };  // One channel config.

  pwm_channel.CMR.calg = PWM_MODE_LEFT_ALIGNED;       // Channel mode.
  pwm_channel.CMR.cpol = PWM_POLARITY_LOW;            // Channel polarity.
  pwm_channel.CMR.cpd = PWM_UPDATE_DUTY;              // Not used the first time.
  pwm_channel.CMR.cpre = AVR32_PWM_CPRE_MCK;       // Channel prescaler.
  pwm_channel.cdty = 1;   // Channel duty cycle, should be < CPRD.
  pwm_channel.cprd = 1024;  // Channel period.
  pwm_channel.cupd = tmp;

  return pwm_sync_update_channel(1, &pwm_channel);
}

int main(void)
{
  // Switch main clock to external oscillator 0 (crystal).
  pm_switch_to_osc0(&AVR32_PM, FOSC0, OSC0_STARTUP);

  init_pwm1();

  update_pwm1(1.5);

  while(1);
}

Bei den unteren beiden Varianten bleibt die Spannung auf dem Wert, den 
sie nach init_pwm1() bereits hat und ändert sich nicht auf ~1,5V.

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK nun ist die Verwirrung komplett. Anscheinend ist es dem µC nicht 
möglich, zur Laufzeit berechnete float-Werte in einen Integer zu casten.
int update_pwm1(int V)
{
  char buf[16];
  float f_tmp;
  int tmp;

  f_tmp = (((((float)V)/1000)-3.27)/-0.00308);

  usart_write_line(EXAMPLE_USART, "\n VOR tmp = (int)f_tmp; \n");
  tmp = (int)f_tmp;
  usart_write_line(EXAMPLE_USART, "\n NACH tmp = (int)f_tmp; \n");
  ...
}

Die Ausgabe vor dem Cast kommt, die nach_ dem Cast aber _nicht mehr.

Änder ich die Berechnung auf Fixpunkt, also
tmp = ((mV*100-327000)/-308);
dann funktioniert es.


Also Problem gelöst, Verwirrung bleibt!

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
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.