PWM mit PIC12F1501

OP #7901436
Lesenswert?

Hallo zusammen, ich steh völlig an...

Auch werd ich aus dem Datenblatt nicht schlau oder ich übersehe etwas. Ich möchte den Hardware PWM Ausgang von 1% bis 99% ansteigen lassen (vorerst nur zum testen).

Fast alles passt: PWM Frequenz stimmt mit der Berechnung (512µs) Aus irgendeinem Grund wird mein PWM Signal nie länger als ca. 100µs !!

Wenn ich einen fixen Wert einstelle passt alles (also ohne den duty zu erhöhen oder zu verändern). Da sind von 1% bis 99% konstant möglich.

Irgendwie nimmt er immer den ersten Startwert - inkrementiert und nach 100µS startet er wieder bei 512 (Hab es mit mehreren Weren getestet - immer gleiches Verhalten)

Ich hab keine Ahnung mehr...

Ich hoffe es kann mir jemand helfen, will es eher nicht mit SW PWM lösen. Danke und Grüße, Klaus

Hier der Code:

#include <xc.h>

#define _XTAL_FREQ 8000000

unsigned int duty = 512;

void init(void);

void main(void) { init(); while (1) {
duty++; __delay_ms(10); if (duty > 1023)duty = 0;
PWM1DCH = duty >> 2; PWM1DCL = (duty & 0x03) << 6; } }

void init(void) { OSCCON = 0b01110010; //Intern 8Mhz T2CON = 0b00000101; //T2 on, Prescaler = 1:4 PR2 = 0xFF; //

1
TRISAbits.TRISA2 = 0;
2
PWM1CON = 0b11000000;
3
PWM1DCH = duty >> 2;
4
PWM1DCL = (duty & 0x03) << 6;
5
T2CONbits.TMR2ON = 1;

}

Angehängte Dateien:
#7901446
Lesenswert?

Bin keine Experte, aber:

  • versuche mal High and Low zu vertauschen. Bei manchen PICs waren Timers so, dass man die reihenfolge richtig machen musste. Wobei das war eher bei lesen. Meine ich.
  • Versuche nur den High zu schreiben. Lass den low auf 0. Funktioniert es so? Schreibe mal da nur feste werte und probiere aus was passiert.
#7901450
Lesenswert?

Könnte noch etwas mit den PIN interagieren? ADC eingang abgeschaltet? War bei anderen PICs immer nerfig.

Guck mal in den Datasheet, da steht welche features noch auf dem PIN liegen. Gucke mal durch ob nicht manchen davon ab reset by default enabled sind.

RA2 5 AN2 DACOUT2 C1OUT T0CKI CWG1A CWG1FLT CLC1

#7901452
Lesenswert?

Andras H. schrieb:

Guck mal in den Datasheet, da steht welche features noch auf dem PIN liegen. Gucke mal durch ob nicht manchen davon ab reset by default enabled sind.

Wichtig ist auch das RxyPPS (also RA2PPS) Register, bei dem man den Timer-Ausgang auf einen Pin legen muss:

https://onlinedocs.microchip.com/oxy/GUID-20DC4AC0-78C3-43D4-B405-15D8B752B254-en-US-3/GUID-B6C0BEDD-12B4-491C-B6CE-052CF7FF2360.html#GUID-B6C0BEDD-12B4-491C-B6CE-052CF7FF2360__SECTION_FYC_S52_DHB

OP #7901476
Lesenswert?

Danke für die raschen Antworten.

Hab die zwei Vorschläge umgesetzt - leider keine Änderung.

Interessant ist, dass er das gleiche Verhalten auch bei anderen PWM Frequenzen hat. Also wenn ich auf den PS auf 16 konfiguriere (122Hz) startet er nach 2 ms neu.

Wichtig ist auch das RxyPPS (also RA2PPS) Register, bei dem man den Timer-Ausgang auf einen Pin legen muss:

Gibt es dies auch für den 12F1501?

Aktueller Code (PS TMD2 noch auf 1:4): #include <xc.h>

#define _XTAL_FREQ 8000000

unsigned int duty = 100;

void init(void);

void main(void) { init(); while (1) { duty++; __delay_ms(10); if (duty > 1023)duty = 0; PWM1DCH = duty >> 2; PWM1DCL = (duty & 0x03) << 6; } }

