www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Avr assmebler Programm funktioniert nur sporadisch


Autor: David (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Ich habe ein kleines Assembler Programm geschrieben, welches alle 
Farbkombinationen einer RGB-Led durchlaufen soll. Leider funktioniert 
dieses nur bei ca. 1 von 10 Programmstarts , sonst werden völlig 
"falsche" Farbkombinationen durchlaufen. Ich bin nun etwas ratlos, da 
ich keinen Fehler finden kann und ziemlicher Anfänger bin.

Normalerweise sollte das Programm den Farbverlauf
Grün->Gelb->Rot->Lila->Blau->Türkis->Grün... darstellen
Meistens macht es aber:
Weiß-> lila->Blau->Türkis->Weiß
oder
Weiß->plötzlich Lila->Rot->plötzlich Blau->plötzlich Türkis->plötzl. 
Blau->plötzl. Weiß
oder andere komische Dinge

Hier der Programmcode:

.include "m8def.inc"



.org 0x000

  rjmp main

.org ovf0addr

  rjmp pwm

.org ovf1addr

  rjmp changer









.def temp= r16

.def led1 =r17

.def led2 =r18

.def led3 =r19

.def outport =r20

.def pwmcounter= r23

.def counter = r21

.def ccounter = r22



.org INT_VECTORS_SIZE



main:





ldi temp, LOW(RAMEND)

out spl, temp

ldi temp, high(ramend)

out sph, temp



ldi temp, 1<<CS01

out tccr0,temp

ldi temp, 1<<CS11

out tccr1b, temp

ldi temp, 1<<toie0 | 1<<toie1

out timsk, temp

ldi led1, 150 ; Grün an

ldi temp,0xff  ; portc als Ausgang

out ddrc, temp



sei



  pwmloop:

  out portc, outport

  rjmp pwmloop







pwm:

inc pwmcounter



  ldi outport,0xff  ;Alle leds an

  cp pwmcounter, led1

  brsh l1off

l2:        ;Prüfen ob leds aus sollen

  cp pwmcounter, led2

  brsh l2off

l3:

  cp pwmcounter, led3

  brsh l3off

l4:

  cpi pwmcounter, 150

  brsh killpwm

  rjmp end

killpwm:ldi pwmcounter,0x00

end:  

reti

l1off:

  cbr outport, 0x01

  rjmp l2

l2off:

  cbr outport, 0x02

  rjmp l3

l3off:

  cbr outport, 0x04

  rjmp l4



changer:



    cpi     counter,11        ;Counter resetten?

    brsh    clearcounter

    ldi     ZL,low(faelle)         

    ldi     ZH,high(faelle)

    add     ZL,counter                     

    ldi     temp,0                   

    adc     ZH,temp

    ijmp        



clearcounter:

  clr counter

  rjmp changer



faelle:

  inc led2  ;Rot +

  rjmp endtime

  dec led1  ; Gruen -

  rjmp endtime

  inc led3  ; Blau+

  rjmp endtime

  dec led2  ; Rot -

  rjmp endtime

  inc led1  ; Gruen+

  rjmp endtime

  dec led3  ; Blau-

  rjmp endtime



endtime:

  inc ccounter  ; Wenn ccounter 150 wird counter erhöht

  cpi ccounter, 150

  breq newcounter

reti

newcounter:

  subi counter, -2

  ldi ccounter, 0x00

reti

Die verwendete Hardware ist das Atmel Evalution Board von Pollin+ 
eigenbau Leistungstreiber. In meiner Werkstatt werkeln (mit Ausnahme des 
PCs) keine Schaltnetzteile o.Ä. , sodass ein EMV-Problem leider eher 
unwahrscheinlich ist.

Ich hoffe mir kann jemand beim finden des Fehlers helfen.

MfG David

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Entweder habe ich jetzt ein Knoten im Kopf oder es ist ein wunder das es 
überhaupt geht?

Hast mal mal etwas von einem Stack gehört? ISR müssen Register sichern! 
Und dann sollte man auch reti und call für ISR verwenden.

Autor: Sascha Weber (sascha-w)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

also rjmp passt schon, und reti sehe ich auch am Ende der ISR's. Aber 
wie Peter schon sagte: beim Eintritt in die ISR zuerst mal das 
Statusregister sichern (in r..,SREG), und dann alle Register die von der 
ISR und der Hauptschleife gemeinsam genutzt werden und getrennte 
Funktionen erfüllen.
In deinem speziellen Fall scheint die Hautschleife ja nun nichts zu tun 
(von dem Out mal abgesehen), und sich ISR's nicht gegenseitig 
unterbrechen können müsste das Programm eigentlich laufen.
Kannst du dein Programm nicht mal als ordentlich formatierten Code und 
ohen die ganzen Leerzeilen reinstellen, beim durchsehen in dem Format 
bekomme ich irgendwie einen Knoten in Sehnerv.

Sascha

Autor: Uwe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!
>Ich bin nun etwas ratlos, da
>ich keinen Fehler finden kann und ziemlicher Anfänger bin.
Dafür schreibst du aber schon recht verwirrende Programme und das fast 
alles ohne Kommentar.;-)
Du könntest led1 bis led3 mal einen eindeutigen Startwert geben.
So ganz erklärt es allerdings die plötzlichen Farbwechsel nicht.

