Forum: Digitale Signalverarbeitung / DSP / Machine Learning PWM Registerwerte TMS320F28335


von Max0804 (Gast)


Lesenswert?

Hallo!
Ich bin gerade dabei eine einfach PWM zu realisieren.
Die DSP läuft mit 150 Mhz und ich habe den Systemclock für die PWM mit 
15 vorgeteilt.
Welchen Wert im TBPRD Register muss man denn da reinladen?
Die Initialisierung sieht so aus:

   EALLOW;
   SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;      // Stop all the TB clocks
   EDIS;
   // Setup Sync
   EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN;  // Pass through


   // Allow each timer to be sync'ed

   EPwm1Regs.TBCTL.bit.PHSEN = TB_ENABLE;

   //Phase
   EPwm1Regs.TBPHS.half.TBPHS = 0;


   //Clock div 15;
   EPwm1Regs.TBCTL.bit.HSPCLKDIV=5;
   EPwm1Regs.TBCTL.bit.CLKDIV=3;



   EPwm1Regs.TBPRD = 18750;
   EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;    // Count up
   EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;     // Select INT on Zero 
event
   EPwm1Regs.ETSEL.bit.INTEN = PWM1_INT_ENABLE;  // Enable INT
   EPwm1Regs.ETPS.bit.INTPRD = ET_1ST;           // Generate INT on 1st 
event


   EALLOW;
   SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;         // Start all the 
timers synced
   EDIS;

Mit dem Wert TBPRD = 18750 läuft die PWM mit exakt 10 ms. So wie 
gewollt. Aber warum gerade der Wert? Habe das Manual gelesen (SPRU791F) 
da steht eine Formel drin (TPWM = (TBPRD + 1) x TTBCLK) aber die passt 
irgendwie nicht zu dem Wert vom TBPRD. Ist die Formel falsch, oder mache 
ich da einen Denkfehler?
Hoffe jemand bringt da bei mir Licht ins Dunkel! ;)

Viele Grüße
Max

von gerd (Gast)


Lesenswert?

Max0804 schrieb:
> //Clock div 15;
>    EPwm1Regs.TBCTL.bit.HSPCLKDIV=5;
>    EPwm1Regs.TBCTL.bit.CLKDIV=3;

Es ist zwar schon eine ganze Weile her, aber ich glaube so ging das 
nicht. HSPCLKDIV kann - meine ich - nicht den Wert 5 annehmen. Im 
Binaermuster wäre das 101 ... das wird im Teiler irgendwas mit 10 sein 
vermute ich.
Gleiches gilt für CLKDIV... 3 gibt es so nicht. Das sind Binaer 011 und 
dürfte vom Teiler wohl bei 8 sein. Das heisst du teilst nicht durch 15 
sondern durch 8 * 10 = 80

Vermutlich liegt da dein Fehler.

Ich würde dir empfehlen Magic Numbers zu vermeiden. Benutze doch die 
freundlicherweise von TI mitgelieferten Definitions... glaube TB_DIV1 
u.s.w.
Dannn kommt es nicht zu solchen Fehlern.

- gerd

von gerd (Gast)


Lesenswert?

Gerade nochmal nachgerechnet... was ich oben geschrieben habe stimmt so. 
Es kommt auch deine PWM-Periodendauer raus. Du teilst die 150 MHz System 
takt nicht durch 15 sondern durch 80.

- gerd

von Max0804 (Gast)


Lesenswert?

gerd schrieb:
> Gerade nochmal nachgerechnet... was ich oben geschrieben habe stimmt so.
> Es kommt auch deine PWM-Periodendauer raus. Du teilst die 150 MHz System
> takt nicht durch 15 sondern durch 80.

