Hallo zusammen,
ich habe mich jetzt dazu entschlossen, mir Assembler anzueignen, da kein
Weg daran vorbei führt.
Ich bin jetzt bei den Interrupts, aber irgendwie will das Ganze nicht so
ganz.
Du hast Timer0 nicht eingeschaltet und du brauchst die Register nicht zu
speichern weil die atomatisch geschpeichert werden mit der RETFIE FAST
Anweisung.Ausserdem ist es sowieso nicht richtig gemacht.
David M. schrieb:> ich habe mich jetzt dazu entschlossen, mir Assembler anzueignen, da kein> Weg daran vorbei führt.
Wie kommst Du zu dieser irrigen Annahme?
Die Compilerbauer und ihre Kunden verdienen jedenfalls gutes Geld mit
ihren Produkten.
Vor 30 Jahren mag Assembler in der MC-Welt eine Rolle gespielt haben.
Aber jetzt ist er nur noch in Nischenanwendungen zu finden.
Es schadet natürlich nichts, wenn man in Assembler soweit fit ist, daß
man ein Compilerlisting ungefähr verstehen kann.
Peter
Peter Dannegger schrieb:> Vor 30 Jahren mag Assembler in der MC-Welt eine Rolle gespielt haben.> Aber jetzt ist er nur noch in Nischenanwendungen zu finden.
AUA
@ David M.
Fehler 1: Du mußt am Ende der ISR Deine geretteten Registerinhalte
zurückschreiben.
Fehler 2: Hinter dem Label isr_high_sub wird kein Doppelpunkt
geschrieben.
Hallo,
@ Peter Dannegger: Ich habe bis vor kurzem auch noch alles mit C
gemacht. Hat auch alles soweit funktioniert. Nur war mir manchmal
schleierhaft, was der Compiler da eigentlich macht. Wenn ich zum
Beispiel jetzt den Timer0 in C implementiere, ist das Programm um das 5-
fache(oder auch mehr) größer(Benutze den High- Tech Compiler), als wenn
ich das in Assembler mache. Ok, wie man sieht, funktioniert der Timer
zwar noch nicht, aber da ist irgendwie nur ein kleiner blöder Fehler
drin ;)
@ kalle wirsch: Danke für die Antwort, das mit dem doppelpunkt ist mir
gestern Abend schon aufgefallen. Ich wollte dafür aber nicht extra einen
Doppelpost riskieren. Das mit dem Zurückschreiben stimmt. Ich habe das
schon früher zurückgeschrieben, als es eigentlich sein sollte. Hier der
Code- Update:
1
org 400
2
Init
3
CLRF PORTA ; PortA delete
4
CLRF TRISA ; All output
5
CLRF ANSELA; All digital output
6
7
CLRF PORTC ; PortA delete
8
CLRF TRISC ; All output
9
CLRF ANSELC; All digital output
10
11
MOVLW B'10000111'
12
MOVWF T0CON
13
14
MOVLW B'11000010'
15
MOVWF TMR0H
16
17
MOVLW B'11110110'
18
MOVWF TMR0L
19
20
BSF INTCON, GIE
21
BSF INTCON, TMR0IF
22
BSF INTCON, TMR0IE
23
24
BSF PORTA, RA0
25
26
loop
27
GOTO loop
28
29
isr_high_sub
30
MOVWF w_copy
31
SWAPF STATUS, w
32
MOVWF s_copy
33
34
BSF PORTC,RC0
35
36
MOVLW B'11000010'
37
MOVWF TMR0H
38
39
MOVLW B'11110110'
40
MOVWF TMR0L
41
42
BCF INTCON, TMR0IF ; Timerinterruptflag delete
43
44
SWAPF s_copy, w
45
MOVWF STATUS
46
SWAPF w_copy, f
47
SWAPF w_copy, w
Ich benutze Portc als meinen "Debug- Port", um mir Sachen ausgeben zu
lassen. An RC0 hängt eine LED dran. Diese leuchtet aber nicht, womit ich
befürchte, dass er nicht einmal in die Interruptroutine reinspringt. Ich
benutze ein Demoboard vom Franzis- Verlag. In dem Handbuch steht, dass
die Adressen von 0 bis 400 vom Bootloader in anspruch genommen werden
und auf keinen Fall überschrieben werden dürfen. Liegt da vielleicht das
Problem? Die Einsprungadresse der Interrupts liegen ja bei 8 bzw 18?
In der ISR brauchst du die Regisater nicht zu sichern/wiederherstellen.
Die Abschnitte
" MOVWF w_copy
SWAPF STATUS, w
MOVWF s_copy
"
und
"
SWAPF s_copy, w
MOVWF STATUS
SWAPF w_copy, f
SWAPF w_copy, w
"
können entfallen, dafür wird die ISR mit "RETFIE FAST" beendet.
Deine globalen Variablen liegen bei Adresse 0x401 + 0x402.
Die gibt es bei diesem PIC gar nicht, da dieser nur 512 Byte RAM hat ist
die höchste Adresse 0x1FF.
Außerdem kannst du die Adressen größer 0xFF nicht direkt sondern nur
über Bank-Umschaltung ansprechen (Ausnahme: indirekte Adrerssierung über
FSRx).
Bei dir gibt der Compiler sogar eine Warnung aus, die du sicherlich
nicht gelesen hast.
Dein Portpin RC0 ist mehrfach belegt. Die genaue Funktion wird im
CONFIG3H-Register festgelegt (siehe Datenblatt).
Zum besserem testen schaltet man den Portpin nicht einfach ein, sondern
man ändert diesen mit "btg LATC, RC0" immer von 0 >> 1 >> 0 >> 1 ....
Bei Ausgängen wird normalerweise mit LATx gearbeitet, bei Eingängen
kommt PORTx zum Einsatz.
So habe das jetzt mal abgeändert. Also der Compiler hat da keine
Fhelermeldung oder Warnung rausgeschmissen. Habe extra darauf geachtet,
damit keine Warnings im Programm sind. So funktioniert da auch nicht.
Was mir noch aufgefallen ist, ist dass wenn ich das T0CON erst kurz vor
dem einschalten der LED setze, die LED nicht angeht. Ich bin mit meinem
Latein am Ende. Ich habe schon alles ausprobiert
David
Was mir an deinen ISR-Adressen aufgefallen ist:
In deinem PIC ist doch ein Bootloader.
Die ISR-Adressen sind doch bestimmt nicht erlaubt, denn vermutlich
gehören die zum Bootloader.
Wie sind denn die Adressen für dein Programm?
Meine Vermutung ist:
Reset = 0x0400 (goto init)
ISR-High = 0x0408 (call isr_high_sub; retfie fast)
ISR-Low = 0x0418 (retfie fast)
Die genauen Angaben findest du im Handbuch zu deinem Franziz-Board.
David M. schrieb:> Ich bin mit meinem> Latein am Ende. Ich habe schon alles ausprobiert
Ist die LED an RA1 angeschlossen? (ggf. auch mal mit dem Multimeter
messen)
Hast Du "RETFIE 1" eingegeben?
Schwingt Dein Oszillator überhaupt? (Deine Definition: External RC
oscillator)
Wartest Du lange genug auf das Blinken? (Blinkfrequenz = 32E6 x
Oszillatorfrequenz)
David M. schrieb:> Wenn ich zum> Beispiel jetzt den Timer0 in C implementiere, ist das Programm um das 5-> fache(oder auch mehr) größer
Das ist ja wirklich heftig.
Beim 8051 oder AVR habe ich im Schnitt 10..50% mehr Code, also weit
unter Deinen 400%.
Ich habe bei beiden mit Assembler angefangen (8051: 1990, AVR: 1997),
möchte aber den Comfort von C nicht mehr missen.
Peter
Peter Dannegger schrieb:> Beim 8051 oder AVR habe ich im Schnitt 10..50% mehr Code, also weit> unter Deinen 400%.
Das hängt sehr stark davon ab, was Du wie in C programmiert hast.
Ich habe auch schon die Ergebnisse von C-Code ausführlich analysiert und
habe Faktoren zwischen 1 und 10 gefunden. Je nach Applikation nützt mir
da die Durchschnittsbetrachtung garnichts: z.B. wenn Du mehrere
zeitkritische Prozesse in einem µc bearbeitest.
Hallo,
es funktioniert :). Der Fehler war die Einsprungadresse(Anstatt 8 und
18, 408 und 418).
Davon stand nichts im Franzis Handbuch. Ich denke mal, dass es daran
liegt, dass sich das Handbuch auf die Programmiersprache C stützt und
sie es deshalb nicht für nötig gehalten haben, dass da reinzuschreiben.
Ich danke vielmals für die schnelle Hilfe.
Gruß
David
kalle wirsch schrieb:> Das hängt sehr stark davon ab, was Du wie in C programmiert hast.
Eher davon, was man noch in Assembler schafft.
Für mich sind max 2..4kB Codegröße die obere Grenze. Darüber ist mir die
vergeudete Zeit einfach zu schade.
Größere Sachen, wie TCP/IP-Stack, Grafiklib, FAT32 usw. in Assembler ist
quasi wie Rasenmähen mit der Nagelschere.
Daher fehlt für größere Programme eine Vergleichsbasis.
Seit Jahren programmiere ich aber auch kleine 1kB-MCs (ATtiny13) nur
noch in C.
kalle wirsch schrieb:> Ich habe auch schon die Ergebnisse von C-Code ausführlich analysiert und> habe Faktoren zwischen 1 und 10 gefunden.
Natürlich muß man auf MCs einige Optimierungsregeln beachten. Gelernte
Windowsprogrammierer neigen besonders dazu, extrem hohen Overhead zu
erzeugen. Sie scheinen oft nichtmal zu wissen, daß unsigned char (1
Byte) in C ein gültiger Datentyp ist. Oder daß 10-fach indirekte Pointer
nicht zu den Stärken von 8-Bittern zählen.
Peter