void init(void) { OSCCON = 0b01110010; //Intern 8Mhz T2CON = 0b00000101; //T2 on, Prescaler = 1:4 PR2 = 0xFF; //

1
TRISAbits.TRISA2 = 0;
2
ANSELAbits.ANSA2 = 0;
3
PWM1CON = 0b11001000;
4
PWM1DCH = duty >> 2;
5
PWM1DCL = (duty & 0x0C) << 6;
6
T2CONbits.TMR2ON = 1;

}

OP #7901484
Lesenswert?

ich verstehe nicht warum es mit einem fixen Wert funktioniert:

Exakt 50%

unsigned int duty = 512;

void init(void);

void main(void) { init(); while (1) { } }

void init(void) { OSCCON = 0b01110010; //Intern 8Mhz T2CON = 0b00000101; //T2 on, Prescaler = 1:4 PR2 = 0xFF; //

1
TRISAbits.TRISA2 = 0;
2
ANSELAbits.ANSA2 = 0;
3

4
PWM1CON = 0b11001000;
5
PWM1DCH = duty >> 2;
6
PWM1DCL = (duty & 0x0C) << 6;
7
T2CONbits.TMR2ON = 1;

}

#7901497
Lesenswert?

Versuche mal in der main() vor dem beschreiben der PWM Register die Interrupts zu sperren. Danach natürlich wieder freigeben. Oder den Timer während des beschreibens anhalten.

1
  T2CONbits.TMR2ON = 0;
2
  PWM1DCH = duty >> 2;
3
  PWM1DCL = (duty & 0x0C) << 6;
4
  T2CONbits.TMR2ON = 1;

Gibt es beim PIC12 keinen Timerinterrupt? Versuche doch mal die Register im Interrupt zu setzen. So macht man das normalerweise, damit das syncron zum Timer ist.

OP #7901556
Lesenswert?

Alle Antworten plausibel und getestet - ich bekomm die Krise ....

immer noch das gleiche Verhalten: bei ca. 1/5 der PWM Zeit startet er bein initialen Duty Wert.

neuer Code mit den eingpeflegten Vorschlägen:

#define _XTAL_FREQ 8000000

unsigned int duty = 100, i; unsigned char dutyh, dutyl;

void init(void);

void __interrupt() myISR(void) { TMR2IF = 0; PWM1DCH = dutyh; PWM1DCL = dutyl;
}

void main(void) { init(); while (1) { __delay_ms(10); duty++; if (duty > 1023)duty = 0; dutyh = duty >> 2; dutyl = (duty & 0x03) << 6; } }

void init(void) { OSCCON = 0b01110010; //Intern 8Mhz INTCON = 0b11000000; // GIE = ON / PEIE = ON PIE1bits.TMR2IE = 1; // T2 IF = ON T2CON = 0b00000101; //T2 on, Prescaler = 1:4 PR2 = 0xFF; //

1
TRISAbits.TRISA2 = 0;
2
ANSELAbits.ANSA2 = 0;
3

4
PWM1CON = 0b11001000;
5
PWM1DCH = duty >> 2;
6
PWM1DCL = (duty & 0x0C) << 6;
7
T2CONbits.TMR2ON = 1;

}

OP #7901582
Lesenswert?

Ste N. - Danke. Hilft vielleicht ber der Ursachenermittlung ;-)

dutyh = (int)duty >> 2; --> gleiches Bild ABER

wenn ich in dutyh = 0xff setzte kommt es alles 2 Sekunden zu einem "reset".

ich sehe es am Oszi und noch deutlicher am angescholssenen Voltmeter (soll eine Meterclock werden) da der Zeiger kurz "einbricht"

Es sieht so aus als ob das PWM Modul alle 2 Sekunden einen reset macht.

Vielleicht hat wer eine Idee?

#7902387
Lesenswert?

Ste N. schrieb:

Roland E. schrieb:

Bei einem 8-Biter?

Wieso nicht? Auch ein 8-Biter kann mit int rechnen. Auch mit long und double. Was ist daran ungewöhnlich? Oder meinst du den 8bit Timer. Da werden für die PWM intern 2bit dazu addiert.

'Int' ist wimre insofern 'genormt', dass da die Standardgröße der entsprechenden CPU codiert wird. Das würde bei der og CPU einen uint_8 ergeben.

Schreib doch mal 1023 in die Variable incrementiere und prüfe auf >=1023.

Könnte spannend werden.

Bei den kleinen PICs habe ich mir angewöhnt, die in ASM zu benutzen. Da fällt so was sofort (im Debugger) auf...

PS: die 2Bit mehr im Timer nutzen dir nix, wenn die ALU sie nicht bearbeiten kann. Da gewinnst du nur jede Menge Registeroperationen, weil er alles doppelt rechnen muss.

