Forum: Mikrocontroller und Digitale Elektronik Nach einschalten Atmega8 Probleme


von David S (Gast)


Angehängte Dateien:

Lesenswert?

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?

von David S (Gast)


Lesenswert?

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

von David S (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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?

von oldmax (Gast)


Lesenswert?

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

von David S (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.