AVR Assembler Probleme/Fragen Interrupt

Gast #2638954
Lesenswert?

Hallo Community,

ich bin gerade am Verzweifeln. Meine Erfahrung mit Assembler 
Programmierung ist ziemlich dürftig. Deshalb drehe ich mich wohl seit 
knapp 3 Std im Kreis.
Als Hardware wird ein Atmega644P verwendet. Hier der Code:
(Fragen stehen danach)
1
;
2
;Includes
3
.include "PFAD/m644Pdef.inc"
4

5

6
;LEDs
7
.EQU LED_1 = 6
8
.EQU LED_2 = 5
9
.EQU LED_3 = 4
10

11
;Registernamen
12
.def temp1 = r16
13
.def zeichen = r17
14

15
;Berechnen der UBRR_VAL anhand der Baud und der CPU Frequenz
16
.equ BAUD = 9600
17
.equ F_CPU = 19660800
18
.equ UBRR_VAL = ((F_CPU+BAUD*8)/(BAUD*16)-1)
19

20

21
;Interrupts
22
.org 0x0000    ;Beginn des Programms (Bei Reset oder Power-Down)
23
  jmp MAIN
24
.org 0x0004
25
  jmp ISR_INT1
26

27

28
;;;;;;
29
;MAIN;
30
;;;;;;
31
MAIN:  
32
  call INIT
33
  ldi zeichen, "b"
34
  call UARTOUT
35
  
36
LOOP:
37
  ldi temp1, (1 << LED_1) | (1 << LED_2) | (1 << LED_3)
38
  out PORTD, temp1
39
  jmp LOOP
40

41
;;;;;;;;;;;
42
;Interrupt;
43
;;;;;;;;;;;
44
ISR_INT1:
45
LOOP1:
46
  ldi temp1, (0 << LED_1) | (0 << LED_2) | (0 << LED_3)
47
  out PORTD, temp1
48
  jmp LOOP1
49
  reti
50

51
UARTOUT:
52
  lds temp1, UCSR0A
53
  sbrs temp1, UDRE0
54
  jmp UARTOUT
55
  sts UDR0, zeichen
56
  ret
57

58
;;;;;;;;;;;;;;;;;
59
;INITIALISIERUNG;
60
;;;;;;;;;;;;;;;;;
61

62
INIT:
63

64
;PORT D
65
  ldi temp1, (1 << LED_1) | (1 << LED_2) | (1 << LED_3)
66
  out DDRD, temp1
67
  out PORTD, temp1
68

69
;UART Initiaisierung
70
  ldi temp1, (1 << RXEN0) | (1 << TXEN0)
71
  sts UCSR0B, temp1
72
  ldi temp1, (1 << UCSZ00) | (1 << UCSZ01)
73
  sts UCSR0C, temp1
74

75
;Baudrate festlegen
76
  ldi temp1, HIGH(UBRR_VAL)
77
  sts UBRR0H, temp1
78
  ldi temp1, LOW(UBRR_VAL)
79
  sts UBRR0L, temp1
80

81
;Pin Change Interrupt
82
  ldi temp1, 1 << PCIE2
83
  sts PCICR, temp1
84
  ldi temp1, (1 << PCINT16) | (1 << PCINT20)
85
  sts PCMSK2, temp1
86

87
;Externe Interrupts
88
  ldi temp1, 1 << ISC11
89
  sts EICRA, temp1
90
  ldi temp1, 1 << INT1
91
  sts EIMSK, temp1
92

93
;Stack Initialisieren
94
  ldi temp1, LOW(RAMEND)
95
  out SPL, temp1
96
  ldi temp1, HIGH(RAMEND)
97
  out SPH, temp1
98

99
  sei ;Interrupts aktivieren
100

101
  ret

1. Der Interrupt wird nicht ausgelöst. Mir ist wohl klar, dass es nicht 
sinnvoll ist den Controller in der ISR "gefangen" zu halten. Die 
Intention ist einfach die, dass die LEDs sichtbar angehen. Ich hab 
allerdings keine Erklärung dafür, die Interruptsregister sind gesetzt, 
die Globalen Interrupts aktiviert und die Einsprungadressen definiert.

2. Des Weiteren ist zu sehen, dass ein Zeichen ausgegeben wird, nachdem 
die Initiaisierung aufgerufen wurde. Dieses Zeichen gibt er aber nur 
dann aus, wenn Controller

a) Programmiert wurde
b) Aus/Eingeschalten wurde

NICHT aber wenn der RESET Knopf betätigt wurde. Warum ?

Alls Assembler wurde der gavrasm unter Linux verwendet. Der code wird 
fehlerfrei assembliert.

Freue mich auf eure Hilfe

Hochachtungsvoll
Quantum
Gast #2638981
Lesenswert?

Thomas P. schrieb:
> Einen Call init zu machen und erst danach den Stack zu initialisieren
> ist keine gute Idee.
>
> Thomas

