Forum: Mikrocontroller und Digitale Elektronik atmega32: Wie ging gleich nochmal PWM mit veränderlichem T


von PWMBastler (Gast)


Lesenswert?

Liebes Forum,


ich benötige für eine Versuchsschaltung ein PWM Signal, bei dem nicht 
nur der Dutycycle (t_on/T) sondern auch die Länge der PWM Periode T im 
Programmablauf dynamisch verändert werden kann.


Leider funktioniert unten angehängter Codeschnipsel nur für 
T=ICR1=const, sobald ich ICR1 im Programm ändere, gibt es Aussetzer im 
PWM Signal, also mache ich irgendetwas falsch 
(Wertebereichsüberscheitung für ICR1 habe ich bereits ausgeschlossen).

Und ich kann mich nicht mehr erinnern, wie ich das damals programmiert 
habe.


Könnt Ihr mir auf die Sprünge helfen? Gibt es vielleicht etwas Fertiges, 
dass ich übernehmen und anpassen kann?



Der Code ist im Arduinostyle, die Funktion setup(){} wird nur einmal 
ausgeführt, loop(){} endlos, PWM Takt=T ist ca. zwischen 4us und 200us:


....
volatile int Set_TCNT3L;  // Variable zum Setzen des Registers TCNT3L
volatile int Set_TCNT3H;  // Variable zum Setzen des Registers TCNT3H


ISR(TIMER3_OVF_vect) {
  TCNT3H = Set_TCNT3H;
  TCNT3L = Set_TCNT3L;
};

void setup()
{

  cli();
  TCCR1A = _BV(COM1A1) | _BV(COM1A0) | _BV(WGM11);
  TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);

  TCCR3A = 0;
  TCCR3B = 2;
  TIMSK3 = (1 << TOIE3); // enable TCNT3 overflow

  sei();

  ICR1 = 200; //Periodenlänge T der PWM, 16Bit Register, default-Wert, 
100=160Khz, 200=80kHz
  OCR1A = wert_von_OCR1A;  // On-Zeit t1 der PWM, 16 Bit Register, 
default-Wert
  Set_TCNT3H = 255; //Setze H-Byte zuerst
  Set_TCNT3L = 0x00;


}


void loop() {

  // Berechnung von t_on und T
  t_on = int(irgendeinefunnktion());
  t_off = int(eineandereFunktion());
  T = t_on + t_off;

  ICR1 = T;      // Setzen der Register ICR1 bestimmt T

  OCR1A = t_off; // OCR1A bestimmt t_off
}

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

PWMBastler schrieb:
> T=ICR1=const, sobald ich ICR1 im Programm ändere

Wenn TCNT schon grösser ist als dein neues ICR, dann läuft der Timer bis 
MAX, um erst im nächsten Durchlauf das neue ICR als MAX zu akzeptieren.
Du darfst ICR also nur setzen, solange TCNT < ICR.
Ein geeignter Ort fürs Setzen von ICR wäre z.B. die Timer-Overflow 
Routine, denn dort ist TCNT sehr niedrig.
Leider schreibst du ja nicht, welcher MC denn nun benutzt wird, weitere 
Tipps sind also erstmal nicht möglich.

PWMBastler schrieb:
> volatile int Set_TCNT3L;  // Variable zum Setzen des Registers TCNT3L
> volatile int Set_TCNT3H;  // Variable zum Setzen des Registers TCNT3H

int ist hier nicht der richtige Datentyp. Entweder setzt du TCNT3 
zusammen als int, oder jede Hälfte des Timers mit z.B. uint8_t.

Das ist nämlich mit GCC erlaubt:
1
TCNT3 = meinintwert;
Um die Bytereihenfolge kümmert sich der Compiler.

: Bearbeitet durch User
von PWMBastler (Gast)


Lesenswert?

Matthias S. schrieb:
> Wenn TCNT schon grösser ist als dein neues ICR, dann läuft der Timer bis
> MAX, um erst im nächsten Durchlauf das neue ICR als MAX zu akzeptieren.
> Du darfst ICR also nur setzen, solange TCNT < ICR.
> Ein geeignter Ort fürs Setzen von ICR wäre z.B. die Timer-Overflow
> Routine, denn dort ist TCNT sehr niedrig.
> Leider schreibst du ja nicht, welcher MC denn nun benutzt wird, weitere
> Tipps sind also erstmal nicht möglich.

Aha! okay, ich werde das gleich mal prüfen!

Es ist ein atmega32U4 mit 16MHz

Feedback nach dem Test, PWMBastler

von Stefan F. (Gast)


Lesenswert?

> Leider schreibst du ja nicht, welcher MC denn nun benutzt wird

Der Titel des Threads lautet:

> atmega32: Wie ging gleich nochmal PWM mit veränderlichem T
> Es ist ein atmega32U4 mit 16MHz

Aber hallo, zwischen ATmega32 und ATmega32u4 gibt es große Unterschiede! 
Warum hast du das nicht gleicht im Eröffnungs-Thread geschrieben?

von PWMBastler (Gast)


Lesenswert?

Hallo Stephan,

mist das mit dem Atmega32 != atmega32u4, tut mir leid, dass ich mich so 
unklar ausgedrückt habe.

Danke an Matthias,


ich versuche mich mal im Reengeneering, weil ich meinen Code nicht mehr 
verstehe, ich benutze dazu 
http://www.avrbeginners.net/architecture/timers/timers.html, Abschnitt 
"PWM Mode" und das Data Sheet atmega32u4

Register TCCR1A: COM1A1, COM1A0 und WGM11 sind gesetzt, was bedeutet 
das?
COM1A0 ist bit 7
COM1A1 ist bit 6
wenn beide gesetzt sind, dann bedeutet das "noninverting PWM"
WGM11  ist bit 1
Das bedeutet, dass der PWM Takt eine Auflösung von 9-Bit hat

Register TCCR1B: WGM13, WGM12 und CS10 sind gesetzt.
WGM13 ist bit 4
WMG12 ist bit 3 --> bit 4 und bit 3 gesetzt = Mode 12=CTC Mode= Clear 
Timer on Compare Mode
CS10  ist bit 1 --> Prescaler = 1

TCNT1 scheint ein Counter zu sein, der hoch zählt. Wenn er den Wert von 
OCR1A erreicht hat, wird er zu null gesetzt, okay, das muß dann wohl die 
off-Zeit bestimmen.

Wie ICR1 das mit rein spielt, ist mir leider nicht klar geworden.

ich recherchiere weiter, Danke, PWMBastler

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Stefan U. schrieb:
> Warum hast du das nicht gleicht im Eröffnungs-Thread geschrieben?

Darüber bin ich ja auch gestolpert - Der Mega32 hat gar keinen Timer 3, 
deswegen die Nachfrage, welcher MC es denn nun wirklich ist.

: Bearbeitet durch User
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.