Forum: Mikrocontroller und Digitale Elektronik Interrupt in Assembler


von nedim m. (d_caine)


Angehängte Dateien:

Lesenswert?

Hallo Leute,
da ich ja neu bin bei der Controller programmierung bin habe ich mir 
folgende  Aufgabe ausgedacht, einfach zur Übung . Eine Led soll blinken 
wärend eine andere LED über einen Taster geschaltet werden kann.
Die Taster Abfrage soll aber unbedingt über eine Interrupt-Routine 
gehen.
Ist ja der Sinn und zweck der Übung.

Der Teil mir dem blinken der LED funktioniert alleine. Da liegt also 
kein Fehler. Sobald ich aber die Interrupt-Routine dazumache geht nix 
mehr, kann das Programm nicht Assemblieren . Komme einfach nicht 
dahinter wo mein Fehler liegt.
Der Assembler MPLAB bringt folgende Fehler :

C:\USERS\Q\DESKTOP\LED_BLINKEN_INTERRUPT\LED_BLINKT_INTERRUPT.ASM 67 : 
Overwriting previous address contents (0004)
Error[118] 
C:\USERS\Q\DESKTOP\LED_BLINKEN_INTERRUPT\LED_BLINKT_INTERRUPT.ASM 67 : 
Overwriting previous address contents (0004)
Error[118]

Und das geht immer weiter bis (0010)
Kann mir bitte einer auf die Sprünge helfen???
Danke im voraus .

Gruss Caine

von spess53 (Gast)


Lesenswert?

Hi

>Die Taster Abfrage soll aber unbedingt über eine Interrupt-Routine
>gehen.

Du weisst aber, das ein Taster prellt und mehrere Interrupts auslöst.

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

Wenn das hier
1
org 0x00
2
3
4
5
init
6
7
 bsf     STATUS, RP0            ;Bank 1  setzen
8
 movlw   B'00000000'            ;Port D alle out
9
 movwf   TRISD
10
 bcf     STATUS, RP0            ;Bank 0 setzen
11
 clrf    PORTD                  ;Alle LED´s aus
12
13
 bsf     STATUS, RP0             ;Bank 1 setzen
14
 bcf     OPTION_REG,NOT_RBPU     ;Pull-upp´s hoch
15
 movlw   B'11111111'             ;Port B alle Eingänge
16
 movwf   TRISB
17
 bcf     STATUS, RP0             ;Bank 0 setzen
18
....

bei Adresse 0 beginnen soll (Beachte das org 0x00 am Anfang), dann wird 
sich das hier
1
    ORG     0x004             ; interrupt vector location
2
    movwf   w_copy            ; save off current W register contents
3
    movf  STATUS,w          ; move status register into W register
4
    movwf  s_copy            ; save off contents of STATUS register
5
....

wohl nicht so ausgehen, dass die entsprechenden Anweisung auf 0x004 
beginnen können, denn durch den ersten Abschnitt liegen da ja schon 
Instruktionen!

Du versuchst da gerade die selben Speicherzellen, für 2 verschiedene 
Instruktionen zu benutzen.


Halte ein bischen mehr Ordnung in deinem Code! Das du in dem Kraut und 
Rüben Salat an unterschiedlichen Schreibweisen und Einrückungen den 
Überblick verlierst, wundert mich persönlich überhaupt nicht. Auch ist 
die ORG Direktive kein Allheilmittel! Ordne deine Codeteile von vorne 
herein am Besten gleich so an, dass sie so auch im Code stehen, wie sie 
auch im Speicher stehen und benutze ORG nicht dazu den Code NACH VORNE 
zu verschieben, sondern dazu um ev. Lücken im Code auf bestimmte 
Endaddressen festzunageln.
1
ORG 0x00
2
    goto    init
3
4
ORG 0x04
5
    movwf   w_copy            ; save off current W register contents
6
     ... hier dann die Interrupt Routine
7
8
init
9
    bsf     STATUS, RP0       ;Bank 1  setzen
10
    movlw   B'00000000'       ;Port D alle out
11
     .....


Ordnung im Code zu halten ist in allen Programmiersprachen wichtig. Aber 
nirgends ist es wohl so wichtig wie in Assembler.

