Hallo Zusammen
Ich bin gerade dabei auf einem PIC24FJ256 eine Routine zu schreiben um
eine Schrittmotor-Treiberstufe anzusteuern. Dabei stiess ich auf eine
aus meiner Sicht etwas seltsame Verhaltensweise der
Output-Compare-Module.
Absicht war, ein Signal variabler Frequenz mit 50:50 Duty-Cycle zu
generieren (ergibt dann pro Periode einen Schrittmotor-Schritt). Um den
Sinn oder Unsinn dafür OC-Module zu nutzen kann man natürlich streiten,
aber mich beschäftigt vor allem folgendes:
Konfiguration: single compare toggle (OCM = 0b011), OC1 und OC2
zusammenschalten (32bit), OCxR = 0x0000 (Pin-Toggle + Interrupt nach
Sync oder Überlauf), mit OCxRS Periodendauer vorgeben (-> Syncsel auf
"this OC-Modul") und als Taktquelle Systemtakt (mit FCY 16MHz).
Setze ich das Register OC2RS > 0x0000 läuft alles wie gedacht. Ist aber
OC2RS = 0x0000 und OC1RS hat irgendeinen Wert (z.B. 0x3999) scheint das
OC Modul direkt nach dem Start den ersten Compare-Event (OCxRS) zum
Synchronisieren (bei 0x00003999) zu "verschlafen". Der OCxTMR zählt beim
ersten Mal immer bis zum Überlauf hoch (dauert bei den 16Mhz und 32bit
einige Minuten...). Nach diesem ersten Überlauf klappt es dann aber
wieder und der Timer wird bei 0x00003999 zurückgesetzt.
Hab ich da irgendwie ein logisches Problem oder sonst etwas übersehen ?
Oder ist das eine Eigenheit dieses OC-Moduls ?
Initialisierung:
1 | //Cascade Mode OC1 + OC2
|
2 | OC1CON1 = 0x0000;
|
3 | OC2CON1 = 0x0000;
|
4 | OC1CON2 = 0x0000;
|
5 | OC2CON2 = 0x0000;
|
6 | OC1CON1bits.OCTSEL = 0b111; // System Clock
|
7 | OC2CON1bits.OCTSEL = 0b111;
|
8 | OC1R = 0x0000; // Toggle nach Sync
|
9 | OC2R = 0x0000;
|
10 | OC1RS = OCxRS_LowWord_FirstToggle;
|
11 | OC2RS = OCxRS_HighWord_FirstToggle;
|
12 | OC1CON2bits.SYNCSEL = 0b11111; //Sync: this OC module
|
13 | OC2CON2bits.SYNCSEL = 0b11111;
|
14 | OC1CON2bits.OCTRIS = 1; //OC1-Pin high-z
|
15 |
|
16 | OC2CON2bits.OC32 = 1; //Cascade Mode
|
17 | OC1CON2bits.OC32 = 1;
|
18 | OC2CON1bits.OCM = 0b000; //deaktiviert
|
19 | OC1CON1bits.OCM = 0b000;
|
20 |
|
21 | IPC1bits.OC2IP = 0b010;
|
22 | IFS0bits.OC2IF = 0;
|
23 | IEC0bits.OC2IE = 1;
|
Später im Code setze ich:
1 | //Enable Toggle Mode
|
2 | OC2CON1bits.OCM = 0b011;
|
3 | OC1CON1bits.OCM = 0b011; // Odd module must be enabled last
|
Gruss,
Matt.