Hallo,
ich beschäftige mich noch nicht seit langen mit Pics und bin noch bei
den Übungsaufgaben (Blinker/Lauflicht), beim Blinklicht habe ich ein
Problem.
Nach anlegen der Betriebsspannung fängt das Lauflicht an zu laufen. Es
passiert aber das manchmal 2 Lichter laufen. Nach Ausschalten des
Netzteils, läuft meistens wieder nur eine LED.
In der Simulation funktioniert alles einwandfrei, nur in der
Wirklichkeit gibts Probleme.
Die Schaltung ist auf einer Steckplatine aufgebaut, sie besteht aus
einem 16Mhz-Quarz, 2x33pF-Kondensatoren, 7 LEDs und 1 Widerstand.
Kann mir jemand meinen Fehler verraten?
mfg
Bruckschi
Das Assemblerfile:
list p=16f826
;********************************
;*
;* Pinbelegung
;
; PortA: 0
; 1
; 2
; 3
; 4
; PortB: 0 LED
; 1 LED
; 2 LED
; 3 LED
; 4 LED
; 5 LED
; 6 LED
; 7 LED
;
; Lauflicht am Port B
;
;***************************************
;
#include <P16f826.INC>
;Configuration bits
CONFIG OSC = HS ; HS 20 MHz
CONFIG PWRT = ON ; power up timer on
CONFIG BOR = OFF ; brown out detect off
CONFIG WDT = OFF ; watchdog off
CONFIG LVP = OFF ; lvp off
;
; Variablen
;
loops Equ 0x22 ;Zähler für Warteschleife
loops2 Equ 0x23 ;Zähler für Warteschleife
;
;
;
;Port B auf Ausgänge stellen
init
bsf Status, RP0 ; Bank 1 umschalten
movlw B'00000000' ; PortB alle Ausgänge
movwf TrisB
bcf Status, RP0 ; auf Bank 0 umschalten
clrf PortB ; alle LED ausschalten
; 1. LED einschalten
clrf PortB, 0
bsf PortB, 0 ; LED an RB0 einschalten
; Lauflicht
Loop
call Wait ;Wartezeit
rlf PortB, f ;nächste LED einschalten
goto Loop
; Warteschleife für 250 ms
Wait
movlw D'250' ;250ms Pause
movwf Loops ;250 in den Zähler schreiben
Wai
Movlw .110 ;Zeitkonstante für 1ms
movwf Loops2
Wai2
nop
nop
nop
nop
nop
nop
decfsz loops2, F ; 1ms 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
clrf PortB, 0
das ist falsch, kann W auf 0 setzen.
clrf PortB
ist richtig.
anstatt
bcf Status, RP0 ; auf Bank 0 umschalten
machst du
clrf Status
damit setzt du Carry auch auf null.
rlf PortB, f ;nächste LED einschalten
da wird das Carry auch eingeschoben, also Achtung.
Weiters was ist, wenn du den 1.er rausschiebst, das hast du nicht drinn.
Nochwas, rlf PortB ist nicht gut, da dabei PortB eingelesen wird,
und da kann es passieren, daß ein bit eine eins ist, wo eine null sein
sollte, lieber eine Variable nehmen, und diese dann auf PortB
raussenden.
clrf PortB, 0
das ist falsch, kann W auf 0 setzen.
clrf PortB
ist richtig.
anstatt
bcf Status, RP0 ; auf Bank 0 umschalten
machst du
clrf Status
damit setzt du Carry auch auf null.
rlf PortB, f ;nächste LED einschalten
da wird das Carry auch eingeschoben, also Achtung.
Weiters was ist, wenn du den 1.er rausschiebst, das hast du nicht drinn.
Nochwas, rlf PortB ist nicht gut, da dabei PortB eingelesen wird,
und da kann es passieren, daß ein bit eine eins ist, wo eine null sein
sollte, lieber eine Variable nehmen, und diese dann auf PortB
raussenden.
MCLR habe ich wirklich nicht mit 10Kohm verbunden, benötige ich das
wirklich, außer als Schutzfunktion für den PIC?
Pic 16F626 ist verkehrt, habe nur einen zu alten Stand vom Lauflicht
hochgeladen, weil es nicht ging hab ich es mit noch ein paar
rücksetztbedingungen von PortB versucht. Daher stammt auch das doppelte
auf 0 setzten des PortB (clrf PortB, 0).
clrf PortB, 0
das ist falsch, kann W auf 0 setzen.
clrf PortB
ist richtig.
Was ist daran falsch, dass W auf 0 gesetzt wird?
rlf PortB, f ;nächste LED einschalten
da wird das Carry auch eingeschoben, also Achtung.
Weiters was ist, wenn du den 1.er rausschiebst, das hast du nicht drinn.
Durch den rlf schieb ich doch Alle Bits in der Speicherzelle um eine
Position nach links. Das Lauflicht läuft von Bit0 nach Bit7, dann kurz
Pause und es fängt wieder von vorne an.
Nochwas, rlf PortB ist nicht gut, da dabei PortB eingelesen wird,
und da kann es passieren, daß ein bit eine eins ist, wo eine null sein
sollte, lieber eine Variable nehmen, und diese dann auf PortB
raussenden.
Könntest du bitte das Programm mit Variablen schreiben.
Mfg
Michael
Wenn du MCLR nicht als I/O Pin verwendest (siehe CONFIG Fuses ->
_MCLRE_ON / _MCLRE_OFF), dann sollte er mit 10K gegen VCC (+) verbunden
sein.
Ansonsten resettet der PIC sporadisch bzw es passiert anderes
undefiniertes Verhalten.
>MCLR habe ich wirklich nicht mit 10Kohm verbunden, benötige ich das>wirklich, außer als Schutzfunktion für den PIC?
Jo, klasse, super Idee. Den Reset Pin floaten lassen.
Hast du noch alle Tassen im Schrank?
Michael Brucksch wrote:
>> clrf PortB, 0> das ist falsch, kann W auf 0 setzen.> clrf PortB> ist richtig.>> Was ist daran falsch, dass W auf 0 gesetzt wird?
Die Syntax von clrf lautet: clrf f
Also gibt es keinen zweiten Parameter. Demzufolge solltest du auch nur
clrf PORTB schreiben ohne Komma und zweiten Parameter.
>> rlf PortB, f ;nächste LED einschalten> da wird das Carry auch eingeschoben, also Achtung.> Weiters was ist, wenn du den 1.er rausschiebst, das hast du nicht drinn.>> Durch den rlf schieb ich doch Alle Bits in der Speicherzelle um eine> Position nach links. Das Lauflicht läuft von Bit0 nach Bit7, dann kurz> Pause und es fängt wieder von vorne an.>
Die Bitschiebebefehle (rlf und rrf) schieben zwar alle Bits nach links
oder rechts, sie schieben aber auch immer das aktuelle Carry-Flag mit
rein (bei rlf wird das Carryflag auf Bit0 geschoben, bei rrf auf Bit7).
Gleichzeitig wird das Bit welches rausgeschoben wird in das Carryflag
geschoben. Wenn du also sicher sein willst, dass du nur Nullen bei
deinem Lauflicht reinschieben willst, solltest du vor dem rlf ein bcf
STATUS,C einfügen. Damit wird das Carryflag gelöscht und du kannst
sicher sein, dass nur Nullen in dein Byte eingeschoben werden.
> Mfg> Michael
dummy wrote:
>>MCLR habe ich wirklich nicht mit 10Kohm verbunden, benötige ich das>>wirklich, außer als Schutzfunktion für den PIC?>> Jo, klasse, super Idee. Den Reset Pin floaten lassen.> Hast du noch alle Tassen im Schrank?
Den Resetpin habe ich direkt mit VCC verbunden.
Habe das Programm nach den oberen Empfelungen abgeändert, der Fehler ist
aber immer noch da. Kann es sein, dass es am Netzteil liegt, da der
Fehler nicht passiert, wenn ich den Pic über MCLR resete.
>Kann es sein, dass es am Netzteil liegt, da der>Fehler nicht passiert, wenn ich den Pic über MCLR resete.
Ja, das kann sein.
Setzt im Configurationword mal BOR auf ON.
Das könnte helfen.
PS: Sorry für das Ding mit den Tassen :(
Nein, Netzteil dürfte es nicht sein, obwohl der Resetpin sollte über
einen Wiederstand gehen, da im Reset der Pin einen zu hohen Strohm
zieht, und in Latch-up gehen könnte.
@ Michael
Hast du das mit dem BOR auf ON versucht?
Wenn die Spannung deines Netzteils nur langsam
hochgeht dann kann das ohne aktivierten Brown Out Reset
zu deinem Fehler führen.
Da wird das Carry-Flag ja immer noch nicht gelöscht...
Ich denke, das ist schon genau der richtige Tipp. Mach das mal, dann
wirst du sehen, wie schön das funktioniert...
So, habe ich meinen Senf auch dazugegeben!
MfG - Marabel
Jetzt, kommt eine Anfängerfrage. Ich Entschuldige mich gleichmal im
vorraus.
Setze ich nicht mit
clrf Status ; auf Bank 0 umschalten
auch das Carry mit auf 0.
Falls das nicht damit zurückgesetzt wird, mit welchen Befehl setzt ich
es dann zurück.
Das mit Bor habe ich versucht, klappt aber nicht. Das selbe gilt für das
abändern der include-datei in 16F628.
Für Fragen brauchst du dich nicht zu entschuldigen: es gibt keine dummen
Fragen - nur dumme Antworten...
Du hast eigentlich Recht: In deinem Programm wird nirgendwo das
Carry-Flag beeinflusst.
ABER: Noch ist dein Programm kurz und überschaubar - das wird sich aber
im Laufe der Zeit ändern...
Daher setzt man das Carry-Flag vor einem Rotationsbefehl grundsätzlich
auf den Wert, dan man benötigt - schwupps, ist diese Fehlerquelle
todsicher eliminiert und man kann weiter suchen...
An dieser Stelle besteht kein diskussionsbedarf: Man macht das so,
fertig aus.
Aber genausowenig führt man Rotationsbefehle direkt am Port aus.
Wie schon oben beschrieben, macht man das mit einer Variablen und gibt
diese dann auf dem Port aus.
Ebenfalls kein diskussionsbedarf...
Versteh mich nicht falsch, aber das sind nunmal die do's und dont's beim
PIC-Programmieren.
Also, benutze zum Rotieren eine Variable und vor dem Rotationsbefehl
löschst du das Carry-Flag.
Das kannst du doch mal eben schnell testen - dauert doch nur 2 Minuten
zum Programmieren...
Es gibt da noch einige Stolperfallen, die du bei www.sprut.de nachlesen
kannst.
MfG - Marabel
Jetzt gibts nur noch das Problem, dass ich das mit den Variablen noch
nicht versucht habe. Es wird leider länger dauern. Könnte mir jemand,
das Programm schreiben?
Im Titel 16F628
Im obersten Post 16.09.2008
list p=16f826
Und mitten drin #include <P16f828.INC>
Ja was denn nun?
>Könnte mir jemand, das Programm schreiben?
Was zahlst du?
>Solche wie du sind eine große Hilfe!
Ich tue mein bestes ;)
>Habe das Programm nach den oberen Empfelungen abgeändert, der Fehler ist>aber immer noch da. Kann es sein, dass es am Netzteil liegt, da der>Fehler nicht passiert, wenn ich den Pic über MCLR resete.
Es liegt wahrscheinlich nicht am Code.
Er hat es immer noch nicht geschafft den Brown Out Reset
zu aktivieren.
init clrf Status
bsf Status,RP0
clrf TrisB
nop
start clrf Status ; interrupt vector
clrf Led
clrf PortB ; all led off
call Wait
movlw 0xff ; led on
movwf PortB ; output it
call Wait_1s
clrf PortB ; alle LED ausschalten
Loop
call Wait
bcf Satus,0
rlf Led,W
skpnz
movlw 1
movwf PortB
movwf Led
goto Loop
Wait_1s call Wait2
Wait2 call Wait
Wait movlw D'250' ;250ms Pause
movwf Loops ;250 in den Zähler schreiben
Wai
Movlw .110 ;Zeitkonstante für 1ms
movwf Loops2
Wai2
goto $+1
goto $+1
gotp $+1
decfsz loops2, F ; 1ms 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
Hallo chris
Hast du das im Editor geschrieben?
Sehr interessant
>skpnz
Diesen Befehl kenne ich nicht
Ist auch nicht im dat. vom P16F628 (finde ihn nicht)
MPLAB zeigt aber kein Fehler an.
skpnz ist ein alias zu
btfsc 3,3
Es ist halt übersichtlicher.
es gibt auch
ADDCF <f>,<dst> Add carry to <f>, result in <dst>
B <addr> Branch
BC <addr> Branch on carry
BZ <addr> Branch on zero
BNC <addr> Branch on no carry
BNZ <addr> Branch on not zero
CLRC Clear carry
CLRZ Clear zero
SETC Set carry
SETZ Set zero
MOVFW <f> Move file to W
NEGF <f> Negate <f>
SKPC Skip on carry
SKPZ Skip on zero
SKPNC Skip on no carry
SKPNZ Skip on not zero
SUBCF <f>,<dst> Subtract carry from <f>, result in <dst>
TSTF <f> Test <f>
Hallo chris
Werde mal alle testen, kannte ich nicht.
Wo steht das ausführlich?
>rlf Led,W>skpnz
Laut meiner Befehlstab. wird doch nur C verändert nicht z,
oder wird auch gleichzeitig "Led" auf Null getestet und Z gesetzt
Gruß
stimmt, wollte eigentlich skpnc nehmen, aber da macht es nach dem
init keine pause, und wenn du das NOP von org 3 auf org 0 setzt, kannst
du es auch debuggen.
So, beim Einschalten, eine Sekunde alle Leds an, als Funktionskontrolle,
danach 1/4 sek alle Leds aus, und dann beginnt das Lauflicht.
Loop
call Wait
bcf Satus,0
rlf Led,f
movf LED,W
skpnz
movlw 1
movwf PortB
movwf Led
goto Loop
stimmt, wollte eigentlich skpnc nehmen, aber da macht es nach dem
init keine pause, und wenn du das NOP von org 3 auf org 0 setzt, kannst
du es auch debuggen.
So, beim Einschalten, eine Sekunde alle Leds an, als Funktionskontrolle,
danach 1/4 sek alle Leds aus, und dann beginnt das Lauflicht.
Sollte zufällig mal ein Interrupt kommen, macht das auch nicht, dann
startet das Ding halt von neuem, und du siehst es auch, aber dann kann
kein Interrupt mehr zustandekommen.
Loop
call Wait
bcf Satus,0
rlf Led,f
movf LED,W
skpnz
movlw 1
movwf PortB
movwf Led
goto Loop