Forum: Mikrocontroller und Digitale Elektronik fast pwm mega8 timer1 OC aktualisierung


von daniel (Gast)


Lesenswert?

Hallo,

meine Frage zur "Fast PWM" auf dem mega8A (4MHz ext. Quarz) ist zu 
folgenden Code. Arbeite mit #define TX_T1_B.
1
/** self triggered transmission from buffer */
2
ISR(CODINGTIMER_OCM)
3
{
4
  HW_Output();
5
}
6
7
/** interupt routine on overflow */
8
static inline void HW_Output(void)
9
{ 
10
  /* active transmission */
11
  g_ubSize--; 
12
#ifdef TX_TIMER2
13
  OCR2 = g_uwOCR[g_ubSize];
14
#endif
15
#ifdef TX_T1_A
16
  OCR1A = g_uwOCR[g_ubSize];
17
#endif
18
#ifdef TX_T1_B
19
  OCR1B = g_uwOCR[g_ubSize];
20
#endif
21
  if(uwCycle < D_CYC)
22
    WrVal(g_uwOCR[g_ubSize], 0);
23
  /* ready, initiate sync */
24
  if (g_ubSize == 0)
25
    HW_Sync();
26
}
27
static inline void HW_TxInit(void)
28
{
29
#ifdef TX_TIMER2 // timer 2
30
  /* initialize sync bit, init fast pwm */
31
  OCR2 = BIT_1;
32
  TCNT2 = 0;
33
  g_ubSize = TX_BITS;
34
  TIFR |= (1<<TOV2);
35
  TIMSK |= (1<<TOIE2);
36
#endif
37
#ifdef TX_T1_A // timer 1 A
38
  OCR1A = stTx.uwBit1;
39
  ICR1 = stTx.uwTx;
40
  TCNT1 = stTx.uwTx-1;
41
  g_ubSize = TX_BITS;
42
  TIFR |= (1<<TOV1) | (1<<ICF1);
43
  TIMSK |= (1<<OCIE1A);
44
#endif
45
#ifdef TX_T1_B // timer 1 B
46
  OCR1B = stTx.uwBit1;
47
  OCR1A = stTx.uwTx;
48
  TCNT1 = 0xFFFF;
49
  ICR1 = 0;
50
  g_ubSize = TX_BITS;
51
  TIFR |= (1<<TOV1) | (1<<ICF1);
52
  TIMSK |= (1<<OCIE1B);
53
#endif
54
}
55
56
static inline void HW_TxActive(void)
57
{
58
  /** inverted PWM(OCR set, OVF clr), prescaler by define */
59
#ifdef TX_TIMER2 // atmega8A
60
  TCCR2 = (3<<WGM20) | (2<<COM20) | (PRES_BTX << CS20);
61
#endif
62
#ifdef TX_T1_A // atmega8
63
  TCCR1A = (2<<WGM10) | (3<<COM1A0);
64
  TCCR1B = (3<<WGM12) | (stTx.ubTxPresc << CS10);
65
#endif
66
#ifdef TX_T1_B // atmega8
67
  TCCR1A = (3<<WGM10) | (3<<COM1B0);
68
  TCCR1B = (3<<WGM12) | (stTx.ubTxPresc << CS10);
69
#endif
70
}
Der Timer1 arbeitet mit Fast PWM, TOP = OCR1A . Das Register OCR1B ist 
ja gepuffert und die Aktualisierung erfolgt nur bei TOP.
Muss ich nun wirklich einen Ueberlauf erzwingen damit ORC1B aktiv wird? 
Wie muss dieser Ueberlauf aussehen mit TCNT1 = 0x0000, mit TCNT1 = 
ORC1A-1 starten.
Kann es im Simulator leiderns nicht testen da dieser einen Bug mit 
Timer1 hat (siehe Wiki). Hab leiderns kein Oszi und kann die PWM nicht 
ueberpruefen.
Gruss
daniel

von Stefan H. (hohmi)


Lesenswert?


von CTC? (Gast)


Lesenswert?

daniel schrieb:
> Muss ich nun wirklich einen Ueberlauf erzwingen damit ORC1B aktiv wird?