Es passt. Dankeschön. Bin normalerweise immer in BIN unterwegs. Doch 
heute morgen dachte ich mir, machen wir mal "schnell", und solche Fehler 
entstehen leider dabei! :(

Nochmals vielen Dank!


Grüße
Max

von Max0804 (Gast)


Lesenswert?

Hallo!
Gibt es eine Möglichkeit die PWM-Pins umzulegen? Über Mux scheint es 
laut Datenblatt (Tabelle) nicht zu funktionieren!
Soll man bei Statusänderung (Also PWM-Signal low=> high und high => low) 
einen GPIO Toggeln, oder wie wird das bei dem Controller gemacht?

Viele Grüße

von gerd (Gast)


Lesenswert?

Die eigentlichen "PWM-Pins" sind meines Wissens nach fest. Sicherlich 
kann man über einen entsprechenden Interrupt auch eine akurate 
Workaround-Lösung für andere Pins hinbekommen (selbst habe ich das aber 
nie ausprobiert).

- gerd

von Max0804 (Gast)


Lesenswert?

gerd schrieb:
> Sicherlich
> kann man über einen entsprechenden Interrupt auch eine akurate
> Workaround-Lösung für andere Pins hinbekommen (selbst habe ich das aber
> nie ausprobiert).

Habe ich bereits versucht, also die GPIOs in der ISR der PWM zu toggeln. 
Allerdings entstehen dann signale mit einem Duty-Cycle von 50%.
Kann es sein, das man da über die Action-Register irgendwie ran kommt? 
Möchte nämlich keine Lösung, bei der man die Registerwerte in der ISR 
ändern muss.

Viele Grüße

von gerd (Gast)


Lesenswert?

Puh, das sind Sachen die ich nichtmehr ganz im Gedächnis habe.
Ich meine mich zu erinnern, dass man mit dem "Action Qualifier" oder 
so ähnlich (kann auch ein ganz anderes Register gewesen sein - wie 
gesagt, alles nur aus dem Gedächnis) die Interrupt-Auslösemechanismen 
festlegen kann. Sprich du kannst bei "Compare on match" als auch bei 
"Zero" einen Interrupt auslösen. Damit sollte sich dann das eigentliche 
PWM-Signal 1:1 abbilden lassen (so die Theorie).

- gerd

von gerd (Gast)


Lesenswert?

Ok, das hat mir nu keine Ruhe gelassen und ich hab nochmal im Dokument 
spru791f.pdf nachgeschaut. Der Event Trigger ist dein Freund! Siehe 
Kapitel 2.8 Seite 64ff.

- gerd

von Micha (Gast)


Lesenswert?

Max0804 schrieb:
> Habe ich bereits versucht, also die GPIOs in der ISR der PWM zu toggeln.
> Allerdings entstehen dann signale mit einem Duty-Cycle von 50%.
> Kann es sein, das man da über die Action-Register irgendwie ran kommt?
> Möchte nämlich keine Lösung, bei der man die Registerwerte in der ISR
> ändern muss.
Du musst mit mehreren Interrupts arbeiten wenn du das so lösen möchtest. 
Sinnvoller/Einfacher/Flexibler/Performanter ist es allerdings die 
entsprechenden Pins zu nehmen.

von Max0804 (Gast)


Lesenswert?

gerd schrieb:
> Ok, das hat mir nu keine Ruhe gelassen und ich hab nochmal im Dokument
> spru791f.pdf nachgeschaut. Der Event Trigger ist dein Freund! Siehe
> Kapitel 2.8 Seite 64ff.

Danke Gerd! Falls jemand ein ähnliches Problem hat, habe es jetzt so 
gelöst:

In der Initialisierung:
1
void InitEPwmTimer()
2
{
3
.....
4
5
6
   EPwm1Regs.ETSEL.bit.INTSEL = ET_CTRD_CMPA;     // Select INT CMPA event
7
   EPwm1Regs.ETSEL.bit.INTEN = 0x1;               // Enable INT
8
   EPwm1Regs.ETPS.bit.INTPRD = ET_1ST;            // Take the first Event
9
.....
10
}

In der PWM_ISR:
1
// Interrupt routine for PWM1
2
interrupt void epwm1_timer_isr(void)
3
{
4
  
5
....  
6
 EPwm1TimerIntCount++;
7
   
8
   // Toggle Pin 16
9
   GpioDataRegs.GPATOGGLE.bit.GPIO16=1;
10
11
   // Set different INT-Trigger-Values
12
   if(EPwm1Regs.ETSEL.bit.INTSEL == ET_CTRD_CMPA)
13
   {
14
      EPwm1Regs.ETSEL.bit.INTSEL = ET_CTRU_CMPA;
15
   }
16
   else
17
   {
18
      EPwm1Regs.ETSEL.bit.INTSEL = ET_CTRD_CMPA;
19
   }
20
   
21
   // Clear INT flag for this timer
22
    EPwm1Regs.ETCLR.bit.INT = 1;
23
24
   // Acknowledge this interrupt to receive more interrupts from group 3
25
   PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
26
.....
27
}

Denke nicht das es die "feine Art" ist, aber es funktioniert.

Danke euch allen!

Viele Grüße
Max

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.