Hallo,
habe ein Problem.
Verwendeter Controller AT90S 8535
Unter AVR-Studio 3.52 (habe noch 4.0 auf de Rechner, da das gleiche)
auf dem STK500 getestet.
Ich will PinD5 mittels Compare-Match toggeln, so Frequenzen erzeugen
(Lautsprecher an PinD5)
Gebe ich den Compare-Wert händisch ein geht es.
Ich gebe die Inititerung mal mit an, vielleicht habe ich ja eines der
T1-Register
.def tmp= r16
INIT: ;Stack init
ldi tmp,LOW (RAMEND) ;Stack
out SPL, tmp
ldi tmp ,HIGH (RAMEND)
out SPH, tmp
;Port initieren
ldi tmp,1<<PinD5 ;setze Bit5 in tmp
out DDRD,tmp ;PinD5 = Output
;Timer1 init
ldi tmp, 1<<CS10|1<<CTC1 ;Prescaler 1,Bit0
out TCCR1B,r16 ;Timer1 bei erreichen des Comparewertes auf Null
setzten,Bit4
ldi tmp,1<<COM1A0 ;toggle PinD5 bei erreichen des Comparewertes
out TCCR1A,tmp
;---------------------
; Hauptprogramm
;---------------------
LADE:
ldi tmp,high($2383) ;schreibe Compare-Wert in Compare-RegisteAr H
out OCR1AH,tmp
ldi tmp,low($2383) ;schreibe Compare-Wert in Compare-RegisteAr L
out OCR1AL,tmp
START:
nop
rjmp START
;---------------------------------------------------------------------
Gebe ich den Compare-Wert aber über Tabelle und LPM ein geht es nicht.
Rest wie oben und
LADE:
ldi ZL,LOW(2*LISTE) ;Registerpaar Z zeigt auf das
ldi ZH,HIGH(2*LISTE)
lpm
out OCR1AL,r0 ;lade 1Byte in CompareL
inc ZL
lpm
out OCR1AH,r0 ;lade Compare_Low
inc ZL
START:
nop
rjmp START
LISTE:
.dw $2383
Im Simulator geht es, aber in Natura nicht.
Sprich erster Code erzeugt Frequnez 440 Hz (bei 8Mhz), zweiter gibt
keinen Ton von sich, und im Simulator gehen beide :-(
Was mache ich falsch ?
Der Code ist auf das Problem reduziert, ich möchte später verschiedene
Compare-Werte über LPM und Programm-Memory auslesen.
Vielen Dank für Hilfe
Ein dummer(?), verzweifelter Markus
LADE:
ldi ZL,LOW(2*LISTE) ;Registerpaar Z zeigt auf das
ldi ZH,HIGH(2*LISTE)
lpm
out OCR1AL,r0 ;lade 1Byte in CompareL
inc ZL
lpm
out OCR1AH,r0 ;lade Compare_Low
inc ZL
consequently, the high byte must be written first for a full 16bit
register write operation....
Stimmt im Simulator auch die Frequenz? Wenn die LISTE gerade auf einer
Seitengrenze zu liegen kommt, reicht z.B. das das inc ZL nicht, weil
sich das ZH erhöhen müßte (oder macht AVRstudio Auto-Align bei .dw --
keine Ahnung). Egal: wenn Du eine echte Liste hast, mußte Du es sowieso
richtig machen.
Andere Möglichkeit: werden im restlichen Code r0 oder Z in
Interruptroutinen benutzt, ohne vorher gerettet zu werden? Wenn der
Interrupt nicht mitsimuliert wird, entgeht Dir das Problem in der
Simulation.
Ich würde sagen, das muss gehen.
Bis auf eins: Bei deinem LPM-Teil lädst du OCR1AL zuerst.
Ist es nicht so, dass bei 16Bit-Registern erst das High-Byte
geschrieben werden muss und dann das Low-Byte?
Schreib mal OCR1AH zuerst, dann OCR1AL.
Gruss
Jadeclaw.
stimmt, auch wenn das hier nicht das eigentliche Problem ist:
statt
inc zl
lieber
adiw z,1 benutzen. Sonst kann es passieren, dass man sich
"unerklärliche " Effekte einbaut, insbesondere nach
Programmänderungen, die scheinbar damit gar nichts zu tun haben.
Ich liebe Compiler, die verschonen mich von solchem Geraffel :-)
Das Erhöhen des Z-Pointers sollte mit
adiw zh:zl,1
erfolgen, damit der Übertrag nach ZH (Pagegrenze) berücksichtigt wird.
Dann wäre es sicher zweckmäßig, nach dem ersten LPM den Wert von r0 in
ein anderes Register zu sichern, dann das zweite Byte aus der Tabelle
zu holen und dann direkt hintereinander ocr1ah und ocr1al zu
beschreiben.
Ob der Timer im korrekten Modus ist, habe ich jetzt nicht überprüft...
...