mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Was ist hier denn falsch µc kaputt?


Autor: Heiner H. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo,
also ich habe jetzt ein programm geschrieben, für den Atmega16.
;***************************************
.include "m16def.inc"
;***************************************

.def temp = r16
.org 0x0000
        rjmp    init                  ; Reset Handler
.org OVF0addr

init:  ldi     temp, LOW (RAMEnD)    ; Stackpointer initialisieren
        out     SPL, temp
        ldi     temp, HIGH (RAMEnD)
        out     SPH, temp
    LDI    R22, 255    ;initialisieren
    OUT    DDRA, r22
    OUT    DDRB, r22
    OUT    DDRC, r22
    OUT    DDRD, r22
    LDI    r18, 0
    LDI    r19, 255
main:  LDI    R17, 0b00000001  ;aufbau in rot
main1:  ROR    r17
    out    PORTA, r17
    CPI    r17, 255
    call warten
    BRNE  main1
main2:  LDI    R17, 0b00000001
main3:  ROR    r17
    out    PORTB, r17
    CPI    r17, 255
    BRNE  main3
    call warten
    out    PORTA, r18    ;alles aus
    out    PORTB, r18
main4:  LDI    R17, 0b00000001  ;aufbau in grün
main5:  ROR    r17
    out    PORTC, r17
    CPI    r17, 255
    call warten
    BRNE  main5
main6:  LDI    R17, 0b00000001
main7:  ROR    r17
    out    PORTD, r17
    CPI    r17, 255
    BRNE  main7
    call warten
    out    PORTC, r18    ;alles aus
    out    PORTD, r18
main8:  LDI    R17, 0b00000001  ;aufbau in orange
main9:  ROR    r17
    out    PORTA, r17
    out    PORTC, r17
    CPI    r17, 255
    call warten
    BRNE  main9
main10:  LDI    R17, 0b00000001
main11:  ROR    r17
    out    PORTB, r17
    out    PORTD, r17
    CPI    r17, 255
    BRNE  main11
    call warten
    out    PORTA, r18    ;alles aus
    out    PORTB, r18
    out    PORTC, r18
    out    PORTD, r18
    nop
    call warten
    out    PORTA, r19    ;schrift rot  
    out    PORTB, r19
    nop
    call warten
    out    PORTA, r18    ;alles aus
    out    PORTB, r18
    out    PORTC, r19    ;alles grün
    out    PORTD, r19
    nop
    call warten
    out    PORTC, r18    ;alles aus
    out    PORTD, r18
    out    PORTA, r19    ;alles orange
    out    PORTB, r19
    out    PORTC, r19    
    out    PORTD, r19
    nop
    call warten
    out    PORTA, r18    ;alles aus
    out    PORTB, r18
    out    PORTC, r18    
    out    PORTD, r18

    rjmp  main

; warte 1999998 Zyklen:
warten:  ldi  R17, $12
WGLOOP0:  ldi  R18, $BC
WGLOOP1:  ldi  R19, $C4
WGLOOP2:  dec  R19
          brne WGLOOP2
          dec  R18
          brne WGLOOP1
          dec  R17
          brne WGLOOP0 
ret
    

Habe jetzt mit dem Multimeter nachgemessen an den Ports, jedoch kommt 
nirgendwo spannung an, außer an Pin C4 und Pin C6.
was ist denn da falsch???
Ist eventuell der µc kaputt, aber habe es eigentlich auch mit einem 
anderen probier, da passierte aber das Gleiche?
mfg

Autor: VZP (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und die fuses sind richtig ?

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
JTAG noch an?
(fuse/bit) -  betrifft aber nur Port C
...Und der Code sieht ganz schön zusammen-ge-copy-n-pasted aus
1)  deine Warte-Funktion überschreibt einfach Register
2)  du hast EIN Register benannt (".def temp=r16"), benutzt aber alle 
andern mit Nummer
3)  das hier funktioniert so nicht
main:
    LDI    R17, 0b00000001  ;aufbau in rot
main1:
    ROR    r17
    out    PORTA, r17
    call warten ;hab ich getauscht, fuer mehr Uebersicht
    CPI    r17, 255
    BRNE  main1
Um da 1en reinzuRORen, müsstest du das Carry-Bit setzen. Abgesehen von 
Punkt 1)

hth. Jörg

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Heiner H. wrote:

> Habe jetzt mit dem Multimeter nachgemessen an den Ports, jedoch kommt
> nirgendwo spannung an, außer an Pin C4 und Pin C6.
> was ist denn da falsch???

Das deutet darauf hin, dass an deinem Mega16 das JTAG Interface
noch eingeschaltet ist (kann per Fuse abgeschaltet werden).

Für den Rest:
Lad dein Programm mal in den Simulator und gehe es Schritt
für Schritt durch. Überleg dir auch was
     ROR r17
eigentlich wirklich macht.

