Verständnisfrage zum Tutorial - 8 Bit Fast PWM

OP #2491244
Lesenswert?

Hallo zusammen

Ich arbeite mich momentan durch das Tutorial und habe eine 
Verständnisfrage zum Tutorial. Und zwar will ich das Fast-PWM Beispiel 
so modifizieren, dass ich eben auf eine 8 Bit PWM komme. Das 
funktioniert auch soweit, einfach stellt sich mir folgende Frage:

Bei der 8 Bit PWM hat der Compare-Wert ja im LowByte des OCR1A Registers 
Platz. Das heisst ja auch, dass es theoretisch reichen würde, nur das 
LowByte neu zu beschreiben, wenn man den Compare-Wert ändern will, das 
High-Byte muss ja immer auf 0 sein. Jetzt habe ich schon an diversen 
Stellen gelesen, dass immer zuerst das High-Byte beschrieben werden 
soll, dann das LowByte, weil es sonst unter umständen zu falschen Werten 
kommen kann. Beim ADC leuchtet mir das auch ein, aber ich kann mir bei 
diesem Register nicht vorstellen, dass es einen Einfluss hat, wenn ich 
innerhalb einer Interrupt-Routine nur das LowByte ändere. Oder übersehe 
ich da etwas, was in späteren, komplexeren Programmen Probleme machen 
könnte? Mit anderen Worten, gilt diese allgemeine Regel auch für das 
OCR1AH/L-Register?

Gruss Johannes
1
.include "m8def.inc"
2

3
;LED an OC1A, pulsiert zwischen lowerlimit und upperlimit
4
.def temp = r16
5
.def dir = r17
6
.def zero = r18
7
.def lowerlimit = r19
8
.def upperlimit = r20
9

10
.org 0x000
11
  rjmp RESET
12
.org OVF0addr
13
  rjmp INTERRUPT
14

15
RESET:
16
  ldi temp, HIGH(RAMEND)
17
  out SPH, temp
18
  ldi temp, LOW(RAMEND)
19
  out SPL, temp
20

21
  ldi zero, 0x00
22
  ldi lowerlimit, 0x00
23
  ldi upperlimit, 0x20
24
  ldi dir, 0x00
25

26
  ;Timer1 initialisieren
27
  ;Modus 5, kein prescaler
28
  ldi temp, 1<<COM1A1 | 1<<WGM10
29
  out TCCR1A, temp
30

31
  ldi temp, 1<<WGM12 | 1<<CS10 
32
  out TCCR1B, temp
33

34

35
  ;Comparewert füe OC1A
36
  ldi temp, 0x00
37
  out OCR1AH, temp
38
  ldi temp, 0X01
39
  out OCR1AL, temp
40

41
  ldi temp, 0x02
42
  out DDRB, temp
43
  
44
; Timer0 Aufsetzen
45
  ldi temp, 1<<CS02 | 1<<CS00  ;prescaler 1024 
46
  out TCCR0, temp
47

48
  ldi temp, 1<<TOIE0
49
  out TIMSK, temp
50

51
  sei
52
  
53

54
main:
55
  rjmp main
56

57
INTERRUPT:
58
  in temp, OCR1AL
59
  sbrs dir, 0 ;wenn das 0. bit 0 ist
60
  inc temp ; erhöhen
61
  sbrc dir, 0 ; wenn das 0. bit 1 ist
62
  dec temp ; verringern
63

64
  cp temp, upperlimit
65
  breq TOGGLEDIR
66
  cp temp, lowerlimit
67
  breq TOGGLEDIR
68

69
INTERRUPTEND:
70
  out OCR1AH, zero ;high-byte zuerst beschreiben (mit nullen, da 8Bit PWM)
71
  out OCR1AL, temp
72
  reti
73

74
TOGGLEDIR:
75
  com dir
76
  rjmp INTERRUPTEND
Gast #2491258
Lesenswert?

Es gibt hardwareseitig in der Tat ein temporäres Reister in dem der High 
Value zwischengespeichert wird. Erst wenn dann der Access auf das 
Low-Byte Register erfolgt, werden beide Werte zusammen, und in das 16Bit 
register geschrieben.
Sofern du also nicht sichergehen kannst, dass der Inhalt des internen 
temporären Registers 0x00 ist, solltest du lieber auch das High-Byte 
schreiben.

Siehe Datenblatt:
> The Output Compare Registers are 16-bit in size. To ensure that both the
> high and Low bytes are written simultaneously when the CPU writes to these
> registers, the access is performed using an 8-bit temporary High byte
> register (TEMP). This temporary register is shared by all the other 16-bit
> registers. See “Accessing 16-bit Registers” on page 77.

> When the Low byte of a 16-bit register is written by the CPU, the High
> byte stored in the temporary register, and the Low byte written are both
> copied into the 16-bit register in the same clock cycle.

> Accessing the Low byte triggers the 16-bit read or write operation. When
> the Low byte of a 16-bit register is written by the CPU, the High byte
> stored in the temporary register, and the Low byte written are both copied
> into the 16-bit register in the same clock cycle.
OP #2491301
Lesenswert?

Ok, wunderbar, dann ist jetzt alles klar.

Das würde heissen, in diesem Beispiel könnte ich es mir sparen, das 
High-Register auch bei jedem Interrupt zu schreiben, das ist aber keine 
gute Idee, sich das anzueignen, da sonst eine nicht unbedingt leicht zu 
findende Fehlerquelle entsteht. Besser ist es, das generell zu 
schreiben, dann ist man auf der sicheren Seite.

Vielen Dank.

Gruss Johannes
Gast #2491327
Lesenswert?

Hi

>Bei der 8 Bit PWM hat der Compare-Wert ja im LowByte des OCR1A Registers
>Platz. Das heisst ja auch, dass es theoretisch reichen würde, nur das
>LowByte neu zu beschreiben, wenn man den Compare-Wert ändern will, das
>High-Byte muss ja immer auf 0 sein. Jetzt habe ich schon an diversen
>Stellen gelesen, dass immer zuerst das High-Byte beschrieben werden
>soll, dann das LowByte, weil es sonst unter umständen zu falschen Werten
>kommen kann.

Bei einer 8Bit-PWM auf einem 16-Bit Timer ist es egal, was in OCRnH 
steht. Die High-Register werden schlichtweg ignoriert.

MfG Spess
Gast #2491427
Lesenswert?

Spess hat Recht:

> Note that when using fixed TOP values the unused bits are masked to zero when 
any of the OCR1x Registers are written.

Mit "fixed TOP values" sind hier die Modi gemeint bei der die PWM 
resolution fest vorgegeben ist. Also z.B. deine 8bit. Das High-Byte ist 
somit garantiert 0x00.

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