von tb (Gast)


Lesenswert?

Hi dein Aufbau ist falsch in etwa so
1
list p=16f876a
2
        include "p16f876a.inc"
3
 
4
        __CONFIG _HS_OSC & _WDT_OFF & _PWRTE_ON & _BODEN_OFF & _LVP_OFF & _CPD_OFF & _WRT_OFF & _DEBUG_OFF & _CP_OFF
5
 
6
        org     0x0000                  ; Programmanfang
7
        nop                             ; Für ICD2 Debugging
8
        goto    init                    ; Springe zur Inialisirung (Anfangsroutine)
9
        org     0x0004                  ; Erste Rotine (main) ab Adresse 004
10
11
<ISP>
12
<Main>

du hast aber:
1
0rg 000
2
<isr>
3
org 04
4
<main>

Da werden die ersten Pahr Adressen von der ISR benutzt und da haste den 
mit org 04 noch die main auf den gleichen Platz gemapt.

von nedim m. (d_caine)


Angehängte Dateien:

Lesenswert?

So hab das jetzt so weit verändert.
sind jetzt weniger Errors da, viel weniger, aber noch stimmt was nicht.

von John B. (johnbauer)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Halte ein bischen mehr Ordnung in deinem Code! Das du in dem Kraut und
> Rüben Salat an unterschiedlichen Schreibweisen und Einrückungen den
> Überblick verlierst, wundert mich persönlich überhaupt nicht.

Das was Karl Heinz Buchegger sagt.
Und definier deine Variablen am Anfang vom Programm, nicht mittendrin.
1
   ; Variablen festlegen
2
   xxx EQU xxx
3
   cblock ... endc
4
   #define ...
5
6
   org 0x0000
7
   goto init
8
9
   org 0x0004
10
   ; Interrupt-Routine
11
12
init
13
   ; Initialisierung
14
15
main
16
   ; Hauptprogramm
17
18
   end

Das hier ist Teil von init
1
; RB0-Interrupt einstellen 
2
  bsf    STATUS, RP0        ; auf Bank 1 umschalten 
3
  bsf    OPTION_REG, INTEDG ; 0-1-Flanke an RB0 
4
  bcf    STATUS, RP0        ; auf Bank 0 zurückschalten
5
6
  bsf    INTCON, INTE       ; RB0-interrupt erlauben 
7
  bsf    INTCON, GIE        ; Interrupt generell erlauben
das solltest Du auch dorthin verschieben: nach dem Label "init".

Das ist nicht Bestandteil der ISR:
1
      clrf    PCLATH            ; ensure page bits are cleared
2
      goto    main              ; go to beginning of program
Hast Du wohl aus versehen mit kopiert und kann, an der Stelle, ersatzlos 
gestrichen werden.

Gruß
John

von Peter D. (peda)


Lesenswert?

nedim muratovic schrieb:
> Die Taster Abfrage soll aber unbedingt über eine Interrupt-Routine
> gehen.

Aber natürlich über den Timerinterrupt.
Macht jeder so, der kein Anfänger ist.


Peter

von nedim m. (d_caine)


Angehängte Dateien:

Lesenswert?

So Leute hab eure Ratschläge befolgt, ein wenig den Code aufgeräumt.
Zuerst die Config-Bits dan Variablen vergeben, Interrupt-Routine, 
Hauptprogramm.
Nun habe ich keinen Error mehr. Das Prog. lässt sich assemblieren und 
laden.
Nur Es funktioniert nicht so wie es sein soll.
Denn die eine LED blinkt zwar aber nach dem ich den Taster betätige geht 
die andere LED an aber die erste blinkt nicht  mehr. :-)
Es sieht so aus als hängt der controller im Interrupt fest.
Wie geht das dass der wieder aus dem Interrupt rauskommt ?

Gruss Caine

von nedim m. (d_caine)


Lesenswert?

Peter Dannegger schrieb:
> Aber natürlich über den Timerinterrupt.
> Macht jeder so, der kein Anfänger ist.
>
>
> Peter

Peter, bin aber Anfänger :-)

von Peter D. (peda)


Lesenswert?

nedim muratovic schrieb:
> Peter, bin aber Anfänger :-)

