Forum: Mikrocontroller und Digitale Elektronik AT91SAM7S Multichannel-PWM


von Max (Gast)


Lesenswert?

Hallo.
Ich habe folgendes Problem. Ich benutze 2 PWM-Kanäle. Mit einem wird ein
Motor betrieben mit dem andren erfolgt eine Sinusausgabe. Sobald beide
Kanäle aktiv sind halbiert sich die Sinusfrequenz. Wenn aber nur der
Sinus-PWM-Kanal läuft, ist die Sinusfrequenz OK. Hier der Quellcode:

in main:
1
 
2
PWM_Init(MOTOR_PWM);
3
PWM_Init(SINE_PWM);


in PWM.c :
1
void PWM_Init(unsigned int channel)
2
{   
3
    // Enable Periphal clock in PMC for PWMC
4
    AT91F_PWMC_CfgPMC();
5
    
6
    // Configure PIO controllers to drive PWM signals
7
    AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA,          
8
                     ((unsigned int) AT91C_PA0_PWM0) |  
9
                     ((unsigned int) AT91C_PA1_PWM1) |      
10
                     ((unsigned int) AT91C_PA2_PWM2),  
11
         ((unsigned int) AT91C_PA7_PWM3));   
12
    switch (channel)
13
    {
14
     // Motor PWM
15
     case 0:  // Stop PWM Channel 0
16
     AT91F_PWMC_StopChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0);
17
     AT91C_BASE_PWMC_CH0->PWMC_CMR = MCKtoPWM | CPD_OFF | CPOL_ON | CALG_ON;
18
19
     // setup the period registers
20
     AT91C_BASE_PWMC_CH0->PWMC_CPRDR = P_MOTOR;
21
22
     // setup the duty cycle registers (first value)
23
     AT91C_BASE_PWMC_CH0->PWMC_CDTYR = P_MOTOR/3;
24
25
     //enable PWM channel 0
26
     AT91F_PWMC_StartChannel( AT91C_BASE_PWMC, AT91C_PWMC_CHID0);
27
     break;
28
  
29
     // PWM  (sine wave)
30
     case 1: // Stop PWM Channel 1
31
     AT91F_PWMC_StopChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID1);
32
      
33
     // setup sine wave
34
     //PWM_InitSinewave();
35
36
     // setup the channel mode registers
37
     AT91C_BASE_PWMC_CH1->PWMC_CMR = MCKtoPWM | CPD_OFF | CPOL_ON | CALG_ON;
38
39
     // setup the period registers
40
     AT91C_BASE_PWMC_CH1->PWMC_CPRDR = EXT_OSC / SINE.PWMFREQ1 / 2;
41
42
     // setup the duty cycle registers (first value)
43
     AT91C_BASE_PWMC_CH1->PWMC_CDTYR = EXT_OSC / SINE.PWMFREQ1 / 4;
44
45
     // Prevent any bad state of this register: Read it clear all set bit
46
     AT91C_BASE_PWMC->PWMC_ISR;
47
48
     AT91F_AIC_ConfigureIt(AT91C_BASE_AIC,
49
                           AT91C_ID_PWMC,
50
                           AT91C_AIC_PRIOR_HIGHEST,
51
                           AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,
52
                           PWM_Interrupt);
53
   
54
     AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_PWMC);  
55
     //enable PWM channel 1
56
     AT91F_PWMC_StartChannel( AT91C_BASE_PWMC, AT91C_PWMC_CHID1 );
57
    
58
     AT91F_PWMC_InterruptEnable(AT91C_BASE_PWMC,AT91C_PWMC_CHID1);
59
     break;
60
    }
61
}


Wo könnte das Problem liegen? Wie gesagt wenn nur der Sinuskanal aktiv
ist ist die Sinusfrequenz richtig.

von Philipp A. (st0ne)


Lesenswert?

hi,

ich weiß zwar leider das problem nicht warums nicht geht, aber du 
könntest mir nicht den gesammten source zukommen lassen? oder zumindest 
den teil für die pwm-sinus generation mit sinus tabelle? da ich genau 
das mit einem at91sam7 machen möchte :-)

danke
gruß st0ne

von Max (Gast)


Lesenswert?

gibt es denn beim multichannelbetrieb was besonderes zu beachten?


@ Phil Nachname
1
void PWM_Interrupt(void) 
2
{
3
  static unsigned int cnt=0;
4
5
    // update PWM Register
6
        AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, SINE_PWM, SINE.TABLE_1[cnt]);
7
      // It is forbidden to continue before updating of the PWM period
8
      while(AT91C_BASE_PWMC->PWMC_ISR != AT91C_PWMC_CHID1); 
9
      cnt++;
10
11
  if (cnt == SINE.SAMPLES)
12
  {
13
    cnt = 0;
14
  }
15
}
1
void PWM_InitSinewave(void)
2
{
3
  unsigned char i;
4
  double helpFreq1;
5
6
  SINE.PWMFREQ1 = (SINE.FREQ1 * SINE.SAMPLES);  // [Hz] - sinewave 1 with n sampling points
7
8
  for(i=0; i<SINE.SAMPLES; i++) //SINE.SAMPLES=13 also 13 unterschiedliche Tastverhältnisse
9
   {
10
    helpFreq1=((2*PI*SINE.FREQ1)/SINE.PWMFREQ1)*i;
11
   SINE.TABLE_1[i]=(SINE.GAIN/100)*(sin(helpFreq1)+1)*0.5*((EXT_OSC/SINE.PWMFREQ1)/2);
12
   }  
13
}

von Max (Gast)


Angehängte Dateien:

Lesenswert?

Das Problem mit der halben Frequenz wurde behoben.
Jetzt gibt es aber ein anderes Problem.
Also ich benutze 4-PWM-Kanäle PA0(LED), PA1(Sinus), PA2(LED) und
PA7(Motor).
Das Sinussignal wird mit Interrupts erzeugt. D.h. es wird immer ein Wert
der Sinustabelle während des PWM-Interrupts in das CUPDR-Register
geschrieben(Code ist im Anhang).
Dabei tritt bei mir folgendes Problem auf: wenn alle PWM-Kanäle (oder
sogar wenn 2) aktiv sind zittert das Sinussignal. Wenn aber nur der
Sinus-PWM-Kanal aktiviert ist, ist  der Sinus stabil.
In Interruptroutine habe ich ein Triggersignal(PA15) für den Oszilloskop
integriert. Diesem ist anzusehen, dass es auch zittert. Daraus schliesse
ich, dass es beim Interruptaufruf Unregelmäßigkeiten gibt.
Dann stellt sich aber die Frage warum beim Einkanalbetrieb(Sinus) alles
stabil ist? Vielleicht ist meine PWM-Initialisierung nicht richtig? Habe
alles schon etliche Male überprüft.

von Philipp A. (st0ne)


Lesenswert?

ich nehme mal an das wohl die unterbrechung der interrupts das jittern 
erzeugen...? ich habs momentan mal geschafft die pwm zu initialisieren 
und bin gerade dabei die sinuswerte zu implementieren, sollte heute 
abend dann funktionieren...
da ich auch 2 pwm's benötige, kann ich das auch gleich austesten...

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.