PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : verzweiflung bei 16F870 mit PortA



Black_Arrow
26.01.2008, 11:20
Hallo zusammen,
Ich will einfacherweise den PortA als digitale Eingänge und den PortB als Ausgänge verwenden.
Wenn ich auf PortA Pin1 5V anlege (High-Signal) sollte dann die erste LED leuchten usw...
Sollte PortA komplett auf LOW sein, sollen alle LED's leuchten.
Nur es will nicht funktionieren. Schaut euch bitte mal den Code an:
Vllt kann mir jemand weiterhelfen. Danke!
mfG. Michael



list p=16f870

#include <P16f870.INC>

; Programmablauf: Wenn kein PIN an Port A high ist, dann alle LEDs einschalten. Wenn ein PIN an Port A high ist, dann das entsprechende LED einschalten

Init

bsf STATUS, RP0 ; auf Bank 1 umschalten
movlw B'11111111' ; PortA alle output
movwf TRISA
MOVLW 0x06
MOVWF ADCON1
bcf STATUS, RP0 ; auf Bank 0 zurückschalten
clrf PORTA

bsf STATUS, RP0 ; auf Bank 1 umschalten
movlw B'00000000' ; PortB alle output
movwf TRISB
bcf STATUS, RP0 ; auf Bank 0 zurückschalten
clrf PORTB ; alle LEDs ausschalten

int
nop
clrf PORTB
nop
movfw PORTA
btfsc STATUS, Z ; Taste gedrückt?
goto main1 ; keine Taste gedrückt
goto main2
main2
movlw B'11111111'
movwf PORTB
goto int
main1
movwf PORTB ; Tastencode zu LEDs
goto int

end

Benedikt.Seidl
26.01.2008, 12:00
hallo

es wäre einfacher zu helfen, wenn du genau beschreibst, was funktioniert und was nicht.

aber generell kann man sagen:

du brauchst vor dem init ein "ORG 0x00". das legt fest, wo das programm überhaupt im pic geschrieben werden soll. und bei 0x00 (hexadezimal für 0 ;-) fängt der prozessor immer an die befehle abzuarbeiten.

man sollte auch immer noch "ORG 0x04" einfügen. das ist die adresse zu dem der prozessor springt, sobald ein interrupt ausgeführt wird. ist jetzt bei deinem programm nicht vorgesehen, aber du machst das zeug ja auch nicht exziplit aus, also lieber mal noch direkt darunter ein retfie (damit springt er dann wieder dahin zurück, wo er zum interrupt gerufen wurde.)

dann würde ich auch noch ganz am anfang, um sicher zu sein, dass man überhaupt auf der bank 1 ist bcf STATUS,RP1 bsf STATUS,RP0 machen. sonst kann es ja sein, dass man auf der bank 4 landet, wenn in STATUS, RP1 auch eine 1 ist.
du brauchst auch nicht für jede änderung von TRISX auf die bank eins zu springen, und dann wieder auf die bank 0.

also würde ich das ungefähr so machen:



list p=16f870
#include <P16f870.INC>
__config _LVP_OFF & _HS_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF & _CPD_OFF & _BODEN_OFF & _DEBUG_OFF

;Programmablauf: Wenn kein PIN an Port A high ist, dann alle LEDs einschalten. Wenn ein PIN an Port A high ist, dann das entsprechende LED einschalten
ORG 0x00
NOP ;manche pics machen da irgendwie zicken, deswegen kommt da immer ein nop rein.
goto Init

ORG 0x04 ;ein interrupt?
retfie ;dann zurück!


Init

bsf STATUS, RP0 ; auf Bank 1 umschalten
bcf STATUS, RP1 ; auf Bank 1 umschalten

MOVLW 0x06 ;
MOVWF ADCON1 ;macht den ad-wandler aus, d.h. alle ein/ausgänge ist digital

movlw 0xFF ; ist bisschen schneller und kürzer. B'11111111' geht aber auch!; PortA alle input
movwf TRISA

clrf TRISB ; ist bisschen schneller und kürzer. movlw D'0'; movwf TRISB, geht auch! PORTB alle als output

bcf STATUS, RP0 ; auf Bank 0 umschalten

clrf PORTA
clrf PORTB

int
;nop ;wenn du das so lässt, macht er ein nur 2-3 befehle davor die leds an, (zeile 48)
;clrf PORTB ;und dann machst du sie für 8-10 befehle wieder aus -> sie schauen evtl. so aus,
;nop ;als ob sie gar nicht an währen.

movfw PORTA ;der Inhalt von PORTA wird in W geschoben
btfsc STATUS, Z ;überspringe den nächsten befehl, wenn Z = 0 -> wenn W != 0 -> wenn PORTA = 0
goto main1 ; W = 0
;goto main2 ;braucht man eigentlich nicht, weil ja direkt darunter schon main2 steht;

main2
movwf PORTB ; Tastencode zu LEDs
goto int

main1
movlw B'11111111'
movwf PORTB
goto int

end


das meiste habe ich schon im code kommentiert. nach meiner logik, hast du main1 und main2 vertauscht. da kann ich mich aber auch irren. das ist für mich immer rel. kompliziert, diese btfss sachen.

ich weiß zwar nicht wie das bei dir und deiner programmierumgebung ist, aber ich gebe da immer noch das config word mit an. das musst du aber evtl. noch deinen gegebenheiten anpassen. ich weiß ja nicht was für einen oszillator du verwendest.

ich hoffe meine ganzen behauptungen stimmen,..

edit: natürlich auch noch ein herzliches willkommen im forum!

SEIDL.

PICture
26.01.2008, 13:42
Hallo!

Es ist unmöglich ohne Schaltplan der Hardware oder zumindest Beschreibung, wie die Tasten und LEDs angeschlossen sind, sagen, ob der Code richtig funktioniert.

MfG

Black_Arrow
26.01.2008, 19:31
hmmmm... so funktionierts leider nicht. Danke trotzdem.
Es scheint, als würde der PIC abstürzen und neu starten, wenn ich nen Eingang betätige.

Nun anders:
Meine Problematik besteht darin, dass ich PortA(Eingänge) nicht einlesen und gleichzeitig 1:1 an PortB(Ausgänge) weitergeben kann.
Die LED's leuchten dann wie sie wollen oder eben garnicht... Wahrscheinlich ist es so wie der PIC gerade meint... ;-)

Aufbau:

Ich beschalte einen PIC16F870 auf PortA (digitale Eingänge oder umgeschaltete Analogeingänge) mit Tastern, so wie in dem Bild:
http://www.sprut.de/electronic/pic/grund/s3.gif

und die Ausgänge auf PortB so:
http://www.sprut.de/electronic/pic/grund/o1.gif
genauso wie die LED D1.

Wie muss ich dann mein Programm schreiben, dass ich den Signalzustand von PortA einlesen und direkt an PortB weitergeben kann?

Sorry dass ich so einfache Sachen frage. Ich hab schon so viele Seiten im Internet durchwühlt und nichts dergleichen gefunden...

mfG. Michael

PICture
27.01.2008, 00:25
Laut deinen Schaltplänen ist dein Hauptprogramm in zwei Zeilen realisierbar, da das Ausgangssignal am Pin von PORTB immer einem Eingangssignal am entsprechendem Pin von PORTA gleich seien sollte.
Dafür braucht man immer nur endlos eigelesener Wert vom PORTA ins PORTB schreiben (kopieren), ohne irgendwas prüfen zu müssen:

movfw PORTA (bzw. movf PORTA,0 oder movf PORTA,W)
movwf PORTB

Sonst sollte noch, wie der Benedikt.Seidl schon geschrieben hat, die Konfiguration des PICs mit __config Direktive festgelegt werden.

MfG

Black_Arrow
27.01.2008, 10:45
Es funktioniert jetzt.
Code:

list p=16f870
#include <P16f870.INC>
__config _LVP_OFF & _HS_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF & _CPD_OFF & _BODEN_OFF & _DEBUG_OFF
;Programmablauf: Wenn kein PIN an Port A high ist, dann alle LEDs einschalten. Wenn ein PIN an Port A high ist, dann das entsprechende LED einschalten
ORG 0x00
NOP ;manche pics machen da irgendwie zicken, deswegen kommt da immer ein nop rein.
goto Init
ORG 0x04 ;ein interrupt?
retfie ;dann zurück!
Init
bsf STATUS, RP0 ; auf Bank 1 umschalten
bcf STATUS, RP1 ; auf Bank 1 umschalten
MOVLW 0x06 ;
MOVWF ADCON1 ;macht den ad-wandler aus, d.h. alle ein/ausgänge ist digital
movlw B'11111111' ;ich habs so gemacht, weil das für mich im Moment noch übersichtlicher und klarer ist
movwf TRISA
movlw B'00000000'
movwf TRISA
bcf STATUS, RP0 ; auf Bank 0 umschalten
clrf PORTA
clrf PORTB

schleife
movfw PORTA ;der Inhalt von PORTA wird in W geschoben
movwf PORTB
goto schleife
end

Nur: Ohne Schleife reagiert der PIC ziemlich langsam auf die Eingange. Ich weiß zwar nicht warum, aber mit Schleife gehts jetzt super.
Danke nochmal

mfG. Michael

kalledom
27.01.2008, 18:43
Hallo,
vermutlich hat der PIC16F870 an Port A Analog- und / oder Comparator-Eingänge.
Dann müssen die Eingänge von Port A zuerst von Analog- auf TTL-Eingänge initialisiert werden.

Black_Arrow
27.01.2008, 20:38
Ja genau, wahrscheinlich.
So haben wir es gelöst:

MOVWF ADCON1 ;macht den ad-wandler aus, d.h. alle ein/ausgänge ist digital

Steht übrigens oben schon im Code drin ;-)

mfG. Michael

PICture
28.01.2008, 20:37
Hallo!

@ Black_Arrow

Ich habe gedacht, dass "Wenn kein PIN an Port A high ist, dann alle LEDs ausschalten".

Um bei Port B alle pins als Ausgänge haben, muss in deinem Code B´00000000´ in TRISB und nicht TRISA geschrieben werden.

MfG

Black_Arrow
28.01.2008, 20:48
Hi!
Achja... sorry, das habe ich im Code schon abgeändert.
Tut mir leid, dass ich das nicht mehr gepostet hab.

Danke trotzdem.

mfG. Michael