Danke, dass löst schonmal das Problem mit dem Resettaster.


spess53 schrieb:
> Hi
>
>>ISR_INT1:
>>LOOP1:
>>  ldi temp1, (0 << LED_1) | (0 << LED_2) | (0 << LED_3)
>>  out PORTD, temp1
>>  jmp LOOP1
>>  reti
>
> Und wie soll der Controller hier wieder rauskommen?
>
> MfG Spess
Das ist rein zum Testen. Will erstmal dass er überhaupt reinspringt. 
Wenn er das dann tun sollte wird das mit sinnvollem Code belegt.

Grüße
#2639077
Lesenswert?

wie hast du INT1 am Contoller beschaltet?

es ist keine gute Idee den PCINT einzuschalten, aber keine entsprechende 
ISR zu haben - dann springt er dir u.U. irgendwo ins Programm rein.
Am besten immer die komplette Interrupttabelle ins Program einbauen, und 
alle nicht benötigten ISR's mit RETI 'kurzschließen'!

Sascha
Gast #2639091
Lesenswert?

Sascha Weber schrieb:
> wie hast du INT1 am Contoller beschaltet?
>
> es ist keine gute Idee den PCINT einzuschalten, aber keine entsprechende
> ISR zu haben - dann springt er dir u.U. irgendwo ins Programm rein.
> Am besten immer die komplette Interrupttabelle ins Program einbauen, und
> alle nicht benötigten ISR's mit RETI 'kurzschließen'!
>
> Sascha

Danke für deine Antwort

Die ISR, die den PCINT2 abarbeitet ist implementiert. Übersichshalber 
hab ich den Code etwas gekürzt. Nach weiterem experimentieren ist mir 
aufgefallen, dass der PCINT16 Pin auf einen Interrupt anspricht. Der 
PCINT20 jedoch nicht. Bei beim INT1 Interrupt hat sich immer noch nichts 
getan.

Der INT1 Pin ist mit nem PullUp und nem Taster beschalten, der den Pin 
dann auf Masse zieht.

Gruß
Gast #2639127
Lesenswert?

> UARTOUT:
>   lds temp1, UCSR0A
>   sbrs temp1, UDRE0
>   jmp UARTOUT
>   sts UDR0, zeichen
>   ret

sbrs templ,UDRE0

hmm hieß sbrs nicht "skip if bits in Register are set" und als operand 
dahinter eine Bitmaske ?
also : sbrs templ,1<<UDRE0
Gast #2639158
Lesenswert?

Mark L. schrieb:
> Quantum schrieb:
>> Der
>> PCINT20 jedoch nicht.
>
> JTAG aktiviert??

JTAG hab ich mithilfe den Fuses deaktiviert

Uwe schrieb:
>> UARTOUT:
>>   lds temp1, UCSR0A
>>   sbrs temp1, UDRE0
>>   jmp UARTOUT
>>   sts UDR0, zeichen
>>   ret
>
> sbrs templ,UDRE0
>
> hmm hieß sbrs nicht "skip if bits in Register are set" und als operand
> dahinter eine Bitmaske ?
> also : sbrs templ,1<<UDRE0

Wenn ich das so mache bringt mir der Assembler einen Fehler. Die Ausgabe 
funktioniert ja auch.

Danke für die Hilfe

Gruß
Gast #2639271
Lesenswert?

Mark L. schrieb:
> Bist du sicher, dass kein Kurzschluss zwischen PD3 und PD4 ist? Du
> könntest auch mal einfach in der Hauptschleife den Taster abfragen und
> die LEDs ohne INT1 schalten.
>
> Ha, nochmal in's Datenblatt geschaut: Hab den Fehler! (glaub ich)
> sts EIMSK ist falsch, muss out EIMSK sein!
>
> Mark

Danke !!
Es funktioniert :)

Darf ich erfahren wie du das herausgefunden hast, bzw wo das steht. Was 
hat dieses Register mit den I/O Registern zu tun ? Oder hab ich das mit 
dem out falsch verstanden ?

Das Problem mit dem Pin Chang Interrupt auf PCINT20 bleibt allerdings. 
PCINT16 funktioniert. Obwohl ich beide eingeschalten habe.
Gast #2639307
Lesenswert?

spess53 schrieb:
> Hi
>
>>Das Problem mit dem Pin Chang Interrupt auf PCINT20 bleibt allerdings.
>>PCINT16 funktioniert. Obwohl ich beide eingeschalten habe.
>
> Hast du die Frage
>
> Beitrag "Re: AVR Assembler Probleme/Fragen Interrupt"
>
> beachtet?
>
> MfG Spess

Wie ich schon geschrieben habe, ist JTAG abgeschaltet. Die ISR wird mit 
einem entsperechendem C Programm problemlos, an beiden Pins, aufgerufen
(Firma: TH Köln) Persönliche Seite #2639574
Lesenswert?

