Forum: Mikrocontroller und Digitale Elektronik Umstieg auf PIC16F887 und die Probleme


von Marcus W. (marcus_w)


Lesenswert?

Hallo ihr,

Ich mache eine Ausbildung zum EGS`ler (2. Lehrjahr)


Ich habe jetzt angefangen mich mit den PIC´s zu beschäftigen.
Zum Anfang habe ich den etwas älteren 16F84A benutzt.

Ich habe mich an viele Anleitungen von Sprut gehalten. Ansteuern, 
Lauflicht, Tastatur etc.
War ja auch alles kein Problem.


Nun wollte ich auf den PIC16F887 umsteigen. Dazu habe ich mir das 
Testboard von Sprut zusammen gebaut.
http://sprut.de/electronic/pic/test/index.htm#40pin

Und nun wollte ich das einfache Lauflicht auf den PIC16F887 
programmieren.
Und leider komm ich einfach nicht weiter.
1
list p=16f887
2
3
4
5
; Einfügen Standardheader
6
  #include <P16F887.INC>
7
  ERRORLEVEL    -302  ; unterdrückt bank-selection warnings
8
9
; Konfigurationsregister
10
; _EC_OSC    : externer Oscillator
11
; _CP_OFF    : Code Protection OFF
12
; _WRT_OFF    :
13
; _LVP_OFF    : Low Voltage Programming OFF (Achtung: sonst RB3 blockiert!)
14
; _PWRTE_ON    : Power-up Timer ON
15
; _WDT_OFF    : Watchdog Timer OFF
16
; _IESO_OFF    : Internal/External Switch Over Bit OFF
17
; _FCMEN_OFF    : Fail Safe Clock Monitor Enable OFF
18
     __CONFIG    _CONFIG1, _EC_OSC & _CP_OFF & _WRT_OFF & _LVP_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC 
19
     __CONFIG    _CONFIG2, _IESO_OFF & _FCMEN_OFF
20
; → CONFIG bzgl. Oszillator anpassen!!
21
22
23
24
;************************************************************** 
25
; Variablennamen vergeben 
26
loops   Equ     0x22            ; Zähler für Warteschleife  
27
loops2  Equ     0x23            ; Zähler für Warteschleife
28
29
30
;************************************************************** 
31
32
33
 
34
35
Init 
36
37
  BANKSEL     TRISB 
38
  MOVLW     B'00000000' 
39
  MOVWF     TRISB
40
  BANKSEL    PORTB
41
  Clrf    PORTB
42
43
; 1. LED einschalten  
44
45
        bsf     PORTB,0         ; LED an RB0 einschalten 
46
47
; Lauflicht 
48
49
Loop 
50
        call    Wait            ; Wartezeit 
51
        rlf     PORTB,f         ; laufen zur nächsten LED 
52
        goto    Loop  
53
  
54
55
;********************************************************** 
56
; Warteschleife 250 ms 
57
58
Wait 
59
        movlw   D'250'          ; 250 ms Pause 
60
        movwf   loops  
61
62
Wai 
63
        movlw   .110           ; Zeitkonstante für 1ms 
64
        movwf   loops2 
65
Wai2    nop                    ;  
66
        nop 
67
        nop 
68
        nop 
69
        nop 
70
        nop 
71
        decfsz  loops2, F      ; 1 ms vorbei? 
72
        goto    Wai2           ; nein, noch nicht 
73
                               ; 
74
        decfsz  loops, F       ; 250 ms vorbei? 
75
        goto    Wai            ; nein, noch nicht 
76
        retlw   0              ; das Warten hat ein Ende 
77
78
        end

Sieht jemmand einen Fehler in der Programmierung?
Spannungen und Takt sind vorhanden.

Wenn ich das Programm starte blinkt RB0 kurz auf und geht wieder aus und 
das war es.


Danke im vorraus ;)

von M. J. (manfred-64)


Lesenswert?

Hi,

dürfte sich wohl um die "read modify write" falle handeln.
Die LED zieht den Port so weit runter das eine NULL eingelesen wird.

In Deiner Config hast Du _EC_OSC und _HS_OSC stehen ?!

von Marcus W. (marcus_w)


Lesenswert?

Manfred John schrieb:
> Hi,
>
>
>
> dürfte sich wohl um die "read modify write" falle handeln.
>
> Die LED zieht den Port so weit runter das eine NULL eingelesen wird.^

Aber der Port ist doch als Ausgang geschaltet wie kann der PIC da was 
einlesen?

Kann man das irgendwie umgehen ? Habe ein Modul dazu gebaut. (2ma LED 
mit Vorwiederstand direkt an den PORT + Pull-Down Widerstand von 
2,7kOhm)


> In Deiner Config hast Du _EC_OSC und _HS_OSC stehen ?!

Dachte gelesen zu haben das _EC_OSC = externer oszillator und _HS_OSC  = 
der Oszillator den ich benutze.
Ist das falsch ?


Also müsste meine Programm funktionieren ? ^^

von M. J. (manfred-64)


Lesenswert?

Marcus W. schrieb:
> Aber der Port ist doch als Ausgang geschaltet wie kann der PIC da was
> einlesen?

Der Port wird vom PIC als Normales Register behandelt und bei jedem 
zugrif erst KOMPLETT eingelesen und dann zurückgeschrieben, eben "read 
modify write"

Einfach ein zusätzliches Register verwenden das Du dann in den Port 
schreibst.
Es reicht auch, den völlig unnötigen Pull-Down Widerstand raus zu 
nehmen.
So was brauch man nur bei Eingängen wenn das Eingabegerät nur einen 
definierten zustand erzeugen kann, zb: Taster...


Mit _EC_OSC schaltet nur den Clock auf den OSC2 Pin zur weiteren 
Verwendung,
also 1/4 Takt der dann Komplett extern erzeugt an Pin OSC1 anliegt.
Da Du wahrscheinlich ein Quartz o. ä. an OSC1 und OSC2 nutzt für Dich 
nicht verwendbar. _HS_OSC dürfte aber sicher _EC_OCS "überschreiben"

von Marcus W. (marcus_w)


Lesenswert?

Danke für die Hilfe. Werde das morgen gleich machen und wenn was ist 
melde ich mich nochmal ^^


Eine gute Nacht wünsche ich :)

von bko (Gast)


Lesenswert?

ich denke "Manfred John" meint diese Assembler Zeile.
1
rlf     PORTB,f         ; laufen zur nächsten LED

der Befehl "rlf" muss erst vom PortB lesen, dann in siner ALU
schieben und dann das Resultat ausgeben.
Ich kenne den PIC nicht, wenn nun aber die Spannung am LED-Port
zu weit absinkt, dann liest der Befehl "rlf" nur Nullen zurück
-obwohl die LED leuchtet-
und schiebt diese Nulen, um dann eben nur Nullen auszugeben.
Das hängt vom Aufbau und der Treiberfähigkeit des Ports ab.

Eventuell muss das "geschobene" Bit in einem anderen Register
gespeichert werden z.B in "nicht ganz PIC Assembler" so:
1
 bsf     PORTB,0         ; LED an RB0 einschalten 
2
 bsf     anderesregister ;  <---
3
loop:
4
 call wait
5
 rlf     anderesregister
6
 mov     anderesregister->W->PORTB  ; weiss nicht genau wie das im PIC geht!
7
 goto loop

von bko (Gast)


Lesenswert?

hoppla, ich tippe zu langsam ...

von usuru (Gast)


Lesenswert?

> Kann man das irgendwie umgehen ? Habe ein Modul dazu gebaut. (2ma LED
> mit Vorwiederstand direkt an den PORT + Pull-Down Widerstand von
> 2,7kOhm)

Ich vermute auch mal, dass der Pull-Down das Problem ist. Das nennt sich 
bei sprut in-out-Falle 
http://sprut.de/electronic/pic/fallen/fallen.html#inout

Einfach eine LED mit 100 Ohm bis 1 kOhm (je nach VDD) Vorwiderstand an 
den Port ran.

Ach ja: und natürlich auch die Analog-Falle: beim 16F887 wird die mit
1
     bsf      STATUS, RP0     ; Bank 3
2
     bsf      STATUS, RP1
3
     clrf     ANSEL           ; Port A digital
4
     clrf     ANSELH          ; Port B digital

abgeschaltet

von Harry (Gast)


Lesenswert?

Meine Azubis müssen sich auch mit dem Ding beschäftigen.

Zugegeben, die wenigen Befehle sind reizvoll, aber n AVR hat meiner 
Meinung weniger Fallen und is leichter zu verstehen, gerade wenn man, 
wie die Azubis, gerade erst anfängt.

Ich werde wenn's akut wird, n Script zu dem Ding schreiben, worin 
nochmals auf Fehler & co hingewiesen wird!

Aber Sprut is schon ganz gut!


Gruß

von M. J. (manfred-64)


Lesenswert?

usuru schrieb:
> Ach ja: und natürlich auch die Analog-Falle: beim 16F887 wird die mit
>      bsf      STATUS, RP0     ; Bank 3
>      bsf      STATUS, RP1
>      clrf     ANSEL           ; Port A digital
>      clrf     ANSELH          ; Port B digital
>
> abgeschaltet

Wohl eher:
   BANKSEL ANSELA   ; weil's sicherer und verständlicher ist
   clrf    ANSELA   ; A vergessen
   clrf    ANSELB   ; H satt B geschrieben
   BANKSEL 0        ; damit wieder "ordentliche" Zustände herrschen

hat der P16F887 überhaupt A/D's an PortA o.B ?
Die LED hat ja 1x geblinkt !

mfg

von Marcus W. (Gast)


Lesenswert?

Ja hat er.

Noch eine Frage dazu. Sind die analog-Eingänge Standard mäßig ein ?
Hatte dazu noch nichts im Datenblatt gefunden.

von M. J. (manfred-64)


Lesenswert?

Ja

von usuru (Gast)


Lesenswert?

>   BANKSEL ANSELA   ; weil's sicherer und verständlicher ist

ok, ist übersichtlicher

>   clrf    ANSELB   ; H satt B geschrieben

nö, das heisst tatsächlich ANSELH und ist für die Ports AN13-AN8, die 
auf Port B liegen (manchmal kann man bei der Inkonsequenz von Microchip 
tatsächlich verzweifeln)

von M. J. (manfred-64)


Lesenswert?

Was'n Bullshitt
Beim P16F887 steht wirklich ANSEL für PortA in der P16F887.INC und für 
PortB ANSELH ?!?!?!

Das gibt aber'n dickes Minus für Microchip :(

von Marcus W. (Gast)


Lesenswert?

Morgen,

Sooo.... mein Prgramm sieht jetzt so aus
1
  list p=16f887
2
3
4
5
; Einfügen Standardheader
6
  #include <P16F887.INC>
7
  ERRORLEVEL    -302  ; unterdrückt bank-selection warnings
8
9
; Konfigurationsregister
10
; _EC_OSC    : externer Oscillator
11
; _CP_OFF    : Code Protection OFF
12
; _WRT_OFF    :
13
; _LVP_OFF    : Low Voltage Programming OFF (Achtung: sonst RB3 blockiert!)
14
; _PWRTE_ON    : Power-up Timer ON
15
; _WDT_OFF    : Watchdog Timer OFF
16
; _IESO_OFF    : Internal/External Switch Over Bit OFF
17
; _FCMEN_OFF    : Fail Safe Clock Monitor Enable OFF
18
     __CONFIG    _CONFIG1, _CP_OFF & _WRT_OFF & _LVP_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC 
19
     __CONFIG    _CONFIG2, _IESO_OFF & _FCMEN_OFF
20
; ? CONFIG bzgl. Oszillator anpassen!!
21
22
23
24
;************************************************************** 
25
; Variablennamen vergeben 
26
loops   Equ     0x22            ; Zähler für Warteschleife  
27
loops2  Equ     0x23            ; Zähler für Warteschleife
28
ausg    Equ  0X24    ; Register für PORTB
29
30
;************************************************************** 
31
32
33
 
34
35
Init 
36
37
  BANKSEL     TRISB 
38
  MOVLW     B'00000000' 
39
  MOVWF     TRISB
40
  BANKSEL   ANSEL     ; weil's sicherer und verständlicher ist
41
  clrf      ANSEL     ; A vergessen
42
  clrf      ANSELH    
43
  BANKSEL    PORTB   ; damit wieder "ordentliche" Zustände herrschen
44
  Clrf    PORTB         
45
46
 
47
48
49
50
; 1. LED einschalten  
51
52
        bsf     PORTB,0         ; LED an RB0 einschalten 
53
        bsf     ausg,0
54
        ; Lauflicht 
55
56
Loop 
57
        call    Wait            ; Wartezeit 
58
        rlf     ausg            ; laufen zur nächsten LED
59
        MOVF  ausg             ; Ausgabe Register ins Arbeitsregister kopieren
60
        MOVWF  PORTB          ; Arbeitsregister in PORTB kopieren
61
        goto    Loop  
62
  
63
64
;********************************************************** 
65
; Warteschleife 250 ms 
66
67
Wait 
68
        movlw   D'250'          ; 250 ms Pause 
69
        movwf   loops  
70
71
Wai 
72
        movlw   .110           ; Zeitkonstante für 1ms 
73
        movwf   loops2 
74
Wai2    nop                    ;  
75
        nop 
76
        nop 
77
        nop 
78
        nop 
79
        nop 
80
        decfsz  loops2, F      ; 1 ms vorbei? 
81
        goto    Wai2           ; nein, noch nicht 
82
                               ; 
83
        decfsz  loops, F       ; 250 ms vorbei? 
84
        goto    Wai            ; nein, noch nicht 
85
        retlw   0              ; das Warten hat ein Ende 
86
87
        end

Leider leuchtet immer nur RB0 einmal auf. Pull-Up ist jetzt auch raus. 
das 10MHz Quarz schwingt auch :)

noch jemmand eine Idee? :)

von ich (Gast)


Lesenswert?

usuru schrieb:
>>   BANKSEL ANSELA   ; weil's sicherer und verständlicher ist
>
> ok, ist übersichtlicher

Übersichtlicher vielleicht, aber falsch. Es heißt ANSEL, ohne A.


Manfred John schrieb:
> Beim P16F887 steht wirklich ANSEL für PortA in der P16F887.INC und für
> PortB ANSELH ?!?!?

Ich hab das ehrlich gesagt noch nie anders gesehen. ANalogSELect, um zu 
wählen, ob der ADC aktiv ist oder nicht. Das H steht dann für High, 
wegen den oberen bytes. Genauso wie bei ADRESL und ADRESH -> 
Analog-Digital-RESult-Low/High. für die unteren und die oberen bits.


Die ADCs werden aber genauso abgeschaltet wie die internen 
Pull-Up-Widerstände, wenn man den Port als Ausgang schaltet. Den Fehler 
mit dem ADC hatte ich auch am Anfang, wobei ich das nicht Microchip in 
die Schuhe schieben kann. Irgendwas muss ja die höhere Priorität haben. 
Beim Ausgang allerdings können Sachen eine Rolle spielen, z.b. Interrupt 
on Change oder die P1A etc pins. Das sind die Anschlüsse für das CCP 
(Capture/Compare/PWM) Modul. Ansich sind die Prioritäten aber so:
ADC, Digital In/Out, Modul-Pins. Wobei die ADCs ja bei Ausgängen 
deaktiviert sind.

Also ich würde so vorgehen:
- Wegen der Sicherheit nochmal die Module (ADC, CCP) extra Ausschalten.
- Das Rotieren in einem extra Register machen und danach ins PORTB 
schreiben
- Pulldown-Widerstände rausmachen
- Wenns danach immernoch nicht gehen sollte, einfach ein Blinklicht vom 
ganzen PortB machen, um zu gucken, ob der Takt, der PIC und die Platine 
wirklich in Ordnung ist.

von ich (Gast)


Lesenswert?

mist zu langsam. Aber lösch nochmal extra das CCP1CON und CCP2CON 
Register.

von bingo (Gast)


Lesenswert?

>   MOVF  ausg     ; Ausgabe Register ins Arbeitsregister kopieren

   MOVF  ausg, 0   ; !!!

von Marcus W. (Gast)


Lesenswert?

ich schrieb:
> Also ich würde so vorgehen:
>
> - Wegen der Sicherheit nochmal die Module (ADC, CCP) extra Ausschalten.

Um CCP auszuschalten muss ich welches Register ansprechen?
Hab hier ja CCP1CON und CCP2CON....sind das die richtigen ?

> - Das Rotieren in einem extra Register machen und danach ins PORTB

        bsf     PORTB,0         ; LED an RB0 einschalten
        bsf     ausg,0
        ; Lauflicht

Loop
        call    Wait            ; Wartezeit
        rlf     ausg            ; laufen zur nächsten LED
        MOVF  ausg             ; Ausgabe Register ins Arbeitsregister 
kopieren
        MOVWF  PORTB          ; Arbeitsregister in PORTB kopieren
        goto    Loop


Ist doch richtig oder ?
> schreiben
>
> - Pulldown-Widerstände rausmachen
Hab ich jetzt wieder rausgelötet

>
> - Wenns danach immernoch nicht gehen sollte, einfach ein Blinklicht vom
>
> ganzen PortB machen, um zu gucken, ob der Takt, der PIC und die Platine
>
> wirklich in Ordnung ist.

Ich schau mal... Hab am CLKOUT die 10MHz und an CLKIN knapp 1V DC
Ist das richtig so ? :-/

von ich (Gast)


Lesenswert?

bingo schrieb:
>>   MOVF  ausg     ; Ausgabe Register ins Arbeitsregister kopieren
>
>    MOVF  ausg, 0   ; !!!

nicht vergessen!


Marcus W. schrieb:
> Um CCP auszuschalten muss ich welches Register ansprechen?
> Hab hier ja CCP1CON und CCP2CON....sind das die richtigen ?

Ja sind es. Können beide direkt auf 0, also mit clrf.

Marcus W. schrieb:
> Ich schau mal... Hab am CLKOUT die 10MHz und an CLKIN knapp 1V DC
> Ist das richtig so ? :-/

Ansich nicht ;) Benutzt du einen Quarz? Wenn ja, wird er genauso 
angeschlossen, wie beim 16F84. Also an OSC1 und OSC2 jeweils ein 
Beinchen vom Quarz dran und dann pro Beinchen nochmal ein kleinen 
Kondensator, ca 20pF gegen Masse.

Wenn dein Projekt läuft und du den PIC bzw "neuere" PICs benutzen 
willst, kannst du auch mal den internen Oscillator angucken. Den benutze 
ich eigentlich nur noch -> weniger Bauteile, Leiterbahnen, Bohrlöcher 
und Routingaufgaben.... Für solche Aufgaben oder nahezu alle, wo es 
nicht Zeitkritisch sein muss, finde ich das recht angenehm.

von Marcus W. (Gast)


Angehängte Dateien:

Lesenswert?

ich schrieb:
> Ansich nicht ;) Benutzt du einen Quarz? Wenn ja, wird er genauso
>
> angeschlossen, wie beim 16F84. Also an OSC1 und OSC2 jeweils ein
>
> Beinchen vom Quarz dran und dann pro Beinchen nochmal ein kleinen
>
> Kondensator, ca 20pF gegen Masse.

Das ist schlecht :)

Hab den Schaltplan für das Übungsboard hochgeladen. An der Jumperleiste 
hab ich die beiden äußeren Verbunden. Hab dort zwei 33pF Kondensatoren 
reingemacht.



> Wenn dein Projekt läuft und du den PIC bzw "neuere" PICs benutzen
>
> willst, kannst du auch mal den internen Oscillator angucken. Den benutze
>
> ich eigentlich nur noch -> weniger Bauteile, Leiterbahnen, Bohrlöcher
>
> und Routingaufgaben.... Für solche Aufgaben oder nahezu alle, wo es
>
> nicht Zeitkritisch sein muss, finde ich das recht angenehm.

Bestimmt doofe Frage. Könnte bestimmt auch selber nachschauen aber wie 
schalte ich den ein? Ist es dann ein Problem wenn ein Quarz mit 
angeschlossen ist bzw. wird der ignoriert.

von ich (Gast)


Lesenswert?

Marcus W. schrieb:
> Bestimmt doofe Frage. Könnte bestimmt auch selber nachschauen aber wie
> schalte ich den ein? Ist es dann ein Problem wenn ein Quarz mit
> angeschlossen ist bzw. wird der ignoriert.

Der wird ignoriert. Du musst deine Setting-Bits überprüfen und dann 
nicht HS_OSC sondern INT_OSC oder so. Bin mir nicht sicher, wie das 
heißt.
Ansich kann man immer noch einen Extra Teiler schalten und man muss. 
Eine gute Übersicht, wie das alles zusammenhängt und auch von welchen 
bits es abhängig ist, sieht man im Blockschaltbild in dem OSC-Abschnitt 
(Seite 61). Ich denke, du kannst den Quarz (oder Resonator) auch 
dranlassen.

von ich (Gast)


Lesenswert?

ich schrieb:
> Ansich kann man immer noch einen Extra Teiler schalten und man muss...

 das OSCCON-Register nochmal angucken.

Man sollte Sätze zuende schreiben.

von usuru (Gast)


Lesenswert?

folgender Code läuft bei mir auf einem 16F886 (ist identisch mit 16F887, 
hat nur weniger PINs), Config und Warteschleife habe ich weggelassen. 
Wichtigste Änderung sind die Zeilen mit ***
1
Init 
2
3
   BANKSEL   TRISB 
4
   MOVLW     B'00000000' 
5
   MOVWF     TRISB
6
   BANKSEL   ANSEL     ; weil's sicherer und verständlicher ist
7
   clrf      ANSEL     ; A vergessen
8
   clrf      ANSELH    
9
   BANKSEL   PORTB     ; damit wieder "ordentliche" Zustände herrschen
10
   clrf      PORTB         
11
   clrf      ausg
12
13
   bsf       ausg, 0
14
15
Loop 
16
   call    Wait        ; Wartezeit 
17
   rlf     ausg, 1     ; laufen zur nächsten LED
18
   MOVFW   ausg        ; *** Ausgabe Register ins Arbeitsregister kopieren
19
   MOVWF   PORTB       ; *** Arbeitsregister in PORTB kopieren
20
   goto    Loop

von M. J. (manfred-64)


Lesenswert?

ich schrieb:
> Ich hab das ehrlich gesagt noch nie anders gesehen. ANalogSELect, um zu
> wählen, ob der ADC aktiv ist oder nicht. Das H steht dann für High,
> wegen den oberen bytes. Genauso wie bei ADRESL und ADRESH ->
> Analog-Digital-RESult-Low/High. für die unteren und die oberen bits.

Hier siehst Du's ;)
P16F727.INC
;-----Bank3------------------
ANSELA           EQU  H'0185'
ANSELB           EQU  H'0186'
ANSELD           EQU  H'0188'
ANSELE           EQU  H'0189'
PMCON1           EQU  H'018C'

Welche OBEREN Bytes bei ANSEL ?
Das sind wie immer 8Bit breite Port's, da is nix mit HIGH-Byte

von usuru (Gast)


Lesenswert?

> Hier siehst Du's ;)
> P16F727.INC

Das ist ein anderer PIC, ist daher völlig irrelevant. Im Datenblatt des 
16F887 steht ANSEL und ANSELH, das zählt.

von ich (Gast)


Lesenswert?

usuru schrieb:
> Das ist ein anderer PIC, ist daher völlig irrelevant. Im Datenblatt des
> 16F887 steht ANSEL und ANSELH, das zählt.

ja schon, er bezog das aber auf meinen post.

Manfred John schrieb:
> Welche OBEREN Bytes bei ANSEL ?
> Das sind wie immer 8Bit breite Port's, da is nix mit HIGH-Byte

Das stimmt wohl, jedoch hast du AN0 bis AN13 oder so.. und dann is AN0 
bis AN7 in ANSEL und AN8-AN13 in ANSELH.

von M. J. (manfred-64)


Lesenswert?

usuru schrieb:
>> Hier siehst Du's ;)
>> P16F727.INC
>
> Das ist ein anderer PIC, ist daher völlig irrelevant. Im Datenblatt des
> 16F887 steht ANSEL und ANSELH, das zählt.

Wurde ja schon weiter oben geklärt.
Ging nur um

ich schrieb:
> Manfred John schrieb:
>> Beim P16F887 steht wirklich ANSEL für PortA in der P16F887.INC und für
>> PortB ANSELH ?!?!?
>
> Ich hab das ehrlich gesagt noch nie anders gesehen.

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.