Hallo Ich bin Neuling auf dem Gebiet der Atmel Programmierung. Ich habe mir ein Programm geschrieben, welches mir 3Leds an den Ports C0,C1,C3 per PWM dimmen soll. Dazu liest es beim start werte, welche fest im EEprom liegen aus und übergibt diese an den SRAM. funktioniert auch super bis auf eine Sache. Wenn ich den Atmega8(teste auf STK500) einschalte dann leuchten die 3 Leds mit max. Helligkeit und nicht mit der gewünschten. Am auslesen des EEproms kann es nicht liegen, das habe ich geprüft die werte werden gelesen. Kann mir jemand einen Tip geben was ich falslch gemacht habe?
Sorry Datei hochladen ging nicht. Hab das Assembler Programm mal
reinkopiert.
.include "m8def.inc"
.def temp = r16
.def temp1 = r17
.def temp2 = r18
.def cv1 = r19
.def cv2 = r20
.def cv3 = r21
.def cv4_7 = r22
.def cv11 = r23
.def pwmcount = r24
.org 0x000
rjmp main
.org OVF2addr
rjmp timer2_overflow ;Timer Overflow Handler
.cseg
main:
ldi temp, LOW(RAMEND) ;Stackpointer initialisieren
out SPL, temp
ldi temp, HIGH(RAMEND)
out SPH, temp
ldi temp, $FF
out DDRC, temp ;Port C0,C1,C2 als
Ausgangsregister
rcall readcvdata ;CV Werte aus eeProm lesen und in
SRAM ablegen
main1:
ldi temp, (1<<CS20) ;CS00 setzen Teiler 1
out TCCR2, temp
ldi temp, (1<<TOIE2) ;TOIE0: Interrupt bei Timer
Overflow
out TIMSK, temp
ldi temp, $00
sts srPWMCount, temp ;Zähler Timer Sram am Anfang null
setzen
sei
loop:
rjmp loop
;pwm für portc für C0-C3
timer2_overflow: ;Timer 0 Overflow Handler
lds pwmcount, srPWMCount ;den PWM Zähler aus dem
Speicher holen
inc pwmcount ;den PWM Zähler von 0 bis
127 zählen lassen
cpi pwmcount, 255 ;wurde 255 erreicht?
brne WorkPWM ;NEIN
clr pwmcount ;Ja: Zähler 0 setzen
WorkPWM:
sts srPWMCount, pwmcount ;den PWM Zähler wieder
speichern
ldi temp, 0b11111000 ;0 .. Led an, 1 .. Led aus
lds pwmcount, srPWMCount
lds temp1, srCV2
cp pwmcount, temp1 ;Ist der Grenzwert für Led
1 erreicht
brlo OneOn
ori temp, $01
OneOn:
lds temp1, srCV3
cp pwmcount, temp1 ;Ist der Grenzwert für Led
2 erreicht
brlo TwoOn
ori temp, $02
TwoOn:
lds temp1, srCV11
cp pwmcount, temp1 ;Ist der Grenzwert für Led
3 erreicht
brlo SetBits
ori temp, $04
SetBits: ;Die neue Bitbelegung am
Port ausgeben
out PORTC, temp
reti
;daten der cv werte aus eeprom lesen und im sram ablegen
read_sram1:
sts srCV1, temp1 ; Lade temp in SRAM Stelle srCV1
inc temp2
rcall readcvdata
read_sram2:
sts srCV2, temp1
inc temp2
rcall readcvdata
read_sram3:
sts srCV3, temp1
inc temp2
rcall readcvdata
read_sram4:
sts srCV4_7, temp1
inc temp2
rcall readcvdata
read_sram5:
sts srCV11, temp1
inc temp2
rcall readcvdata
readcvdata:
ldi ZL, LOW(eeCV1) ;Low-Byte der Adresse in
Z-Pointer
ldi ZH, HIGH(eeCV1) ;High-Byte der Adresse in
Z-Pointer
cpi temp2, 0 ;Vergleiche temp2 mit 0
breq EEPROM_read ;Wenn gleich dann EEPROM_read ausführen
cpi temp2, 1
breq read_sram1
ldi ZL, LOW(eeCV2)
ldi ZH, HIGH(eeCV2)
cpi temp2, 2
breq EEPROM_read
cpi temp2, 3
breq read_sram2
ldi ZL, LOW(eeCV3)
ldi ZH, HIGH(eeCV3)
cpi temp2, 4
breq EEPROM_read
cpi temp2, 5
breq read_sram3
ldi ZL, LOW(eeCV4_7)
ldi ZH, HIGH(eeCV4_7)
cpi temp2, 6
breq EEPROM_read
cpi temp2, 7
breq read_sram4
ldi ZL, LOW(eeCV11)
ldi ZH, HIGH(eeCV11)
cpi temp2, 8
breq EEPROM_read
cpi temp2, 9
breq read_sram5
ldi temp1, 0x00
ldi temp2, 0x00
rcall main1
EEPROM_read:
sbic EECR, EEWE ;prüdfe ob der vprherige Schreibzugriff
beendet ist
rjmp EEPROM_read ;NEIN nochmal prüfen
out EEARH, ZH ;Adresse laden
out EEARL, ZL
sbi EECR, EERE ;Lesevorgang aktivieren
in temp1, EEDR
inc temp2
rcall readcvdata
ret
; eeprom daten, hier die Standart CV Werte
.eseg
eeCV1: .db 0x01 ;Adresse der Lok
eeCV2: .db $01 ;Dimmung Ausgang C0 einstellbar
zwischen 0x00 und 0xF7
eeCV3: .db 20 ;Dimmung Ausgang C1 einstellbar
zwischen 0x00 und 0xF7
eeCV4_7: .db 0x01 ;Richtungsabhängige Steuerung,
Abschaltung und Steuerung Unterprogramme
eecv11: .db $FF ;Dimmung Ausgang C3 einstellbar
zwischen 0x00 und 0xF7
;sram daten
.dseg
srPWMCount: .BYTE 1 ;Der PWM Counter (0 bis 127)
srCV1: .BYTE 1 ;5 Bytes für CV Daten
srCV2: .BYTE 1
srCV3: .BYTE 1
srCV4_7: .BYTE 1
srCV11: .BYTE 1
Hallo
Habe den Fehler selber gefunden, es fehlte ein rjmp zwischen sei und
loop:
ldi temp, $00
sts srPWMCount, temp ;Zähler Timer Sram am Anfang null
setzen
sei
rjmp 0x004
loop:
rjmp loop
David S schrieb: > Hallo > > Habe den Fehler selber gefunden, es fehlte ein rjmp zwischen sei und > loop: > Das ist ziemlich sicher nicht die Problemlösung. Das mag das Problem kaschieren, aber als Lösung ist das untauglich. Wie soll dieser rjmp (und warum eigentlich 0x004?) irgendetwas an der Programausführung verbessern?
Hi Ich glaube auch nicht, das der RJMP 0x004 irgendwas it deinem Problem zu tun hat. Bei Assembler ist es zwingend notwändig, sich eine Struktur aufzubauen. Richtig ist z. B.
1 | Org: 0x000 RJMP Main ; Sprung zum Hauptprogramm |
2 | ; hier stehen die Interruptvektoren |
3 | |
4 | Main: ldi temp, LOW(RAMEND) ;Stackpointer initialisieren |
5 | out SPL, temp |
6 | ldi temp, HIGH(RAMEND) |
7 | out SPH, temp ; soweit richtig |
8 | ; und weitere Initialisierungen |
9 | ldi temp, $FF ; 0xFF ! |
10 | out DDRC, temp ;Port C0,C1,C2 als |
11 | Ausgangsregister |
12 | |
13 | ; irgendwann kommt deine Programmschleife |
14 | Loop: ; ab hier werden alle Unterprogramme aufgerufen |
15 | ; die in deinem Programm laufend abgearbeitet werden |
16 | ; in der Form |
17 | ; Lesen z. B. Werte von außen, Schalter, Taster UART etc |
18 | ; Bearbeiten |
19 | ; Ausgeben von Werten an die Peripherie |
20 | RJMP Loop ; dieser Teil wird immer wieder aufgerufen |
21 | |
22 | ; und nun deine Unterprogramme |
23 | read_sram5: ; Wert nehmen |
24 | ; bearbeiten |
25 | ; ablegen |
26 | RET ; mit RET verläßt du das Unterprogramm |
27 | ; RETI ist Ausnahme bei Interrupt - ende |
du hast in deinem Programm Sprungmarken, die du aufrufst, aber kein RET dahinter, sondern Nahtlosen Übergang in die nächste Routine. Ich kann mich irren und es kann so gewollt sein, aber sicher ist, das der Aufruf RCALL readcvdata ;CV Werte aus eeProm lesen und in den Aufruf rcall main1 zur Folge hat, ohne das ich hier irgendwo ein RET gesehen habe. Innerhalb springst du bedingt auf irgendwelche Marken und rufst wieder mit RCALL readcvdata auf. Damit ist ein Stacküberlauf vorprogrammiert. Du mußt die Verwendung von RCALL und RJMP richtig einsetzen, sonst marschiert das Programm ins Nirwana Gruß oldmax
Hallo Danke für Eure Hinweise werd den Aufbau noch mal überdenken. Binn für weitere Hinweise offen, nur dadurch lernt man es vernünftig ;-)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.