Quantum schrieb:
> Darf ich erfahren wie du das herausgefunden hast, bzw wo das steht. Was
> hat dieses Register mit den I/O Registern zu tun ? Oder hab ich das mit
> dem out falsch verstanden ?

Das out geht für alle Register bis 0x5F Die Adresse ist bei out aber um 
0x20 versetzt. Alles was mit out erreichbar ist, steht auch mit der 
out-Adresse in der *def.inc, daher führt sts zum Beschreiben eines 
falschen IO-Registers. Ist manchmal etwas nervig bei den Atmels, gibt 
immer wieder Unterschiede. Steht einmal in der *def.inc und im 
Datenblatt die IO-Register mit den doppelten Adressen.

In kurzen Programmen sind das und die sbr/sbrs-Geschichte so 
Fehlerquellen, die man einfach nicht direkt sieht und die die 
Fehlersuche selbst in einem 20-Zeiler zur nervenaufreibenden Sache 
werden lassen.

Mark
#2639608
Lesenswert?

Mark L. schrieb:
> Das out geht für alle Register bis 0x5F Die Adresse ist bei out aber um
> 0x20 versetzt. Alles was mit out erreichbar ist, steht auch mit der
> out-Adresse in der *def.inc, daher führt sts zum Beschreiben eines
> falschen IO-Registers. Ist manchmal etwas nervig bei den Atmels, gibt
> immer wieder Unterschiede.


IN, LD, LDI, LDD, LDS, MOV, OUT, ST, STD, STS

... und dann auch noch mit unterschiedlichen Adressen, je nach Befehl 
...
Manchmal habe ich den Eindruck, daß hier völlige Anfänger den 
Befehlssatz entworfen haben. Man könnte meinen, daß sie nicht mal den 
8051 kannten. Dort gibt es einen Befehl für alle diese (und noch 
weitere) Aktionen: MOV
Um den Rest kümmert sich der Kompiler. Und genau von dem erwarte ich 
diese Leistung!

Wenn man ein Programm von einem AVR in einen anderen überträgt, kann es 
bei SFRs die dort an anderer Stelle hocken, passieren, daß man IN und 
OUT gegen LDS und STS tauschen muß. Es gibt nicht mal eine Meckermeldung 
vom Kompiler. Also muß ich von Hand heraussuchen, welches SFR nun in 
welchem Bereich sitzt. Da kann ich die Adresse auch gleich von Hand 
eintragen!

*kopfschüttel** - Die Dinger sind eigentlich völliger Murks!


Gruß

Jobst
Gast #2639702
Lesenswert?

Hi

>Den gleichen Eindruck habe ich auch seit dem Umstieg an die AVRs. Im
>Gegensatz zum 51er ist der Befehlssatz aus Sicht eines
>Assemblerprogrammierers einfach Schrott.

Dann macht doch einen eigenen Thread dazu auf. Dort könnt ihr euren 
Frust in aller Ruhe ausdiskutieren.

@Quantum (Gast)

Im Anhang ein kurzer Test. Funktioniert problemlos.

MfG Spess
Angehängte Dateien:
Gast #2640124
Lesenswert?

Mark L. schrieb:
> Quantum schrieb:
>> Darf ich erfahren wie du das herausgefunden hast, bzw wo das steht. Was
>> hat dieses Register mit den I/O Registern zu tun ? Oder hab ich das mit
>> dem out falsch verstanden ?
>
> Das out geht für alle Register bis 0x5F Die Adresse ist bei out aber um
> 0x20 versetzt. Alles was mit out erreichbar ist, steht auch mit der
> out-Adresse in der *def.inc, daher führt sts zum Beschreiben eines
> falschen IO-Registers. Ist manchmal etwas nervig bei den Atmels, gibt
> immer wieder Unterschiede. Steht einmal in der *def.inc und im
> Datenblatt die IO-Register mit den doppelten Adressen.
>
> In kurzen Programmen sind das und die sbr/sbrs-Geschichte so
> Fehlerquellen, die man einfach nicht direkt sieht und die die
> Fehlersuche selbst in einem 20-Zeiler zur nervenaufreibenden Sache
> werden lassen.
>
> Mark

Danke, hab´s nun verstanden. In der *def.inc ist das sehr übersichtlich 
dargestellt.

spess53 schrieb:
> Hi
>
>>Den gleichen Eindruck habe ich auch seit dem Umstieg an die AVRs. Im
>>Gegensatz zum 51er ist der Befehlssatz aus Sicht eines
>>Assemblerprogrammierers einfach Schrott.
>
> Dann macht doch einen eigenen Thread dazu auf. Dort könnt ihr euren
> Frust in aller Ruhe ausdiskutieren.
>
> @Quantum (Gast)
>
> Im Anhang ein kurzer Test. Funktioniert problemlos.
>
> MfG Spess

Es funktioniert nun auch, lag an der externen Beschaltung.
Ich bedanke mich bei allen Problemlösern. Habt mir wirklich sehr 
geholfen.

Grüße

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren