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


von Tobi (Gast)


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.
1
static float V = 1.5;
2
3
int update_pwm1(void)
4
{
5
  int tmp = (int)((V-3.27)/-0.00308);
6
7
8
  if(tmp < 1)
9
  {
10
    tmp = 1;
11
  }
12
  else if(tmp > 1023)
13
  {
14
    tmp = 1023;
15
  }
16
17
18
  avr32_pwm_channel_t pwm_channel = { .ccnt = 0 };  // One channel config.
19
20
  pwm_channel.CMR.calg = PWM_MODE_LEFT_ALIGNED;       // Channel mode.
21
  pwm_channel.CMR.cpol = PWM_POLARITY_LOW;            // Channel polarity.
22
  pwm_channel.CMR.cpd = PWM_UPDATE_DUTY;              // Not used the first time.
23
  pwm_channel.CMR.cpre = AVR32_PWM_CPRE_MCK;       // Channel prescaler.
24
  pwm_channel.cdty = 1;   // Channel duty cycle, should be < CPRD.
25
  pwm_channel.cprd = 1024;  // Channel period.
26
  pwm_channel.cupd = tmp;
27
28
  return pwm_sync_update_channel(1, &pwm_channel);
29
}
30
31
int main(void)
32
{
33
  // Switch main clock to external oscillator 0 (crystal).
34
  pm_switch_to_osc0(&AVR32_PM, FOSC0, OSC0_STARTUP);
35
36
  init_pwm1();
37
38
  update_pwm1();
39
40
  while(1);
41
}

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

Geht nicht:
1
static volatile float V = 1.5;
2
3
int update_pwm1(void)
4
{
5
  int tmp = (int)((V-3.27)/-0.00308);
6
7
8
  if(tmp < 1)
9
  {
10
    tmp = 1;
11
  }
12
  else if(tmp > 1023)
13
  {
14
    tmp = 1023;
15
  }
16
17
18
  avr32_pwm_channel_t pwm_channel = { .ccnt = 0 };  // One channel config.
19
20
  pwm_channel.CMR.calg = PWM_MODE_LEFT_ALIGNED;       // Channel mode.
21
  pwm_channel.CMR.cpol = PWM_POLARITY_LOW;            // Channel polarity.
22
  pwm_channel.CMR.cpd = PWM_UPDATE_DUTY;              // Not used the first time.
23
  pwm_channel.CMR.cpre = AVR32_PWM_CPRE_MCK;       // Channel prescaler.
24
  pwm_channel.cdty = 1;   // Channel duty cycle, should be < CPRD.
25
  pwm_channel.cprd = 1024;  // Channel period.
26
  pwm_channel.cupd = tmp;
27
28
  return pwm_sync_update_channel(1, &pwm_channel);
29
}
30
31
int main(void)
32
{
33
  // Switch main clock to external oscillator 0 (crystal).
34
  pm_switch_to_osc0(&AVR32_PM, FOSC0, OSC0_STARTUP);
35
36
  init_pwm1();
37
38
  update_pwm1();
39
40
  while(1);
41
}

Geht auch nicht:
1
//static float V = 1.5;
2
3
int update_pwm1(float V)
4
{
5
  int tmp = (int)((V-3.27)/-0.00308);
6
7
8
  if(tmp < 1)
9
  {
10
    tmp = 1;
11
  }
12
  else if(tmp > 1023)
13
  {
14
    tmp = 1023;
15
  }
16
17
18
  avr32_pwm_channel_t pwm_channel = { .ccnt = 0 };  // One channel config.
19
20
  pwm_channel.CMR.calg = PWM_MODE_LEFT_ALIGNED;       // Channel mode.
21
  pwm_channel.CMR.cpol = PWM_POLARITY_LOW;            // Channel polarity.
22
  pwm_channel.CMR.cpd = PWM_UPDATE_DUTY;              // Not used the first time.
23
  pwm_channel.CMR.cpre = AVR32_PWM_CPRE_MCK;       // Channel prescaler.
24
  pwm_channel.cdty = 1;   // Channel duty cycle, should be < CPRD.
25
  pwm_channel.cprd = 1024;  // Channel period.
26
  pwm_channel.cupd = tmp;
27
28
  return pwm_sync_update_channel(1, &pwm_channel);
29
}
30
31
int main(void)
32
{
33
  // Switch main clock to external oscillator 0 (crystal).
34
  pm_switch_to_osc0(&AVR32_PM, FOSC0, OSC0_STARTUP);
35
36
  init_pwm1();
37
38
  update_pwm1(1.5);
39
40
  while(1);
41
}

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.

von Tobi (Gast)


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.
1
int update_pwm1(int V)
2
{
3
  char buf[16];
4
  float f_tmp;
5
  int tmp;
6
7
  f_tmp = (((((float)V)/1000)-3.27)/-0.00308);
8
9
  usart_write_line(EXAMPLE_USART, "\n VOR tmp = (int)f_tmp; \n");
10
  tmp = (int)f_tmp;
11
  usart_write_line(EXAMPLE_USART, "\n NACH tmp = (int)f_tmp; \n");
12
  ...
13
}

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

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


Also Problem gelöst, Verwirrung bleibt!

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.