Ja, ich habe mich ungenau ausgedrückt.
Ich meinte, wer nicht ein Anfänger ist, der unbedingt auf die harte Tour 
lernen will, wie man es nicht macht.

Ich will Dich aber nicht daran hindern, sattsam bekannte Fehler nochmal 
selber zu machen. Solange Du das nicht auf Arbeit machst, d.h. für die 
unnütze Zeit von anderen bezahlt wirst, ist das ja egal.


Peter

von John (Gast)


Lesenswert?

Dave Jones (eevblog) wünscht den Anfängern ja, dass ihre Schaltungen 
nicht funktionieren. Weil man dann den Fehler suchen muss, und dabei 
lernt man mehr, als wenn alles gleich funktionieren würde.

John

von John (Gast)


Lesenswert?

Du musst in der ISR einmal Port B auslesen und dann das RBIF-Bit im 
INTCON-Register löschen. Sonst wird nach verlassen der ISR sofort wieder 
ein Interrupt ausgelöst.

John

von John (Gast)


Lesenswert?

Hab gerade gesehen, dass Du RB0 verwendest. Hier musst Du das INTF-Bit 
löschen.
Mein voriger Post gilt nur für RB4-RB7.

John

von GroberKlotz (Gast)


Lesenswert?

Hallo d_caine
habe gerade mal im Forum nachgeschaut und gesehen, dass Du doch bereits 
ein einwandfreies, übersichtliches Muster
[Beitrag "Einfaches Assemblerprogramm"]
zum Aufbau eines Assemblerprogramms erhalten hast. Halt Dich doch an die 
bisher entwickelte Systematik, dann hast es Du, aber auch Deine Helfer 
erheblich einfacher!
Wenn Du gute Ratschläge nicht beachtest, brauchst Du Dich nicht zu 
wundern, wenn die Helfer allmählich keine Lust mehr an der Hilfe für 
Dich haben!

Grüße
GroberKlotz

von GroberKlotz (Gast)


Lesenswert?


von nedim m. (d_caine)


Lesenswert?

Hallo John ,

Mein Taster liegt ja an RB4, habe das jetzt in der Initialisierung 
geändert ,
jetzt passiert das was ich auch wollte, nämlich das RB4 den Interrupt 
auslöst und nicht auch noch RB0.

; RB-Interrupt einstellen
  bsf    STATUS, RP0             ; auf Bank 1 umschalten
  bsf    OPTION_REG, INTEDG      ; 0-1-Flanke an RB0
  bcf    STATUS, RP0             ; auf Bank 0 zurückschalten

  bsf    INTCON, RBIE            ; RB0-interrupt erlauben
  bsf    INTCON, GIE             ; Interrupt generell erlauben

Habe noch in der ISR das Port B ausgelesen und das RBIF Bit gelöscht
so wie Du es vorgeschlagen hast
movf PORTE
bcf  INTCON, RBIF

Und das funktioniert  RB4 macht die 2-te LED an die erste blinkt immer 
noch.So wie ich das haben wollte.

Nur kann ich die LED nicht mehr ausschalten. Aber bin ziemlich weit 
gekommen mit euren Vorschlägen .
Danke Jungs .

von John B. (johnbauer)


Lesenswert?

nedim muratovic schrieb:
> Habe noch in der ISR das Port B ausgelesen und (...)
> movf PORTE
       ^^^^^ <- Port B ?

von nedim m. (d_caine)


Lesenswert?

meinte PORT E ausgelesen ...so wie es im Code auch steht...sorry 
...tippfehler.
Aber John, danke für die Tippst ...hat einiges geholfen .., muss nur 
noch die ISR-Routine richtig machen. Wenn das abgeschlossen ist plane 
ich eine zweite test Platine zu machen an der ich Temperatursensoren 
anschließen kann und noch ein Display. Vor dem Hintergrund das ich plane 
so oder so irgendwann mit den grafischen Displays zu arbeiten da sie 
nicht mehr viel kosten aber gut aussehen, wäre es sinnvoll sofort ein 
solchen zu holen und damit anzufangen oder wäre es besser erst mal mit 
einem 2x14 Display zu starten ?

Caine

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.