Viel Erfolg, Uwe

Autor: Mark Leyer (m2k10) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Könnte es sein, dass es immer läuft, wenn du den Strom neu einschaltest 
oder neu flashst?

So rein funktional betrachtet sollte dein Programm eigentlich laufen, 
ich hab zumindest keine groben Fehler gesehen. Der AVR setzt aber die 
Register nicht einfach auf 0 beim Reset, wie du augenscheinlich 
voraussetzt, daher ist es schon ratsam, diese vor Verwendung mit einem 
festen Wert zu initialisieren. (clr led2, clr led3 etc. hinter main: 
einfügen)

Dein Programm hier ist ein 'klassisches' Beispiel, dass ISRs weder das 
SREG noch irgendwelche Register sichern MÜSSEN. Da du dich aber als 
'ziehmlichen Anfänger' bezeichnest: besser zuviel sichern, sich dafür 
aber an das routinemäßige Sichern gewöhnen. Spart später viele Tage 
Lebenszeit für die Fehlersuche.

Mark

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

die nicht geretteten Register sind vermutlich zufällig nicht ganz so 
tragisch, in der main loop gibt es keine Flag-abhägigen Befehle und auch 
keine, die die Flags ändern.
Allerdings habe ich mir das pwm-Chaos nicht im Detail angeschaut.

Die ijmp gehen aber in jedem Fall die Hose.
Die Adresse ist eim Flash, also eine Word-Adresse, die Label sind 
Byte-Label.

Also
    ldi     ZL,low(faelle*2)
    ldi     ZH,high(faelle*2)

Dann addierst Du counter dazu, der kann offenbar 0...11 annehmen, 
soviele Fälle sehe ich garnicht.
Dazu kommt: alle Befehle des AVR sind Word lang (mindestens), Du 
addierst aber z.B. 1 und der AVR fällt auf die Nase, weil ein Befehl 2 
lang ist...
Ein Tabelleneintrag ist ja wohl:

  inc led2  ;Rot +
  rjmp endtime

inc ist 1 Word (2 Byte)
rjmp ebenfalls.

Ein Eintrag ist also 4 Byte lang und nicht nur ein Byte...

Gruß aus Berlin
Michael

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Also
>    ldi     ZL,low(faelle*2)
>    ldi     ZH,high(faelle*2)

Das gilt nur für lpm. ijmp und icall arbeiten mit den Wordadressen.

>Dazu kommt: alle Befehle des AVR sind Word lang (mindestens), Du
>addierst aber z.B. 1 und der AVR fällt auf die Nase, weil ein Befehl 2
>lang ist...

Macht er auch richtig:

  subi counter, -2

MfG Spess

Autor: gtf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo David,
 im AVR PWM Tutorial ist ein Beispiel vorhanden dass kaum noch zu toppen 
ist.
http://www.mikrocontroller.net/articles/AVR-Tutorial:_PWM

Und Push,Pop nicht vergessen. Wie das geht siehe
http://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack

Gruß gtf

Autor: Mark Leyer (m2k10) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael U. schrieb:
> ldi     ZL,low(faelle*2)
>     ldi     ZH,high(faelle*2)

Ist bei dem ijmp genau nicht so, da hier die word-Adresse verwendet 
wird. Adresse *2 ist nur für byteweisen Datenzugriff mit lpm. 'subi 
counter, -2
' berücksichtigt auch ganz richtig die 4 bytes, weshalb die Sprünge 
korrekt laufen sollten. Sehr eigenwillig geschrieben aber durchaus 
kreativ.

Autor: MWS (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn counter = 0 und dann  2 abgezogen wird, dann ist counter = 254, das 
als Index für den ijmp gibt ein interessantes Ergenis :D

Autor: MWS (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ooops, minus übersehen...

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

@Spess53:
@Mark L. (m2k10):

wo Ihr recht habt, habt Ihr recht...

Das subi counter, -2 habe ich auch übersehen...

Wohl nicht mein Tag heute.

Gruß aus Berlin
Michael

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Wohl nicht mein Tag heute.

Kenne ich.

MfG Spess

Autor: MWS (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auch wenn der Code tatsächlich recht "creativ" ist, so scheint er doch 
so weit zu funktionieren, auch der IJMP.

Allerdings wird zu Beginn nur das Register für "grün" led1 
initialisiert, led2 und led3 haben einen zufälligen Zustand und werden 
von diesem Zustand aus weiter gezählt, inklusive möglicher Überläufe.

Initialisieren der beiden Register dürfte das Problem beheben, hatte Uwe 
bereits geschrieben.

Autor: David (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo,
Danke für die vielen Antworten.

Des Rätselts Lösung war:

MWS schrieb:
> Allerdings wird zu Beginn nur das Register für "grün" led1
> initialisiert, led2 und led3 haben einen zufälligen Zustand und werden
> von diesem Zustand aus weiter gezählt, inklusive möglicher Überläufe.
>
> Initialisieren der beiden Register dürfte das Problem beheben, hatte Uwe
> bereits geschrieben.

Nachdem ich nun alle Register beim Programmstart initialisiere 
funktionierts perfekt.

Grüße David

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.