PS: Nichts gegen Dezimalzahlen. Aber in diesem Beispiel sind
Dezimalzahlen so ziemlich die ungeeignetste Form. Hex oder
Binär wäre wesentlich besser.

Autor: AVRFan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaube kaum, dass Du hier jemand findest, der Dir diese Wurst von 
Code analysiert.  Vorschlag: Versuch erst mal EINE LED zum Leuchten 
(danach: Blinken) zu bringen.  Wenn das funktioniert, baust Du darauf 
auf, indem Du immer wenig hinzufügst und ständig testest.  Dann klappts 
auch mit dem µC...

Autor: Tim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ohne das jetzt vollständig zu analysieren ein parr worte....

Du verwendest mehrfach sowas wie:

    CPI    r17, 255
    call warten
    BRNE  main5

wobei "call warten" dir das erbebniss von "CPI    r17, 255"
durch die DEC operationen verändert.

Beim verlassen von "warten:" sind die register R17..R19 == 0...
BRNE (springt wenn Z=0) dadurch nie.
und das ROR auf das leere R17 macht auch nicht viel sinn.

Du solltest beachten das der AVR weder beim CALL noch bei
einem IRQ irgend etwas von seinen registern von selbst sichert.
(mit ausnahme des PC).
wenn du also vor "call warten" einen verglich machst und
danach das ergebniss benutzen willst must du das SREG
in "warten:" sichern und wiederherstellen. Gleiches gilt
für die register.

als Beispiel:

warten:
  push R17
  in   R17, SREG
  push R17
  push R18
  push R19

; hier der eigentliche warten kram

  pop R19
  pop R18
  pop R17
  out SREG, R17
  pop R17
ret

dann kanst du das call warten beliebig einbauen.
oder du rufst "warten:" vernünftig auf:

    call warten
    CPI    r17, 255
    BRNE  main5

UND benutzt in "warten:" nicht das R17, R18 und R19

ausserdem vermisse ich ein
.cseg vor "init:"

Autor: Ralph (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Diese kaum lesbare und mit Fehler vollgestopfte Assemblerwurst ist 
wieder mal ein gutes Beispiel dafür in C zu programmieren und den 
Assemblercode vom Compiler erzeugen zu lassen.

Bevor man in Assembler programmieren kann MUSS man genau wissen wann 
welcher Befehl auf welche Register einwirkt, und wie das geschieht.

@ Heiner:
Leg den µC mal für ein paar Wochen oder Monate zur Seite und fang an zu 
lesen und zu lernen was der µC da bei den einzelnen Befehlen macht, oder 
nicht macht.

Solange du das nicht weißt, macht es keinen Sinn in Assembler 
rumzubasteln.

Autor: Heiner H. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also vielen Dank für eure Antworten.
Das mit den Registern hatte ich übersehen, denn ich hatte einfach einen 
Warteschleifengenerator verwendet.
Ich habe jetzt die Tipps befolgt und stelle das Programm nocheinmal 
verkürzt hier rein.  Jetzt müsste alles richtig sein, oder?
Achso, muss ich die Register immer sichern wenn ich in ein UP springe 
oder nur wenn ich im UP diese Register verwende?
[avrasm]
;***************************************
.include "m16def.inc"
;***************************************

.def temp = r16
.def schieb = r17
.def aus = r18
.def an = r19
.org 0x0000
        rjmp    init                  ; Reset Handler
.org OVF0addr
.cseg

init:  ldi     temp, LOW (RAMEND)    ; Stackpointer initialisieren
        out     SPL, temp
        ldi     temp, HIGH (RAMEND)
        out     SPH, temp
    LDI    R22, 0b11111111     ;initialisieren
    OUT    DDRA, r22
    OUT    DDRB, r22
    OUT    DDRC, r22
    OUT    DDRD, r22
    LDI    aus, 0b00000000
    LDI    an, 0b11111111
main:  LDI    schieb, 0b00000001  ;aufbau in rot
main1:  ROR    schieb
    out    PORTA, schieb
    CPI    schieb, 0b11111111
    call warten
    BRNE  main1
main2:  LDI    schieb, 0b00000001
main3:  ROR    schieb
    out    PORTB, schieb
    CPI    schieb, 0b11111111
    BRNE  main3
    call warten
    out    PORTA, aus    ;alles aus
    out    PORTB, aus
; warte 1999998 Zyklen:
warten:   ldi  R23, $12
WGLOOP0:  ldi  R24, $BC
WGLOOP1:  ldi  R25, $C4
WGLOOP2:  dec  R25
          brne WGLOOP2
          dec  R24
          brne WGLOOP1
          dec  R23
          brne WGLOOP0
ret

Autor: Heiner H. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also vielen Dank für eure Antworten.
Das mit den Registern hatte ich übersehen, denn ich hatte einfach einen 
Warteschleifengenerator verwendet.
Ich habe jetzt die Tipps befolgt und stelle das Programm nocheinmal 
verkürzt hier rein.  Jetzt müsste alles richtig sein, oder?
Achso, muss ich die Register immer sichern wenn ich in ein UP springe 
oder nur wenn ich im UP diese Register verwende?
;***************************************
.include "m16def.inc"
;***************************************

.def temp = r16
.def schieb = r17
.def aus = r18
.def an = r19
.org 0x0000
        rjmp    init                  ; Reset Handler
.org OVF0addr
.cseg

init:  ldi     temp, LOW (RAMEND)    ; Stackpointer initialisieren
        out     SPL, temp
        ldi     temp, HIGH (RAMEND)
        out     SPH, temp
    LDI    R22, 0b11111111     ;initialisieren
    OUT    DDRA, r22
    OUT    DDRB, r22
    OUT    DDRC, r22
    OUT    DDRD, r22
    LDI    aus, 0b00000000
    LDI    an, 0b11111111
main:  LDI    schieb, 0b00000001  ;aufbau in rot
main1:  ROR    schieb
    out    PORTA, schieb
    CPI    schieb, 0b11111111
    call warten
    BRNE  main1
main2:  LDI    schieb, 0b00000001
main3:  ROR    schieb
    out    PORTB, schieb
    CPI    schieb, 0b11111111
    BRNE  main3
    call warten
    out    PORTA, aus    ;alles aus
    out    PORTB, aus
; warte 1999998 Zyklen:
warten:   ldi  R23, $12
WGLOOP0:  ldi  R24, $BC
WGLOOP1:  ldi  R25, $C4
WGLOOP2:  dec  R25
          brne WGLOOP2
          dec  R24
          brne WGLOOP1
          dec  R23
          brne WGLOOP0
ret

Autor: Heiner H. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also jetzt scheint es endlich zu funktionieren :).
Nur bei PortC noch nicht.
Ihr hattet was mit dem JTAG gesagt.
Muss ich diesen setzen? Bei PonyProg steht da JTAGEN. dort muss ich dann 
wohl noch ein Häkchen reinsetzten?
mfg

