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.