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


von Heiner H. (Gast)


Lesenswert?

hallo,
also ich habe jetzt ein programm geschrieben, für den Atmega16.
1
;***************************************
2
.include "m16def.inc"
3
;***************************************
4
5
.def temp = r16
6
.org 0x0000
7
        rjmp    init                  ; Reset Handler
8
.org OVF0addr
9
10
init:  ldi     temp, LOW (RAMEnD)    ; Stackpointer initialisieren
11
        out     SPL, temp
12
        ldi     temp, HIGH (RAMEnD)
13
        out     SPH, temp
14
    LDI    R22, 255    ;initialisieren
15
    OUT    DDRA, r22
16
    OUT    DDRB, r22
17
    OUT    DDRC, r22
18
    OUT    DDRD, r22
19
    LDI    r18, 0
20
    LDI    r19, 255
21
main:  LDI    R17, 0b00000001  ;aufbau in rot
22
main1:  ROR    r17
23
    out    PORTA, r17
24
    CPI    r17, 255
25
    call warten
26
    BRNE  main1
27
main2:  LDI    R17, 0b00000001
28
main3:  ROR    r17
29
    out    PORTB, r17
30
    CPI    r17, 255
31
    BRNE  main3
32
    call warten
33
    out    PORTA, r18    ;alles aus
34
    out    PORTB, r18
35
main4:  LDI    R17, 0b00000001  ;aufbau in grün
36
main5:  ROR    r17
37
    out    PORTC, r17
38
    CPI    r17, 255
39
    call warten
40
    BRNE  main5
41
main6:  LDI    R17, 0b00000001
42
main7:  ROR    r17
43
    out    PORTD, r17
44
    CPI    r17, 255
45
    BRNE  main7
46
    call warten
47
    out    PORTC, r18    ;alles aus
48
    out    PORTD, r18
49
main8:  LDI    R17, 0b00000001  ;aufbau in orange
50
main9:  ROR    r17
51
    out    PORTA, r17
52
    out    PORTC, r17
53
    CPI    r17, 255
54
    call warten
55
    BRNE  main9
56
main10:  LDI    R17, 0b00000001
57
main11:  ROR    r17
58
    out    PORTB, r17
59
    out    PORTD, r17
60
    CPI    r17, 255
61
    BRNE  main11
62
    call warten
63
    out    PORTA, r18    ;alles aus
64
    out    PORTB, r18
65
    out    PORTC, r18
66
    out    PORTD, r18
67
    nop
68
    call warten
69
    out    PORTA, r19    ;schrift rot  
70
    out    PORTB, r19
71
    nop
72
    call warten
73
    out    PORTA, r18    ;alles aus
74
    out    PORTB, r18
75
    out    PORTC, r19    ;alles grün
76
    out    PORTD, r19
77
    nop
78
    call warten
79
    out    PORTC, r18    ;alles aus
80
    out    PORTD, r18
81
    out    PORTA, r19    ;alles orange
82
    out    PORTB, r19
83
    out    PORTC, r19    
84
    out    PORTD, r19
85
    nop
86
    call warten
87
    out    PORTA, r18    ;alles aus
88
    out    PORTB, r18
89
    out    PORTC, r18    
90
    out    PORTD, r18
91
92
    rjmp  main
93
94
; warte 1999998 Zyklen:
95
warten:  ldi  R17, $12
96
WGLOOP0:  ldi  R18, $BC
97
WGLOOP1:  ldi  R19, $C4
98
WGLOOP2:  dec  R19
99
          brne WGLOOP2
100
          dec  R18
101
          brne WGLOOP1
102
          dec  R17
103
          brne WGLOOP0 
104
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

von VZP (Gast)


Lesenswert?

Und die fuses sind richtig ?

von Jörg X. (Gast)


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
1
main:
2
    LDI    R17, 0b00000001  ;aufbau in rot
3
main1:
4
    ROR    r17
5
    out    PORTA, r17
6
    call warten ;hab ich getauscht, fuer mehr Uebersicht
7
    CPI    r17, 255
8
    BRNE  main1
Um da 1en reinzuRORen, müsstest du das Carry-Bit setzen. Abgesehen von 
Punkt 1)

hth. Jörg

von Karl H. (kbuchegg)


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.

von AVRFan (Gast)


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...

von Tim (Gast)


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:"

von Ralph (Gast)


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.

von Heiner H. (Gast)


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

von Heiner H. (Gast)


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?
1
;***************************************
2
.include "m16def.inc"
3
;***************************************
4
5
.def temp = r16
6
.def schieb = r17
7
.def aus = r18
8
.def an = r19
9
.org 0x0000
10
        rjmp    init                  ; Reset Handler
11
.org OVF0addr
12
.cseg
13
14
init:  ldi     temp, LOW (RAMEND)    ; Stackpointer initialisieren
15
        out     SPL, temp
16
        ldi     temp, HIGH (RAMEND)
17
        out     SPH, temp
18
    LDI    R22, 0b11111111     ;initialisieren
19
    OUT    DDRA, r22
20
    OUT    DDRB, r22
21
    OUT    DDRC, r22
22
    OUT    DDRD, r22
23
    LDI    aus, 0b00000000
24
    LDI    an, 0b11111111
25
main:  LDI    schieb, 0b00000001  ;aufbau in rot
26
main1:  ROR    schieb
27
    out    PORTA, schieb
28
    CPI    schieb, 0b11111111
29
    call warten
30
    BRNE  main1
31
main2:  LDI    schieb, 0b00000001
32
main3:  ROR    schieb
33
    out    PORTB, schieb
34
    CPI    schieb, 0b11111111
35
    BRNE  main3
36
    call warten
37
    out    PORTA, aus    ;alles aus
38
    out    PORTB, aus
39
; warte 1999998 Zyklen:
40
warten:   ldi  R23, $12
41
WGLOOP0:  ldi  R24, $BC
42
WGLOOP1:  ldi  R25, $C4
43
WGLOOP2:  dec  R25
44
          brne WGLOOP2
45
          dec  R24
46
          brne WGLOOP1
47
          dec  R23
48
          brne WGLOOP0
49
ret

von Heiner H. (Gast)


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

von Randy (Gast)


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

von Heiner H. (Gast)


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

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.