Autor: Randy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Achso, muss ich die Register immer sichern wenn ich in ein UP springe
> oder nur wenn ich im UP diese Register verwende?

Scheinbar ist die der Grundlegende Aufbau einer CPU noch nicht klar. Die 
Register sind die Register. Da steht ein 8-Bit Wert drin, der der als 
letztes reingeschrieben wurde. Wenn also eine Unterroutine (oder keine 
Unterroutine) etwas in ein Register schreibt, dann steht das da drin und 
er alte Wert ist weg. Die Warteroutine verändert also immer die Register 
23,24 und 25. Das musst du beachten wenn du die Register auch woanders 
im Programm benutzt.
Außerdem die Flags: Das ist auch nur ein Speicherplatz pro Flag. Mit 
BRNE übeprüfst du immer den aktuellen Stand des Zero-Flags. Dem Befehl 
ist es egal wann das Flag zum letzten mal verändert wurde. D.h. mit

[1]    CPI    schieb, 0b11111111
[2]    call warten
[3]    BRNE  main1

dem BRNE in Zeile 3 überprüfst du nicht was beim CPI in Zeile 1 als 
Ergebnis herausgekommen ist, sondern das BNRE in Zeile 3 prüft ob das 
Zero-Flag gesetzt ist. Nur das jeder Befehl sich eventuell auf das 
Zero-Flag auswirken kann (manche tun es, manche nicht). Und du hast ein 
ganzes Unterprogramm zwischen dem CPI[1] und dem BNRE[2]. Die ganzen 
DEC-Befehle im Unterprogramm verändern das Zero-Flag, speziell kann man 
im Unterprogramm sehen dass es über einen BRNE-Befehl verlassen wird, 
sprich wenn das Unterprogramm zurück kommt ist das Zero-Flag immer 
gesetzt, der BNRE in Zeile 3 springt also nie nach main1.
Das Unterprogramm verändert also die Register R22-24 und das 
Statusregister, sprich die Flags (du musst mal nachsehen welche Flags 
von LDI und DEC verändert werden).

Hast du schon mal in einer höheren Programmiersprache wie Basic,Pascal 
oder C programmiert? -> Wenn ja, steig auf C um. Das ist sehr viel 
übersichtlicher.

Randy

Autor: Heiner H. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also wenn ich bei main1 als erstes warte und dann den Vergleich anstelle 
müsste es ja gehen.
Mein Problem ist ja aber eigentlich nur, da bei PORTc kein Strom 
ankommt, außer an c4 und c6.
bei den anderen scheint es ja zu gehen, laut Multimeter.

Muss denn ein ein Häkchn bei dem JTAGEN rein?
Ich werde die Porsitino von dem warten nocheinmal verändern.

Heiner

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.