Nein, mal überprüfen ob der CTC Modus statt Fast PWM nicht auch 
verwendbar ist.

von daniel (Gast)


Lesenswert?

Hallo,

hatte nur "PWM" gefunden und nicht "AVR_PWM". Dennock konnte ich aber 
nicht viel zu meiner Frage fuer den Mode 15 finden.
1
mega8a.pdf - p.93
2
The OCR1A Register, however, is double buffered. This feature allows the OCR1A I/O
3
location to be written anytime. When the OCR1A I/O location is written the value written will be
4
put into the OCR1A Buffer Register. The OCR1A Compare Register will then be updated with
5
the value in the Buffer Register at the next timer clock cycle the TCNT1 matches TOP. The
6
update is done at the same timer clock cycle as the TCNT1 is cleared and the TOV1 Flag is set.

So wie ich es verstanden habe ist es egal wie oft am OCR1A rumschreibt. 
Es wird erst beim TCNT1 == TOP uebernommen. Aber wie ist es nun beim 
Start in diesem Mode, wird es da gleich uebernommen?

Naja ich werde nun ICR1 verwenden, also Mode = 14. Da mein TOP ein 
fester Wert und ICR1 nicht gepuffert ist.

Gruss
daniel

von daniel (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

hier mal ein Bild von einer Fast PWM aufm Mega8A.
Der erste Impuls von den 13 ist fehlerhaft, da er komplett high ist, 
sollte entsprechend eine "1" sein. Der zweite stellt dann eine "1"(DC = 
66%) dar und alle weiteren eine "0"(DC=33%).

Das ist die Init fuer den Bereich der Impulse(Fast PWM).
1
void TxInit()
2
{
3
  g_ubSize = TX_BITS;
4
  OCR1B = stTx.uwBit1;
5
  ICR1 = stTx.uwTx;
6
  TCNT1 = 0;
7
  TIFR = (1 << OCF1B);
8
  TIMSK |= (1<<OCIE1B);
9
  TCCR1A = (2<<WGM10) | (3<<COM1B0);
10
  TCCR1B = (3<<WGM12) | (stTx.ubTxPresc << CS10);
11
}
Wie muss ich denn nun TCNT1 initializieren, damit OCR1B gleich aktiv 
wird? Denn aktuell scheint es mir, dass es erst nach dem ersten 
TIMER1_COMPB und TOV1 aktualisiziert wird.

Gruss daniel

von daniel (Gast)


Lesenswert?

Hallo,

hatte nun mal nicht invertiert und eben die DC getauscht, aber dann ist 
das ganze Phasenverschoben.
Egal wie ich den Timer vorkonfiguriere bei einer invertierten Fast PWM 
hab ich immer den ersten Zyklus komplett high. Erst dann ist die PWM 
richtig.

Gruss daniel

von Spess53 (Gast)


Lesenswert?

Hi

>Egal wie ich den Timer vorkonfiguriere bei einer invertierten Fast PWM
>hab ich immer den ersten Zyklus komplett high. Erst dann ist die PWM
>richtig.

Und an welcher Stelle ist da das Problem?

MfG Spess

von daniel (Gast)


Lesenswert?

Hi,

das Problem ist der erste Impuls. Er ist fehlerhaft und bring den ganzen 
Algorithmus durcheinander.
Hab es nun endlich hinbekommen. Das Zaehlregister muss mit dem TOP Wert 
vorgeladen werden um einen Ueberlauf zu erzwingen. Dann erst wird ORC1B 
geladen und die PWM startet von Anfang an richtig. Einen Nadelimpuls 
am Ende des PWM Zykluses erledigt man entsprechend mit dem OCR1B in dem 
man es auf TOP laedt, bevor der Ueberlauf geschieht.
Fuer Motor-, Ledsteuerung interresiert soetwas niemanden. Bei 
Codierungen macht das sich aber schon bemerkbar, leiderns.

Hab nun noch einen Nadelimpuls im Ruhezyklus, aber das dann naechstes 
Wochenende?! ;)

Gruss daniel

von daniel (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

hier noch ein Bild vom Nadelimpuls. Man koennte mich ja missverstehen. 
Er befindet sich im rechten Teil vom Oszillogram.

Gruss daniel

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.