#7902451
Lesenswert?

Roland E. schrieb:

PS: die 2Bit mehr im Timer nutzen dir nix, wenn die ALU sie nicht bearbeiten kann.

Lieber Roland, deine Beiträge hier sind Quark. Hättest du mal in das Datenblatt des Pic12F1501 reingeschaut, da wäre dir bereits auf Seite 1 der Text "Four PWM modules 10 Bit" begegnet. Das Bauteil, diese Hardware-Untergruppe Timer, kann eben diese Auflösung. Einmal eingestellt, wird das von ganz alleine beibehalten. Nur bei Änderungen schreibt man neuen Wert. Die ALU der CPU braucht man dazu überhaupt nicht, falls Konstanten direkt oder aus Tabellen geschrieben werden. Aber selbst wenn man irgendwie berechnete Werte verwendet, schafft es der Compiler XC8 diese richtig zu verwursten, wenn man korrekte Typgrössen verwendet. Deine Formulierungen zeigen ziemlichen Nachholbedarf bei "modernen" 8-Bit-uC.

#7902455
Lesenswert?

Roland E. schrieb:

'Int' ist wimre insofern 'genormt', dass da die Standardgröße der entsprechenden CPU codiert wird. Das würde bei der og CPU einen uint_8 ergeben.

Schreib doch mal 1023 in die Variable incrementiere und prüfe auf

1
>=1023

Könnte spannend werden.

Wenn ich nicht völlig falsch liege hat ein 'Int' im XC8 immer 16bit und damit ist der Code völlig i.O.

#7902860
Lesenswert?

Klaus F. schrieb:

Roland E. schrieb:

PS: die 2Bit mehr im Timer nutzen dir nix, wenn die ALU sie nicht bearbeiten kann.

Lieber Roland, deine Beiträge hier sind Quark. Hättest du mal in das Datenblatt des Pic12F1501 reingeschaut, da wäre dir bereits auf Seite 1 der Text "Four PWM modules 10 Bit" begegnet. Das Bauteil, diese Hardware-Untergruppe Timer, kann eben diese Auflösung....

Das mag sein, die Vergleichsoperation im Code wird aber nicht imn Register des Timers ausgeführt. Sondern in der ALU. Und die ist bestenfalls 9 Bit, wenn man das Carry mitzählt.

Und ein 16bit Vergleich auf einer 8Bit Hardware ist immer ein Handstand.

#7903005
Lesenswert?

Klaus F. schrieb:

Roland E. schrieb:

Und ein 16bit Vergleich auf einer 8Bit Hardware ist immer ein Handstand.

Anbei der Handstand.

Da ich die kleinen PICs nach wie vor mit Assembler bespaße, ist mir das durchaus bewusst. Die Codebasis/Rechenzeit steigt grob um das dreifache. Macht (muss man das) in einem IRQ, erzeugt man damit eine erhebliche Totzeit, in der der Knödel nix mehr anderes macht und ggf IRQs verliert.

Klar, mit C merkt man es nicht, was für einen Blähcode man damit erzeugt. Man merkt dann nur, dass selten irgend welche komischen Effekte auftreten.

Die ursprüglich vom OP beschriebenen Ausfälle passen in solche Kategorien.

Mit etwas Nachdenken und geschickt gewählte Vorteiler kann man den 16Bit-Vergleich auch sicherlich vermeiden, vor allem wenn man wie der OP eh auf Überlauf prüft. DECFZ fällt mir da ein...

#7904138
Lesenswert?

Roland E. schrieb:

'Int' ist wimre insofern 'genormt', dass da die Standardgröße der entsprechenden CPU codiert wird. Das würde bei der og CPU einen uint_8 ergeben.

Falsch geraten. "int" muß lt. C-Standard mindestens 16 Bit sein, darf aber auch 32 Bit oder 64 Bit haben. Wenn die Bitbreite eine Rolle spielt, sollten man immer die Typen aus der <stdint.h> benutzen (uint16_t usw.).

Roland E. schrieb:

Bei den kleinen PICs habe ich mir angewöhnt, die in ASM zu benutzen.

Na wenn Du Spaß daran hast, viel Schreibarbeit für den ganzen Low-Level Schrunz auf Dich zu nehmen. Auch bei 8-Bittern erhöht C drastisch die Lesbarkeit und verringert Fehlerquellen, weil man sich besser auf die eigentlichen Abläufe fokussieren kann.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren