Forum: Mikrocontroller und Digitale Elektronik Timer0 Assembler PIC 18 Problem


von David M. (mic_dave)


Lesenswert?

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.
1
#include "p18f23k22.inc"
2
;Hallo Welt
3
4
;Kunfiguration
5
  CONFIG FOSC     = RCIO6
6
  CONFIG PLLCFG   = OFF
7
  CONFIG PRICLKEN = ON
8
  CONFIG FCMEN    = OFF
9
  CONFIG IESO     = ON
10
  CONFIG PWRTEN   = ON
11
  CONFIG BOREN    = ON
12
  CONFIG BORV     = 285
13
  CONFIG WDTEN    = OFF
14
  CONFIG PBADEN   = OFF
15
  CONFIG MCLRE    = INTMCLR
16
  CONFIG STVREN   = OFF
17
  CONFIG XINST    = OFF
18
  CONFIG DEBUG    = ON
19
  CONFIG CP0      = OFF
20
  CONFIG CP1      = OFF
21
  CONFIG CPB      = OFF 
22
  CONFIG CPD      = OFF
23
  CONFIG WRT0     = OFF
24
  CONFIG WRT1     = OFF
25
  CONFIG WRTC     = OFF
26
  CONFIG WRTB     = OFF
27
  CONFIG WRTD     = OFF
28
  CONFIG EBTR0    = OFF 
29
  CONFIG EBTR1    = OFF
30
  CONFIG EBTRB    = OFF
31
32
  org 0
33
;----------------------------------------------------------
34
; GLOBAL VARIABLE
35
;----------------------------------------------------------
36
w_copy EQU 0401h; Save W register 
37
s_copy EQU 0402h; Save Statusregister
38
39
40
  GOTO Init
41
;----------------------------------------------------------
42
; INTERRUPT SERVICE ROUTINE
43
;----------------------------------------------------------
44
  org 8
45
isr_high
46
  CALL isr_high_sub
47
  RETFIE
48
49
  org 18
50
isr_low
51
  RETFIE
52
53
  org 400
54
Init
55
  CLRF PORTA ; PortA delete
56
  CLRF TRISA ; All output
57
  CLRF ANSELA; All digital output
58
59
  CLRF PORTC ; PortA delete
60
  CLRF TRISC ; All output
61
  CLRF ANSELC; All digital output
62
  
63
  MOVLW B'00000111'
64
  MOVWF T0CON
65
66
  MOVLW B'11000010'
67
  MOVWF TMR0H
68
69
  MOVLW B'11110110'
70
  MOVWF TMR0L
71
72
  BSF PORTA, RA0
73
74
  BSF INTCON, TMR0IE
75
  BCF INTCON, TMR0IF
76
  BSF INTCON, GIE
77
loop GOTO loop
78
79
isr_high_sub:
80
  MOVWF w_copy
81
  SWAPF STATUS, w
82
  MOVWF s_copy
83
84
  BSF PORTC,RC0 
85
86
  SWAPF s_copy, w
87
  MOVWF STATUS
88
  SWAPF w_copy, f
89
  SWAPF w_copy, w
90
91
  MOVLW B'11000010'
92
  MOVWF TMR0H
93
94
  MOVLW B'11110110'
95
  MOVWF TMR0L
96
97
  BCF INTCON, TMR0IF ; Timerinterruptflag delete
98
99
  RETURN
100
101
  end

Mein Programm kommt nie in die Interruptroutine. Sieht da jemand den 
Fehler?

Danke im vorraus.

Gruß
David

von Sunny (Gast)


Lesenswert?

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.

von David M. (mic_dave)


Lesenswert?

Ok, und was genau ist da nicht richtig gemacht?

P.S.: TMR0ON eingeschaltet,funktioniert aber immer noch nicht

von Peter D. (peda)


Lesenswert?

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

von kalle wirsch (Gast)


Lesenswert?

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.

von David M. (mic_dave)


Lesenswert?

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?

von hagi (Gast)


Lesenswert?

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.

von David M. (mic_dave)


Lesenswert?

1
;----------------------------------------------------------
2
; MAIN ROUTINE
3
;----------------------------------------------------------
4
  org 400
5
Init
6
  CLRF PORTA ; PortA delete
7
  CLRF TRISA ; All output
8
  CLRF ANSELA; All digital output
9
10
  CLRF PORTC ; PortA delete
11
  CLRF TRISC ; All output
12
  CLRF ANSELC; All digital output
13
  
14
  MOVLW B'10000111'
15
  MOVWF T0CON
16
17
  MOVLW B'11000010'
18
  MOVWF TMR0H
19
20
  MOVLW B'11110110'
21
  MOVWF TMR0L
22
23
  BSF INTCON, GIE
24
  BSF INTCON, TMR0IF
25
  BSF INTCON, TMR0IE
26
27
  BSF LATA, RA0
28
29
loop 
30
  GOTO loop
31
32
;----------------------------------------------------------
33
; IMPLEMENT INTERRUPT SERVICE ROUTINE
34
;----------------------------------------------------------
35
isr_high_sub
36
37
  BTG LATA,RA1
38
39
  MOVLW B'11000010'
40
  MOVWF TMR0H
41
42
  MOVLW B'11110110'
43
  MOVWF TMR0L
44
45
  BCF INTCON, TMR0IF ; Timerinterruptflag delete
46
47
  RETURN

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

von hagi (Gast)


Lesenswert?

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.

von kalle wirsch (Gast)


Lesenswert?

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)

von Peter D. (peda)


Lesenswert?

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

von kalle wirsch (Gast)


Lesenswert?

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.

von David M. (mic_dave)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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

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.