PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Einstieg codierung eigentlich ganz simpel oder doch nicht?



jorues
30.03.2007, 20:36
Hallo,

hatte folgendes bereits bei microcontroller.net schon geschrieben:

"
Hallo,

ich bin grade dabei ein elektronisches Handrad für eine CNC-Fräse zu
bauen.
Für die Anzeige der aktiven Achse breuchte ich eine Logik, die mir aus 2
Leitungen 4 LED ansteuert.
Ich weiß das könnte man auch einfach mit der 74 TTL reihe (4 and und 2
invertern) realisieren. Aber ich wollte jetzt doch etwas mal mit einem
PIC16F84A machen. Also dachte ich mir ich les mal ein bisschen im I-Net
nach, bin aber leider noch nicht auf einen grünen Zweig gekommen.
Ich weiß durch spurt mittlerweile, dass ich erstmal die ein ung augänge
initalisieren muss mit dem TRISx-Register soweit ich das verstanden
habe, nur dann wird es schwierig.
Könnte mir vielleich jemand einen einfachen und übersichtlichen
Lösungsweg zeigen? Das soll jetzt nicht so sein lass einfach mal die
anderen das machen, ich hab jetzt mittlerweile 1,5 Tage investiert aber
sehe leider immer noch keinen richtigen Ansatz´, wäre also für jede Hilf
dankbar.
Ich hab mir das so gedacht, den Port A des PIC16F84A nehme ich als
Eingang und den Port B als Ausgang.
Input #1 = RA2
Input #2 = RA3
LED x = RB4
LED y = RB5
LED z = RB6
LED a = RB7

