Forum: Mikrocontroller und Digitale Elektronik AT90PWM Prescaler


von uCli (Gast)


Lesenswert?

Hallo zusammen!

Warum habe ich eine PWM-Frequenz von 63,5 kHz bei einem externen 16 MHz 
Quarz, wenn ich folgendes Register wie folgt beschreibe?


CLKPR = (1<<CLKPCE)|(0<<CLKPS3)|(1<<CLKPS2)|(1<<CLKPS1)|(1<<CLKPS0);
==> Prescaler = 128


Egal wie ich die Bits im Register verändere, ich erhalte immer ein 63,5 
kHz PWM-Signal!
==> der Prescaler ist ständig auf Divisor 1

Warum? Ich müsste doch mit CLKPR-Register, die PWM-Frequenz ändern 
können!?

Kann mir jemand helfen?

Vielen  DANK!

von spess53 (Gast)


Lesenswert?

Hi

>Warum? Ich müsste doch mit CLKPR-Register, die PWM-Frequenz ändern
>können!?

Kannst du auch. Aber zum Einstellen des Prescalers ist ein bestimmter 
Timing notwendig. Also noch mal Datenblatt lesen.

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

uCli schrieb:

> Kann mir jemand helfen?

Datenblattleser wissen mehr
1
To avoid unintentional changes of clock frequency, a special write
2
procedure must be followed to change the CLKPS bits:
3
1. Write the Clock Prescaler Change Enable (CLKPCE) bit to one and all
4
   other bits in CLKPR to zero.
5
2. Within four cycles, write the desired value to CLKPS while writing
6
   a zero to CLKPCE.

von uCli (Gast)


Lesenswert?

Hallo!

Vielen Dank für euere Antworten.
Leider funktioniert es noch nicht, kann mir jemand sagen, was ich in 
meinem Code falsch mache. Wo liegt der Fehler beim beschreiben des 
Prescaleregisters?

#include <avr/io.h>
#include <avr/interrupt.h>

//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 
xxxxxxxxxxxxxxx
// Ramp_Mode_Selection
  int ramp_mode = 0;    // Mode: 
4=Four_Ramp/2=Two_Ramp/1=One_Ramp/0=Center_Aligned

// Define_Times

  float DUTY_CYCLE;
  double PSC_CYCLE;
  double   DEAD_TIME_0;
  double   DEAD_TIME_1;
  double  ON_TIME_0;
  double  ON_TIME_1;
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 
xxxxxxxxxxxxxxxx



void init_pwm_values(void)
{


};

// PWM_Overlapping_Selection
void init_lapping(void)
{
  int pwm_overlapping = 0;   // Mode: 0=non_overlapping/1=overlapping

    if(pwm_overlapping == 1)
    {
    DEAD_TIME_0 = 50;
    ON_TIME_0 = 100;
    DEAD_TIME_1 = 75;
    ON_TIME_1 = 125;
    }
    else
    {
    DEAD_TIME_0 = 50;
    ON_TIME_0 = 75;
    DEAD_TIME_1 = 100;
    ON_TIME_1 = 125;
    }

}

// Power_Stage_Controll_2_Initalisation
void init_psc2(void)
{
  //PCNF2 = (0<<PCLKSEL2); // Slow_Clock_Input //CLK_I/O

  CLKPR = (1<<CLKPCE)|(0<<CLKPS3)|(0<<CLKPS2)|(0<<CLKPS1)|(0<<CLKPS0);

  CLKPR = (0<<CLKPCE)|(0<<CLKPS3)|(1<<CLKPS2)|(1<<CLKPS1)|(1<<CLKPS0);

  PSOC2 = (1<<POEN2A)|(1<<POEN2B);

  OCR2SA = DEAD_TIME_0;

  OCR2RA = ON_TIME_0;

  OCR2SB = DEAD_TIME_1;

  OCR2RB = ON_TIME_1;
}

// Ramp_Mode_Initialisation
void init_ramp_mode(void)
{
    switch (ramp_mode)
    {
      case 4:
      PCNF2 = (1<<PMODE21)|(1<<PCLKSEL2)|(1<<POP2); // Four_Ramp_Mode
      break;

      case 2:
      PCNF2 = (1<<PMODE20)|(1<<POP2); // Two_Ramp_Mode
      break;

      case 1:
      PCNF2 = (0<<PMODE21)|(0<<PMODE20)|(1<<POP2); // One_Ramp_Mode
      break;

      case 0:
      PCNF2 = (1<<PMODE21)|(1<<PMODE20)|(1<<POP2)|(0<<PCLKSEL2); // 
Center_Aligned_Mode // Slow_Clock_Input (PCLKSEL2 = 0)
      break;
    }
}

// Power_Stage_Controll_Input_Initialisation // page:167
void init_psc_input(void)
{
  PFRC2A = 0;
  PFRC2B = 0;
}

// PWM_Output_Selection
void init_pwm_out(void)
{
  //PCTL2 = (0<<PPRE21)|(0<<PPRE20); // No_Divider_On_PSC_Input_Clock

  PCTL2 = (1<<PRUN2); // PWM_Output_enable
}

int main(void)
{

  //init_pwm_values();
  init_lapping(); // Exclude_from_build_for_defining_divergent_times
  init_psc2();
  init_ramp_mode();
  init_psc_input();
  init_pwm_out();

    while(1)
    {
    }


}

Wäre nett, wenn mir jemand weiterhelfen könnte!

Danke!

Gruß

von Karl H. (kbuchegg)


Lesenswert?

1
void init_psc2(void)
2
{
3
  //PCNF2 = (0<<PCLKSEL2); // Slow_Clock_Input //CLK_I/O
4
5
  CLKPR = (1<<CLKPCE)|(0<<CLKPS3)|(0<<CLKPS2)|(0<<CLKPS1)|(0<<CLKPS0);
6
7
  CLKPR = (0<<CLKPCE)|(0<<CLKPS3)|(1<<CLKPS2)|(1<<CLKPS1)|(1<<CLKPS0);

sieh dir mal im Assemblerlisting an, was der Compiler da drauss macht. 
Da hier das Timing kritisch ist, ist es unabdingbar dass er hier eine 
kurze Sequenz daraus generiert, ohne viel Schnörkel.

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.