Hallo
Ich versuche gerade was mit meinem Atmega8 und dem avr-gcc:
Wenn an PD2 oder PD3 (Die Interrupteingänge) eine fallende Flanke kommt,
soll eine LED an PB0 leuchten. An PD2 und PD3 sind Taster angeschlossen,
die den Pegel beim Drücken auf low ziehen.
Folgendes funktioniert super (geklaut vom avr-Tutorial von
Mikrocontroller.net, die beiden Zeilen, die einen Wert in PortD laden
habe ich hinzugefügt, wollte gucken, ob das ganze auch mit Pullups an
den Interrupteingängen läuft) Das Programm schaltet die LED in einer
Routine an, in der anderen aus.
1
.include "m8def.inc"
2
3
.def temp = r16
4
5
.org 0x000
6
rjmp main ; Reset Handler
7
.org INT0addr
8
rjmp int0_handler ; IRQ0 Handler
9
.org INT1addr
10
rjmp int1_handler ; IRQ1 Handler
11
12
13
main: ; hier beginnt das Hauptprogramm
14
15
ldi temp, LOW(RAMEND)
16
out SPL, temp
17
ldi temp, HIGH(RAMEND)
18
out SPH, temp
19
20
ldi temp, 0x00
21
out DDRD, temp
22
23
ldi temp, 0b00001100
24
out PORTD, temp
25
26
ldi temp, 0xFF
27
out DDRB, temp
28
29
ldi temp, (1<<ISC01) | (1<<ISC11) ; INT0 und INT1 auf fallende Flanke konfigurieren
30
out MCUCR, temp
31
32
ldi temp, (1<<INT0) | (1<<INT1) ; INT0 und INT1 aktivieren
33
out GICR, temp
34
35
sei ; Interrupts allgemein aktivieren
36
37
loop: rjmp loop ; eine leere Endlosschleife
38
39
int0_handler:
40
sbi PORTB, 0
41
reti
42
43
int1_handler:
44
cbi PORTB, 0
45
reti
Mein C-Programm läuft hingegen nicht:
1
#define F_CPU 3686400UL
2
#include<avr/io.h>
3
#include<avr/interrupt.h>
4
5
6
7
intmain(void){
8
SP=RAMEND;
9
DDRD=0x00;//PortD als Interrupteingang
10
PORTD=0b00001100;//Pullups am Interrupteingang
11
DDRB=0xFF;//Port B als LED-Ausgang (LED an PB0)
12
MCUCR=(1<<ISC11)|(1<<ISC01);//Flankenverhalten setzen, Int0 und Int1 bei fallender Flanke auslösen
13
GICR=(1<<INT0)|(1<<INT1);//INT0 und INT1 aktivieren
14
15
16
sei();//Interruptflag setzen
17
18
while(1){
19
}
20
21
return0;
22
}
23
24
ISR(INT0_vect){
25
PORTB|=0b00000001;
26
}
27
28
ISR(INT1_vect){
29
PORTB|=0b00000001;
30
}
Der vom Compiler erzeugte Assemblercode:
1
.file "main.c"
2
__SP_H__ = 0x3e
3
__SP_L__ = 0x3d
4
__SREG__ = 0x3f
5
__tmp_reg__ = 0
6
__zero_reg__ = 1
7
.section .text.startup,"ax",@progbits
8
.global main
9
.type main, @function
10
main:
11
/* prologue: function */
12
/* frame size = 0 */
13
/* stack size = 0 */
14
.L__stack_usage = 0
15
ldi r24,lo8(95)
16
ldi r25,lo8(4)
17
out __SP_L__+1,r25
18
out __SP_L__,r24
19
out 0x11,__zero_reg__
20
ldi r24,lo8(12)
21
out 0x12,r24
22
ldi r24,lo8(-1)
23
out 0x17,r24
24
ldi r24,lo8(10)
25
out 0x35,r24
26
ldi r24,lo8(-64)
27
out 0x3b,r24
28
/* #APP */
29
; 17 "main.c" 1
30
sei
31
; 0 "" 2
32
/* #NOAPP */
33
.L2:
34
rjmp .L2
35
.size main, .-main
36
.text
37
.global __vector_1
38
.type __vector_1, @function
39
__vector_1:
40
push r1
41
push r0
42
in r0,__SREG__
43
push r0
44
clr __zero_reg__
45
/* prologue: Signal */
46
/* frame size = 0 */
47
/* stack size = 3 */
48
.L__stack_usage = 3
49
sbi 0x18,0
50
/* epilogue start */
51
pop r0
52
out __SREG__,r0
53
pop r0
54
pop r1
55
reti
56
.size __vector_1, .-__vector_1
57
.global __vector_2
58
.type __vector_2, @function
59
__vector_2:
60
push r1
61
push r0
62
in r0,__SREG__
63
push r0
64
clr __zero_reg__
65
/* prologue: Signal */
66
/* frame size = 0 */
67
/* stack size = 3 */
68
.L__stack_usage = 3
69
sbi 0x18,0
70
/* epilogue start */
71
pop r0
72
out __SREG__,r0
73
pop r0
74
pop r1
75
reti
76
.size __vector_2, .-__vector_2
77
.ident "GCC: (GNU) 4.7.2"
Es leuchtet einfach nichts mit dem C-Programm. Egal was passiert.
Und noch etwas: Die Adresse des MCUCR, dessen Wert ich auch im
C-Beispiel verändere ist 0x35. Im C-Code des Compilers taucht die
Adresse nirgens auf. Wenn ich im Programm in der leeren while-Schleife
den Wert von MCUCR mit LED's überprüfe, ist das Register aber wie
gewünscht gesetzt. Wie kommt das?
Gruß
Joschua
STK500-Besitzer schrieb:> mach mal den PortB zum Ausgang, wenn du ihn benutzen willst.
was soll er denn da noch machen?
> DDRB=0xFF; //Port B als LED-Ausgang (LED an PB0)
Um den Inhalt der ISR als Fehlerquelle auszuschließen, ab ich
PORTB |= 0b00000001;
verwendet. Eine Zeile, LED anschalten, wenn eine Routine ausgeführt
wird. Die Zeile habe ich dann nochmal in main getestet und benutze sie
jetzt. Das dadurch nichts um- sondern nur angeschaltet wird, ist mir
schon klar. Ich wollte möglichst alle Fehlerquellen reduzieren und ne
Menge Google befragen und dann hier rumheulen.
Es ist sinnvoll die verwendete Hardware zu nenen oder zu beschreiben
(Schaltplan). Üblicherweise sind LEDs mit Low zum leuchen zu bringen.
Was mir auch merkwürdig vorkommt ist die Zuweisung an den Stack-Pointer
am Anfang. Lösche die mal raus. Sie ist unnötig.
Hululu schrieb:> Es ist sinnvoll die verwendete Hardware zu nenen oder zu beschreiben> (Schaltplan). Üblicherweise sind LEDs mit Low zum leuchen zu bringen.
wenn das ASM fehlerfrei arbeitet, braucht man wohl nicht über die
Hardware zu wissen. Es gibt nur um den Vergleich der beiden Programm auf
der gleichen Hardware.
hp-freund hat vermutlich das Problem schon gefunden
Wir sollten nur noch wissen ob die LED gegen GND oder VCC angeschlossen
ist.
Joschua C. schrieb:> Die Adresse des MCUCR, dessen Wert ich auch im> C-Beispiel verändere ist 0x35. Im C-Code des Compilers taucht die> Adresse nirgens auf.
ldi r24,lo8(10)
out 0x35,r24
Mmh. Das Setzen von MCUCR hab ich wohl übersehen. Danke.
Die LED ist gegen GND angeschlossen. Den Inhalt von den ISRs habe ich
auch schon mal in die Endlosschleife geschrieben => LED hat geleuchtet.
Hululu schrieb:> Es ist sinnvoll die verwendete Hardware zu nenen oder zu beschreiben> (Schaltplan). Üblicherweise sind LEDs mit Low zum leuchen zu bringen.>> Was mir auch merkwürdig vorkommt ist die Zuweisung an den Stack-Pointer> am Anfang. Lösche die mal raus. Sie ist unnötig.
Erledigt. Geht leider auch nicht.
Hi
>Was mir auch merkwürdig vorkommt ist die Zuweisung an den Stack-Pointer>am Anfang. Lösche die mal raus. Sie ist unnötig.
Beim ATMega8 wird der Stackpointer nicht automatisch geladen. Also
notwendig.
MfG Spess
spess53 schrieb:> Beim ATMega8 wird der Stackpointer nicht automatisch geladen. Also> notwendig.
das macht der Compiler, um so etas muss man sich bei C nicht kümmern.
Joschua C. schrieb:> Gut, ist wieder drin.
machst wieder raus. Man müsste es wenn man es selber macht vor main
machen. Denn main ist selber schon eine Funktion die etwas auf dem Stack
ablegt.
Peter II schrieb:> das macht der Compiler, um so etas muss man sich bei C nicht kümmern.
Hui. Ihr antwortet immer so schnell. Schneller als ich tippen kann.
Danke =D
http://www.rn-wissen.de/index.php/Avr-gcc#Abk.C3.BCrzungen_und_Bezeichnungen
Verstehe ich das richtig: Wenn man am Stackpointer rumfummelt, ohne den
gcc zu informieren, werden Interrupts deaktiviert? Siehe -mno-interrupts
unter "Maschinenspezifische Optionen für avr-gcc"
>http://www.rn-wissen.de/index.php/Avr-gcc#Abk.C3.B...>Verstehe ich das richtig: Wenn man am Stackpointer rumfummelt, ohne den>gcc zu informieren, werden Interrupts deaktiviert?
Wo steht das in dem von Dir verlinkten Dokument?
Also ich gebs jetzt auf, da Du andauern Deine Beiträge so änderst, das
Deine Fragen und unsere Antworten irrelevant werden. Falls Du auf eine
Frage antwortest, tue das nach der Frage nicht in dem Beitrag der die
Frage erst aufgeworfen hat.
Tschüss
Hululu schrieb:>>http://www.rn-wissen.de/index.php/Avr-gcc#Abk.C3.B...>>>Verstehe ich das richtig: Wenn man am Stackpointer rumfummelt, ohne den>>gcc zu informieren, werden Interrupts deaktiviert?>> Wo steht das in dem von Dir verlinkten Dokument?
"-mno-interrupts
Ändert den Stackpointer ohne Interrupts zu deaktivieren"
Hab den falschen Abschnitt verlinkt. Tschuldigung.
Wenns nicht so wäre, bräuchte man die Option nicht, oder?
Joschua C. schrieb:> Wenns nicht so wäre, bräuchte man die Option nicht, oder?
Das bezieht sich darauf, wenn der Compiler den SP verändert. Auf deine
manuelle Änderung hat das keinen Einfluss. Verbeis dich nicht darin,
nimmt die Zeile einfach raus, und gut ist. Ursache deines eigentlichen
Problems ist das höchstwahrscheinlich eh nicht.
Wenn Interrupts nicht funktionieren, obwohl eigentlich alles gut
aussieht, dann liegt das in der Regel an Problemen im Build-Process
(z.B. nicht für den richtigen Controller gelinkt). Also poste mal den
kompletten Build-Output.
Ursache deines Problems ist das hier:
> avr-gcc ... -o main.hex ...
Der Compiler produziert eine ELF-Datei. Da kommt keine fertig brennbare
HEX-Datei raus, nur weil du der Datei eine entsprechende Endung
verpasst. Du musst die HEX-Datei erst aus der ELF-Datei mittels objcopy
extrahieren.
Hululu schrieb:> Da hat es keine Fehlermeldung gegeben, als beim Flashen versucht wurde> eine ELF-Datei als eine Hex-Datei zu interpretieren?
Das Brenn-Programm wird die Endung ignoriert und die Datei einfach als
binäres Image betrachtet haben. Einfacher Code funktionieren dann sogar
meist. Da der Code aber nicht an der richtigen Adresse im Controller
liegt, gehören Interrupts zu den Dingen, die dann garantiert nicht
funktionieren.
>Das Brenn-Programm wird die Endung ignoriert und die Datei einfach als>binäres Image betrachtet haben.
Das wird wohl vermutlich so sein. Ist schon klar.
Aber es geht um was anderes (Zaunpfahl heraushol): Wir wissen ja
garnicht was für ein Brenn-Programm der TO verwendet. Warum wissen wir
das nicht?
LED blinken usw. hat auch funktioniert. Ich hab mich schon gewundert,
warum so ein popeliges Programm 3k Flash braucht? Arbeite aber gerade
zum ersten Mal mit C und Controllern, hab da so keinen schlimmen
Verdacht geschöpft.
Was muss ich denn mit objcopy für die Quelldatei für bfdname angeben?
Und wieso kann ich nicht einfach gcc -c verwenden? Dann erkennt avrdude
das Format nicht.
Joschua C. schrieb:> Was muss ich denn mit objcopy für die Quelldatei für bfdname angeben?
Nichts. Eine ELF-Datei ist der "natürliche" Input für objcopy. Nur wenn
du es mit was anderem füttern willst, musst du das näher spezifizieren.
Joschua C. schrieb:> Und wieso kann ich nicht einfach gcc -c verwenden?
Weil da kein fertig gelinktes Programm raus kommt, sondern nur ein
Objekt-Modul.
PS:
Du würdest dich leichter tun, wenn du einfach ein erprobtes Makefile
verwenden würdest, z.B. eines das von MFile erzeugt wurde.
avr-objcopy -O binary main.hex main
Das hats gelöst.
Ja, makefile klingt gut. Habe ich mir bei der C-Entwicklung für Linux
auch irgendwann gebaut. Wird halt später immer zu viel.
Joschua C. schrieb:> avr-objcopy -O binary main.hex main>> Das hats gelöst.
Nur dass deine Namenswahl für den Compiler-Output mit main.hex immer
noch sehr unglücklich ist.