LEDx= nicht(Input #1) und nicht(Input #2)
LEDy= Input #1 und nicht(Input #2)
LEDz= nicht(Input #1) und Input #2
LEDa= Input #1 und Input #2

ich weiß etwas blöd geschrieben aber wusste nicht wie sonst.
Und wie bereits gesagt ich weiß ein PIC ist dafür etwas Oversized, aber
ich habe mich bewusst dafür entschieden, um mal mit etwas einfachen in
Assembler anzufangen.
Oder ist Assembler nicht so gut für den Anfang? Ich kann leider bis
jetzt keine Programmiersprache, außer Java, das lernen wir gerade an der
UNI.

Ich hoffe mir kann jemand helfen und schon mal vielen vielen Dank für
eure Mühe.

Danke Jo
"

leider habe ich keine für mich gute Antwort bekommen
also habe ich mich daran gemacht mal etwas zu experimentieren,
nach ettlichen verschiedenen Ansätzen bin ich nun zu diesem Ergebnis gelangt :



list p=16f84a
;************************************************* *************
;* Pinbelegung
;* ----------------------------------
;* PORTA: Eingänge
;* 0 - PIN 17 - Tastereingang
;* 1 - PIN 18 - n.c.
;* 2 - PIN 01 - Input #4
;* 3 - PIN 02 - Input #5
;* 4 - PIN 03 - n.c.
;* PORTB:
;* 0 - PIN 06 - Tastersignal
;* 1 - PIN 07 - n.c.
;* 2 - PIN 08 - n.c.
;* 3 - PIN 09 - n.c.
;* 4 - PIN 10 - LED x-Achse
;* 5 - PIN 11 - LED y-Achse
;* 6 - PIN 12 - LED z-Achse
;* 7 - PIN 13 - LED a-Achse
;*
;************************************************* *************
;
;jorues 30.03.2007
;
; Handradlogik
;
; Taktquelle: 4 MHz
;
;************************************************* *************
; Includedatei für den 16F84A einbinden

#include <P16f84a.INC>

; Configuration festlegen
; bis 4 MHz: Power on Timer, kein Watchdog, XT-Oscillator

__CONFIG _PWRTE_ON & _WDT_OFF & _XT_OSC

;************************************************* *************
; Variablen festlegen

Input Equ 0x20
Input_kor Equ 0x21
Result Equ 0x22

; Constanten festlegen

Ini_con Equ B'00000000' ; TMR0 -> Intetupt disable
Ini_opt Equ B'00000010' ; pull-up
digit0 Equ B'00000000' ; Wert0 festlegen
digit1 Equ B'00000100' ; Wert1 festlegen
digit2 Equ B'00001000' ; Wert2 festlegen
digit3 Equ B'00001100' ; Wert3 festlegen
LED_X Equ B'00010000' ; LED für X-Achse
LED_Y Equ B'00100000' ; LED für Y-Achse
LED_Z Equ B'01000000' ; LED für Z-Achse
LED_A Equ B'10000000' ; LED für A-Achse
;************************************************* ************
; Das Programm beginnt mit der Initialisierung

Init bsf STATUS, RP0 ; Bank 1
movlw Ini_opt ; pull-up on
movwf OPTION_REG ;
movlw B'11111111' ; PortA alle inputs
movwf TRISA ;
movlw B'00000000' ; PortB alle outputs
movwf TRISB ;
bcf STATUS, RP0 ; Bank 0
clrf PORTA
clrf PORTB

movlw Ini_con ; Interupt disable
movwf INTCON
clrw
;************************************************* ***************

Main

movfw PORTA ; Port A lesen und nach W kopieren
movwf Input ; von W in Input (0x20) kopieren
clrw ; W löschen
bcf Input,0 ;
bcf Input,1 ; alle Bits von Input1 bis auf entscheidende Bits 2 und 3 werden
bcf Input,4 ; auf 0 gesetzt
bcf Input,5 ;
bcf Input,6 ;
bcf Input,7 ;
movfw Input ; Input in Input_kor schreiben
movwf Input_kor
clrw ; W löschen


;************************************************* ***************
; Input vergleichen

X_achse

movfw Input_kor ; Input_kor wird in W geladen
xorwf digit0,0 ; Input_kor und digit0 werden verglichen, Ergenbins in W
movwf Result ; Ergebnis wird in Result gespeichert
clrw ; W löschen

btfss Result,2 ; nächste Zeile überspringen wenn Bit Nr.2 den Wert 1 hat
btfsc Result,3 ; nächste Zeile überspringen wenn Bit Nr.3 den Wert 0 hat
goto Y_achse ; sprung zu Y_achse
bsf PORTB,7 ; Bit 7 von PORTB wird auf high gesetzt, die LED für X-Achse leuchtet
goto Main

;************************************************* ***************
Y_achse

clrf PORTB

movfw Input_kor ; Input_kor wird in W geladen
xorwf digit1,0 ; Input_kor und digit1 werden verglichen, Ergenbins in W
movwf Result ; Ergebnis wird in Result gespeichert
clrw ; W löschen

btfss Result,2 ; nächste Zeile überspringen wenn Bit Nr.2 den Wert 1 hat
btfsc Result,3 ; nächste Zeile überspringen wenn Bit Nr.3 den Wert 0 hat
goto Z_achse ; sprung zu Z_achse
bsf PORTB,6 ; Bit 6 von PORTB wird auf high gesetzt, die LED für Y-Achse leuchtet
goto Main

;************************************************* ***************
Z_achse

clrf PORTB

movfw Input_kor ; Input_kor wird in W geladen
xorwf digit2,0 ; Input_kor und digit2 werden verglichen, Ergenbins in W
movwf Result ; Ergebnis wird in Result gespeichert
clrw ; W löschen

btfss Result,2 ; nächste Zeile überspringen wenn Bit Nr.2 den Wert 1 hat
btfsc Result,3 ; nächste Zeile überspringen wenn Bit Nr.3 den Wert 0 hat
goto A_achse ; sprung zu A_achse
bsf PORTB,5 ; Bit 5 von PORTB wird auf high gesetzt, die LED für Z-Achse leuchtet
goto Main
;************************************************* ***************
A_achse

clrf PORTB

movfw Input_kor ; Input_kor wird in W geladen
xorwf digit3,0 ; Input_kor und digit3 werden verglichen, Ergenbins in W
movwf Result ; Ergebnis wird in Result gespeichert
clrw ; W löschen

btfss Result,2 ; nächste Zeile überspringen wenn Bit Nr.2 den Wert 1 hat
btfsc Result,3 ; nächste Zeile überspringen wenn Bit Nr.3 den Wert 0 hat
goto X_achse ; sprung zu X_achse
bsf PORTB,4 ; Bit 4 von PORTB wird auf high gesetzt, die LED für A-Achse leuchtet
goto Main

;************************************************* ***************
end


beim Umsetzen in eine hex gibts folgende Meldungen, welche soweit ich weiß weiter nicht schlimm sind:



Message[302] C:\ASM\ROUTINE.ASM 63 : Register in operand not in bank 0. Ensure that bank bits are correct.
Message[302] C:\ASM\ROUTINE.ASM 65 : Register in operand not in bank 0. Ensure that bank bits are correct.
Message[302] C:\ASM\ROUTINE.ASM 67 : Register in operand not in bank 0. Ensure that bank bits are correct.


Beim Brennen gibts auch keine Fehler.

Aber leider funktioniert das ganze auf dem Testboard garnicht. Es geschieht nichts. Der ResetPin liegt auf VDD daran kanns also nicht liegen.

Kann jemand den Code mal anschauen, sicher gibt es einfachere Lösungen aber das war das einzige was mir in meinem ersten Code so eingefallen ist.


Vielen Vielen Vielen Dank
Jo

jorues
31.03.2007, 07:32
Kann mir den keiner helfen?
Jo

r.moshage
31.03.2007, 08:55
Schau dir mal unter Microchip\MPASM Suite\Template\Code das Grundgerüst eines Programms für deinen Controller an. In deinem Code fehlt
ORG 0x000 ; processor reset vector
goto main ; go to beginning of program
MFG
Ralf

wolfbert
31.03.2007, 11:04
Hallo,

ich möchte vorausschicken, dass ich mit dem PIC keine Erfahrung habe, also prozessor- und hardwarespezifische Einstellungen kann ich nicht kommentieren, und mit CNC-Fräsen kenn' ich mich auch nicht aus. Aber ich komme mit Deinem Code nicht so recht klar. Der Assembler-Einstieg ist (von Java kommend) schon etwas heftig (aber zweifellos lohnenswert; einfacher wäre C). Mein Tip: zeichne Dir mal die Register Deines PICs auf, nimm das Handbuch und führe jeden einzelnen Befehl auf dem Papier aus lt. Handbuch. Da lernst Du viel und findest auch so manches Problem.

Ich hab' das jetzt mal anhand von http://www.sprut.de/electronic/pic/assemble/befehle.html (schau da mal hin!) versucht:




Main

movfw PORTA ; Port A lesen und nach W kopieren >> W = PORTA
movwf Input ; von W in Input (0x20) kopieren >> Input = W, brauchen wir aber nicht mehr

>> jetzt soll W "gereinigt" werden, also alle Bits = 0 außer Bits 2 und 3
>> das geht einfach mit W = W & 0x0C, also bitweises AND mit 00001100

andlw 12 ; W = W & 0x0C, Zero-Flag in STATUS ggf. auf 1 wenn Ergebnis 0

>> folgender Code ergo unnötig

clrw ; W löschen
bcf Input,0 ;
bcf Input,1 ; alle Bits von Input1 bis auf entscheidende Bits 2 und 3 werden
bcf Input,4 ; auf 0 gesetzt
bcf Input,5 ;
bcf Input,6 ;
bcf Input,7 ;
movfw Input ; Input in Input_kor schreiben

>> hier geht's weiter

movwf Input_kor >> Input_kor = W

>> jetzt haben wir also den Originalzustand von PORTA in Input und den sauberen Zustand in Input_kor und W

clrw ; W löschen >> nicht nötig, wir brauchen Input_kor ja gleich wieder


X_achse >> Du willst PORTB auf 00010000 (LED_X) wenn Input_kor = 00000000 (digit0)

movfw Input_kor ; Input_kor wird in W geladen >> hier nicht nötig, aber für die anderen Achsen schon

>> jetzt W mit digit0 vergleichen

xorwf digit0,0 ; Input_kor und digit0 werden verglichen, Ergenbins in W

>> wenn W gleich digit0, dann liefert XOR 0; das setzt das Zero-Flag in STATUS, und das kannst Du testen

movwf Result ; Ergebnis wird in Result gespeichert >> wenn Du magst, brauchen wir aber nicht

>> ab hier löschen
clrw ; W löschen
btfss Result,2 ; nächste Zeile überspringen wenn Bit Nr.2 den Wert 1 hat
btfsc Result,3 ; nächste Zeile überspringen wenn Bit Nr.3 den Wert 0 hat
goto Y_achse ; sprung zu Y_achse

>> hier geht's weiter
bnz Y_achse ; >> ungleich 0, war's also nicht (Branch on Non Zero)

>> kapier ich nicht: Ergebnis ist 10000000 in PORT B; LED_X ist aber als 00010000 definiert
>> sollte das nicht bsf PORTB,4 sein (Bits von rechts nach links numeriert, also 76543210 )?
>> ein Fehler, der mir auch schon das Leben schwer gemacht hat, ist, dass mit 1 die Leitung auf +5V geht
>> das klappt nur, wenn die LED richtig herum eingebaut ist, also Prozessor, Vorwiderstand, LED, Masse
>> wenn LED zwischen Prozessor und +5V, dann muss der Port auf 0
bsf PORTB,7 ; Bit 7 von PORTB wird auf high gesetzt, die LED für X-Achse leuchtet

>> dann solltest Du da noch eine Pause einbauen, und alle Leitungen z.B. in Main auf 0 setzen
>> siehe http://www.sprut.de/electronic/pic/programm/lauflicht/lauflich.htm

goto Main


Wie gesagt, bin kein PIC-Experte und mache auch viele Fehler (aber am ATmega128)... Hoffentlich hilft's trotzdem etwas.

LG
Wolfgang

jorues
31.03.2007, 13:50
Hallo,

danke für die Tipps. In der Tat waren da ein paar Fehler in der PIN-Zuordnung bei den LEDs .

Hab den Code jetzt mal wie folgt umgestalltet. Wußte leider noch nichts mit flags anzufangen. Jetzt weis ich aber um was es etwa geht:



list p=16f84a
;************************************************* *************
;* Pinbelegung
;* ----------------------------------
;* PORTA: Eingänge
;* 0 - PIN 17 - Tastereingang
;* 1 - PIN 18 - n.c.
;* 2 - PIN 01 - Input #4
;* 3 - PIN 02 - Input #5
;* 4 - PIN 03 - n.c.
;* PORTB:
;* 0 - PIN 06 - Tastersignal
;* 1 - PIN 07 - n.c.
;* 2 - PIN 08 - n.c.
;* 3 - PIN 09 - n.c.
;* 4 - PIN 10 - LED x-Achse
;* 5 - PIN 11 - LED y-Achse
;* 6 - PIN 12 - LED z-Achse
;* 7 - PIN 13 - LED a-Achse
;*
;************************************************* *************
;
;jorues 30.03.2007
;
; Handradlogik
;
; Taktquelle: 4 MHz
;
;************************************************* *************
; Includedatei für den 16F84A einbinden

#include <P16f84a.INC>

; Configuration festlegen
; bis 4 MHz: Power on Timer, kein Watchdog, XT-Oscillator

__CONFIG _PWRTE_ON & _WDT_OFF & _XT_OSC
;************************************************* **************
; Variablen festlegen

Input Equ 0x20
Input_kor Equ 0x21
Result Equ 0x22
loops Equ 0x24 ; Zähler für Warteschleife
loops2 Equ 0x25 ; Zähler für Warteschleife

; Constanten festlegen

Ini_con Equ B'00000000' ; TMR0 -> Intetupt disable
digit0 Equ B'00000000' ; Wert0 festlegen
digit1 Equ B'00000100' ; Wert1 festlegen
digit2 Equ B'00001000' ; Wert2 festlegen
digit3 Equ B'00001100' ; Wert3 festlegen
LED_X Equ B'10000000' ; LED für X-Achse
LED_Y Equ B'01000000' ; LED für Y-Achse
LED_Z Equ B'00100000' ; LED für Z-Achse
LED_A Equ B'00010000' ; LED für A-Achse
;************************************************* ************
;Reset vector
; This code will start executing when a reset occurs.

ORG 0x0000

;************************************************* *************
; Das Programm beginnt mit der Initialisierung

Init

bsf STATUS, RP0 ; Bank 1
movlw B'11111111' ; PortA alle inputs
movwf TRISA ;
movlw B'00000000' ; PortB alle outputs
movwf TRISB ;
bcf STATUS, RP0 ; Bank 0
clrf PORTA
clrf PORTB

movlw Ini_con ; Interupt disable
movwf INTCON
clrw

;************************************************* ***************
Main

movfw PORTA ; Port A lesen und nach W kopieren >> W = PORTA
;
movwf Input ; von W in Input (0x20) kopieren >> Input = W
;
andlw 12 ; W = W & 0x0C, Zero-Flag in STATUS ggf. auf 1 wenn Ergebnis 0
;
movwf Input_kor ; Input_kor = W
; jetzt haben wir also den Originalzustand von PORTA in Input und den sauberen
; Zustand in Input_kor und W
;
clrw ; W löschen >> nicht nötig, wir brauchen Input_kor ja gleich wieder
;
clrf PORTA ; Alle Leitungen auf 0 (LOW)
clrf PORTB ;

;************************************************* ************************************************** *************
;PORTB auf 10000000 (LED_X) wenn Input_kor = 00000000 (digit0)

X_achse

call Wait ; Wartezeit
movfw Input_kor ; Input_kor wird in W geladen
;
xorwf digit0,0 ; Input_kor und digit0 werden verglichen, Ergenbins in W
; wenn W gleich digit0, dann liefert XOR 0; das setzt
; das Zero-Flag in STATUS, und das kannst Du testen
;
movwf Result ; Ergebnis wird in Result gespeichert >> wenn Du magst, brauchen wir aber nicht
;
bnz Y_achse ; >> ungleich 0, war's also nicht (Branch on Non Zero)
bsf PORTB,7 ; Bit 7 von PORTB wird auf high gesetzt, die LED für X-Achse leuchtet

;************************************************* ************************************************** *************
;PORTB auf 01000000 (LED_Y) wenn Input_kor = 00000100 (digit1)

Y_achse

call Wait ; Wartezeit
movfw Input_kor ; Input_kor wird in W geladen
;
xorwf digit1,0 ; Input_kor und digit1 werden verglichen, Ergenbins in W
; wenn W gleich digit1, dann liefert XOR 0; das setzt
; das Zero-Flag in STATUS, und das kannst Du testen
;
movwf Result ; Ergebnis wird in Result gespeichert >> wenn Du magst, brauchen wir aber nicht
;
bnz Z_achse ; >> ungleich 0, war's also nicht (Branch on Non Zero)
bsf PORTB,6 ; Bit 6 von PORTB wird auf high gesetzt, die LED für Y-Achse leuchtet

;************************************************* ************************************************** *************
;PORTB auf 00100000 (LED_Z) wenn Input_kor = 00001000 (digit2)

Z_achse

call Wait ; Wartezeit
movfw Input_kor ; Input_kor wird in W geladen
;
xorwf digit2,0 ; Input_kor und digit2 werden verglichen, Ergenbins in W
; wenn W gleich digit2, dann liefert XOR 0; das setzt
; das Zero-Flag in STATUS, und das kannst Du testen
;
movwf Result ; Ergebnis wird in Result gespeichert >> wenn Du magst, brauchen wir aber nicht
;
bnz A_achse ; >> ungleich 0, war's also nicht (Branch on Non Zero)
bsf PORTB,5 ; Bit 5 von PORTB wird auf high gesetzt, die LED für Z-Achse leuchtet

;************************************************* ************************************************** *************
;PORTB auf 00010000 (LED_A) wenn Input_kor = 00001100 (digit3)

A_achse

call Wait ; Wartezeit
movfw Input_kor ; Input_kor wird in W geladen
;
xorwf digit3,0 ; Input_kor und digit3 werden verglichen, Ergenbins in W
; wenn W gleich digit3, dann liefert XOR 0; das setzt
; das Zero-Flag in STATUS, und das kannst Du testen
;
movwf Result ; Ergebnis wird in Result gespeichert >> wenn Du magst, brauchen wir aber nicht
;
bnz X_achse ; >> ungleich 0, war's also nicht (Branch on Non Zero)
bsf PORTB,4 ; Bit 4 von PORTB wird auf high gesetzt, die LED für A-Achse leuchtet

;************************************************* ************************************************** *************

goto Main

;************************************************* ************************************************** *************
; Warteschleife 250 ms

Wait
movlw D'250' ; 250 ms Pause
movwf loops

Wai
movlw .110 ; Zeitkonstante für 1ms
movwf loops2
Wai2 nop ;
nop
nop
nop
nop
nop
decfsz loops2, F ; 1 ms vorbei?
goto Wai2 ; nein, noch nicht
;
decfsz loops, F ; 250 ms vorbei?
goto Wai ; nein, noch nicht
retlw 0 ; das Warten hat ein Ende

end



Habs jetzt auch versuch, mit dem Ergebnis, dass nach dem einschalten erst RB7 und kurz darauf RB5 auf high, logisch 1, gehen.

Ich bin mir immer noch nicht so sicher, ob mein Grundgerüst stimmt.
Vielleicht könnte da ein PIC experte mal schnell einen Blick darauf werfen???

Vielen Dank euch allen

LG Jo

wolfbert
31.03.2007, 18:21
Am Ende der Achsen-Routinen fehlt jetzt das "goto main", und die Warteschleife ist besser unmittelbar nach dem "bsf PORTx".

Ansonsten musst Du mal sehen, was wirklich an den Input-Ports anliegt.

LG
Wolfgang