PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Probleme mit Programm (LED-Blinklicht)



G4nd41f
24.10.2008, 16:14
Ich bin Anfänger im Pic-Programmieren und möchte mir deshalb zur Übung erst einmal ein LED-Blinklicht/Lauflicht bauen. Dazu verwende ich einen PIC16F88, den ich nach folgendem Schaltplan angeschlossen habe:

http://www.mstracey.btinternet.co.uk/pictutorial/progtu1.jpg

Es sind allerdings mehrere LEDs an Port A Pins angeschlossen.

Dazu habe ich folgendes Programm für den PIC16F88 angepasst und mit dem Brenne 8 MiniP von Sprut auf den Chip gebrannt:


#include P16f88.INC

;*****Set up the Constants****

STATUS equ 03h ;Address of the STATUS register
TRISA equ 85h ;Address of the tristate register for port A
PORTA equ 05h ;Address of Port A
COUNT1 equ 20h ;First counter for our delay loops
COUNT2 equ 21h ;Second counter for our delay loops

;****Set up the port****

bsf STATUS,5 ;Switch to Bank 1
movlw 00h ;Set the Port A pins
movwf TRISA ;to output.
clrf ANSEL
bcf STATUS,5 ;Switch back to Bank 0

;****Turn the LED on****

Start movlw 1Fh ;Turn the Port A LEDs on by first putting it
movwf PORTA ;into the w register and then on the port

;****Add a delay

call Delay
call Delay


;****Delay finished, now turn the LED off****

movlw 00h ;Turn the LEDs off by first putting it
movwf PORTA ;into the w register and then on the port

;****Add another delay****

call Delay
call Delay


;****Now go back to the start of the program

goto Start ;go back to Start and turn LEDs on again

;****Here is our Subroutine

Delay

Loop1 decfsz COUNT1,1 ;This second loop keeps the LEDs
goto Loop1 ;turned off long enough for us to
decfsz COUNT2,1 ;see it turned off
goto Loop1 ;
return

;****End of the program****

end ;Needed by some compilers, and also
;just in case we miss the goto instruction.

Allerdings habe ich jetzt das Problem, dass die LEDs konstant leuchen, anstatt wie zu erwartend zu blinken. Ich vermute, dass ich irgendetwas mit dem Delay falsch gemacht habe, sehe aber nicht was. Könnt ihr mir hier bitte weiterhelfen ?

Mixxer
24.10.2008, 16:58
Hast du n Oszilloskop?? Dann schau mal deinen Ausgang an, evtl. blinkt deine LED so schnell, dass man s nicht sieht! Mit dem Code kann ich nicht viel anfangen, da AVR Assembler ein bisschen anderst ist, allerdings solltest du etwa so vorgehen:
-Port umschalten
-Warten
-Port umschalten
-Warten
-zurück auf Anfang

MFG Mixxer

G4nd41f
24.10.2008, 17:13
Ich gehe im Prinzip so vor wie du beschrieben hast.

Leider habe ich kein Oszi hier. Wenn ich allerdings mein Multimeter auf Wechselspannung stelle und eine LED messe, dann messe ich so 4V. Wenn ich es auf Gleichspannung stelle, dann so 2V. Also wird es wohl wie vermutet die Delay-Subroutine sein die nicht funktioniert. Was stimmt hier nicht?

Mixxer
24.10.2008, 17:26
eine Delay-Subroutine in Assembler zählt ein Register hoch oder runter bis es einen bestimmten Wert erreicht, dann springt er wieder aus der Routine. Du musst schauen was das (es können auch mehrere) Register ist und schauen mit was es vorgeladen wird und wie gezählt wird. Dann kannst du über den Takt feststellen, was die Delay-Zeit ist. Wenn diese ca. kleiner wie 20ms ist siehst du von der LED nur noch Dauerlicht.
Du solltest das Register also so laden dass die Zeit z.B. 0,5s lang ist, dann siehst du ein schönes Blinken!

So wie es bei dir aussieht heißen die beiden Register für die Delay "COUNT1 und COUNT2". Ich sehe aber weder wo sie vorgeladen werden (muss immer am Anfang von der Subroutine passieren) und wo sie für das weiterspringen mit einem bestimmten Wert geprüft werden. Außer das macht alles der Befehl "decfsz". Wie gesagt, mit PIC ASM kenn ich mich nicht so gut aus!

MFG Mixxer

G4nd41f
24.10.2008, 17:36
decfsz erhöht den Register um 1 und überspringt den Befehl in der nächsten Reihe, wenn das Register "voll" ist.

Mixxer
24.10.2008, 17:44
Dann schau doch mal wie viel Takte der PIC für die Delay-Schleife benötigt und errechne mal mit der Taktzeit vom µC die Verzugszeit!

wberger
24.10.2008, 18:14
decfsz erhöht den Register um 1 und überspringt den Befehl in der nächsten Reihe, wenn das Register "voll" ist.
Fast richtig. Das wäre incfsz. dec bedeutet decrement. Zählt also abwärts.

wberger
24.10.2008, 18:18
Dein PIC hat keinen Takt. Der RC Oszillator gehört an OSC1 nicht an OSC2. Außerdem empfiehlt das Datenblatt einen R1 von <= 100kOhm.

Hast du das gefixt ist sicherlich die Delay Routine viel zu lange. Bei Verwendung von 220pF und 100kOhm hast du ganz grob einen Takt von 40kHz. Durch 4 gibt das intern 10kHz Ausführungsgeschwindigkeit. Deine Delay Routine ist eine Doppelt verschachtelte Schleife mit insgesamt
255*255=65025 Durchläufen. Enthalten sind zwei Befehle. Das ergibt einen Delay von rund 12 Sekunden.

Außerdem lädst du die Register nicht mit sinnvollen Werten vor. Dadurch ist es beim ersten Durchlauf dem Zufall überlassen was drin steht. Später stehen die dann immer auf Null und springen durch decfsz auf 255.

Schau mal den modifzierten Code an. Dort sollten die LEDs mit dem Vorgeschlagenen Oszillator grob im 1/2 Sekundentakt blinken.



Generell:
ich würde bevorzugt die vordefinierten macros verwenden.
Statt
bsf STATUS,5
besser
bsf STATUS, RP0
oder besser gleich
banksel TRISA

statt
decfsz COUNT1,1
besser
decfsz COUNT1,f

macht das ganze lesbarer und weniger fehleranfällig.


#include P16f88.INC

;*****Set up the Constants****

STATUS equ 03h ;Address of the STATUS register
TRISA equ 85h ;Address of the tristate register for port A
PORTA equ 05h ;Address of Port A
COUNT1 equ 20h ;First counter for our delay loops
COUNT2 equ 21h ;Second counter for our delay loops

;****Set up the port****

bsf STATUS,RP0 ;Switch to Bank 1
movlw 00h ;Set the Port A pins
movwf TRISA ;to output.
clrf ANSEL
bcf STATUS,RP0 ;Switch back to Bank 0

;****Turn the LED on****

Start movlw 1Fh ;Turn the Port A LEDs on by first putting it
movwf PORTA ;into the w register and then on the port

;****Add a delay

call Delay

;****Delay finished, now turn the LED off****

movlw 00h ;Turn the LEDs off by first putting it
movwf PORTA ;into the w register and then on the port

;****Add another delay****

call Delay


;****Now go back to the start of the program

goto Start ;go back to Start and turn LEDs on again

;****Here is our Subroutine

Delay
movlw 255
movwf COUNT1 ;Load count1 with init value
movlw 10
movwf COUNT2 ;Load count1 with init value


Loop1 decfsz COUNT1,f ;This second loop keeps the LEDs
goto Loop1 ;turned off long enough for us to
decfsz COUNT2,f ;see it turned off
goto Loop1 ;
return

;****End of the program****

end ;Needed by some compilers, and also
;just in case we miss the goto instruction.

G4nd41f
24.10.2008, 18:53
Danke, jetzt gehts :)

G4nd41f
24.10.2008, 19:50
Habe mich wohl zu früh gefreut. Ich habe jetzt mal den Delay ein wenig verkürzt und schon machen die Leds nicht mehr das was ich will. Hier erst mal der Code:


#include P16f88.INC

;*****Set up the Constants****

STATUS equ 03h ;Address of the STATUS register
TRISA equ 85h ;Address of the tristate register for port A
PORTA equ 05h ;Address of Port A
COUNT1 equ 20h ;First counter for our delay loops
COUNT2 equ 21h ;Second counter for our delay loops

;****Set up the port****

bsf STATUS,RP0 ;Switch to Bank 1
movlw 00h ;Set the Port A pins
movwf TRISA ;to output.

clrf ANSEL
bcf STATUS,RP0 ;Switch back to Bank 0


movlw 00h ;
movwf PORTA

;****Turn the 1st LED on****

Start movlw 04h ;Turn the Port A LEDs on by first putting it
movwf PORTA ;into the w register and then on the port



call Delay
;2nd LED

movlw 08h ;Turn the Port A LEDs on by first putting it
movwf PORTA ;into the w register and then on the port
call Delay


;****Delay finished, now turn the LED off****

movlw 00h ;Turn the LEDs off by first putting it
movwf PORTA ;into the w register and then on the port

call Delay


;****Now go back to the start of the program

goto Start ;go back to Start and turn LEDs on again

;****Here is our Subroutine

Delay
movlw 5
movwf COUNT1 ;Load count1 with init value
movlw 5
movwf COUNT2 ;Load count1 with init value


Loop1 decfsz COUNT1,f ;This second loop keeps the LEDs
goto Loop1 ;turned off long enough for us to
decfsz COUNT2,f ;see it turned off
goto Loop1 ;
return

;****End of the program****

end ;Needed by some compilers, and also
;just in case we miss the goto instruction.

end ;Needed by some compilers, and also
;just in case we miss the goto instruction.

Es soll folgendes passieren:
LED1 an->Pause->LED1 aus und LED2 an->Pause->Neustart
Es passiert aber folgendes:
LED1 an-> Pause->LED1 aus und LED2 an->Pause->LED2 aus und LED1an> Pause->LED1 aus und LED2 an->lange Pause-> Neustart

Woher kommt diese lange Pause alle zwei Durchläufe ?

Wenn ich jetzt den Delay auf deinen ursprünglichen Wert erhöhe, dann
kommen nur zwei Wechsel anstatt drei vor der langen Pause.

LED 1 hängt übrigens an RA2 und LED2 an RA3.

wberger
25.10.2008, 14:25
Der von dir gepostete Code sollte eigentlich folgendes machen

LED1 an -> Pause -> LED2 an, LED1 aus -> Pause -> Alles aus -> Pause -> Start

Kann es sein, dass dein PIC nicht stabil läuft. Löte mal einen 100nF Kondensator zwischen VDD und VSS und zwar so nahe wie möglich am PIC. Am besten direkt darunter zwischen den Pins. Oder hast du den Kondensator bereits und nur nicht im Schaltplan gezeichnet?

Gruß
Wolfgang

G4nd41f
25.10.2008, 15:05
Mein LED Lauflicht funktioniert inzwischen. Allerdings hat sich jetzt ein neues Problem ergeben. Der PIC läuft nicht kontinuierlich durch, sondern startet das Programm nach einer bestimmten Zeit immer neu. Das erkenne ich daran, dass das Lauflicht nach einem Mal durchlaufen nur noch ein halbes Mal durchläuft und dann wieder von vorne anfängt.
Ich versorge den PIC mit 5V über ein USB-Kabel. Benutzen tue ich den internen Oszilator des PIC16F88. Zur Entstörung habe ich schon einen 100nF Kondensator zwischen VDD und VSS gehängt (direkt unter die Pins). Wie kann ich dieses Problem beheben?

Hier ist zur Sicherheit auch nochmal der Code:


#include P16f88.INC

;*****Set up the Constants****

STATUS equ 03h ;Address of the STATUS register
TRISA equ 85h ;Address of the tristate register for port A
PORTA equ 05h ;Address of Port A
TRISB equ 86h
PORTB equ 06h
OSCCON equ 8Fh
COUNT1 equ 20h ;First counter for our delay loops
COUNT2 equ 21h ;Second counter for our delay loops

;****Set up the port****
call Delay

bsf STATUS,RP0 ;Switch to Bank 1
movlw 10h ;Set the Port A pins
movwf TRISA
movlw 01h ;Set the Port B pins
movwf TRISB
movlw 2Eh
movwf OSCCON
clrf ANSEL
bcf STATUS,RP0 ;Switch back to Bank 0


movlw 00h ;
movwf PORTA
movlw 00h
movwf PORTB

;****Turn the 1st LED on****

Start movlw 04h ;Turn the Port A LEDs on by first putting it
movwf PORTA ;into the w register and then on the port
call Delay
btfsc PORTA,4 ;if RA4 is on, the next instruction is skipped
call Delay
;2nd LED

movlw 08h ;Turn the Port A LEDs on by first putting it
movwf PORTA ;into the w register and then on the port
call Delay
btfsc PORTA,4
call Delay

;3rd LED****

movlw 00h ;Turn the LEDs off by first putting it
movwf PORTA ;into the w register and then on the port
movlw 02h ;Turn LED on RB1 on
movwf PORTB
call Delay
btfsc PORTA,4
call Delay

;4th LED

movlw 04h
movwf PORTB
call Delay
btfsc PORTA,4
call Delay
;5th LED


movlw 10h
movwf PORTB
call Delay
btfsc PORTA,4
call Delay
;6th LED

movlw 20h
movwf PORTB
call Delay
btfsc PORTA,4
call Delay
;turn all off

movlw 00h
movwf PORTB
call Delay
btfsc PORTA,4
call Delay
;****Now go back to the start of the program

goto Start ;go back to Start and turn LEDs on again

;****Here is our Subroutine

Delay
movlw 30
movwf COUNT1 ;Load count1 with init value
movlw 10
movwf COUNT2 ;Load count2 with init value


Loop1 decfsz COUNT1,f ;This second loop keeps the LEDs
goto Loop1 ;turned off long enough for us to
decfsz COUNT2,f ;see it turned off
goto Loop1 ;
return


;****End of the program****

end ;Needed by some compilers, and also
;just in case we miss the goto instruction.

end ;Needed by some compilers, and also
;just in case we miss the goto instruction.

Lif79
25.10.2008, 20:13
hast du den watchdogTimer deaktiviert???, der würde nach ablauf für ein reset des µC sorgen...

G4nd41f
26.10.2008, 09:27
Ich denke, das ich das nicht getan habe. Kann mir jemand bitte sagen, wie das geht bzw. wie das zugehörige Register heißt, nachdem ich im Datenblatt suchen muss?

MrNiemand
26.10.2008, 09:44
Ich würde mal an die 5V Leitung vom USB Anschluss noch mal so ca. 100µF hängen. Bei meiner Dockingstation z.b. hatte ich ansonsten eine Restwelligkeit von ca 0,5V bei 20khz. Kann schon sein das du ein deratiges Problem hast.

G4nd41f
26.10.2008, 10:02
Ok, es war der Watchdogtimer. Gibt wohl ein paar Tricks die man als Anfänger lernen muss.

Lif79
26.10.2008, 10:10
Ich weiß ja nicht genau was du benutzt, aber in MPLAB kann man auf jeden fall die Config-Werte in die *.asm datei schreiben.

z.B.


#include P16f88.INC

; Configuration festlegen
__CONFIG _CP_OFF & _DEBUG_OFF & _WDT_OFF & _PWRTE_ON & _EXTRC_IO

;*****Set up the Constants****

STATUS equ 03h ;Address of the STATUS register
TRISA equ 85h ;Address of the tristate register for port A
PORTA equ 05h ;Address of Port A
TRISB equ 86h
PORTB equ 06h
OSCCON equ 8Fh
COUNT1 equ 20h ;First counter for our delay loops
COUNT2 equ 21h ;Second counter for our delay loops

;****Set up the port****
call Delay

bsf STATUS,RP0 ;Switch to Bank 1
movlw 10h ;Set the Port A pins
movwf TRISA
movlw 01h ;Set the Port B pins
movwf TRISB
movlw 2Eh
movwf OSCCON
clrf ANSEL
bcf STATUS,RP0 ;Switch back to Bank 0


movlw 00h ;
movwf PORTA
movlw 00h
movwf PORTB

;****Turn the 1st LED on****

Start movlw 04h ;Turn the Port A LEDs on by first putting it
movwf PORTA ;into the w register and then on the port
call Delay
btfsc PORTA,4 ;if RA4 is on, the next instruction is skipped
call Delay
;2nd LED

movlw 08h ;Turn the Port A LEDs on by first putting it
movwf PORTA ;into the w register and then on the port
call Delay
btfsc PORTA,4
call Delay

;3rd LED****

movlw 00h ;Turn the LEDs off by first putting it
movwf PORTA ;into the w register and then on the port
movlw 02h ;Turn LED on RB1 on
movwf PORTB
call Delay
btfsc PORTA,4
call Delay

;4th LED

movlw 04h
movwf PORTB
call Delay
btfsc PORTA,4
call Delay
;5th LED


movlw 10h
movwf PORTB
call Delay
btfsc PORTA,4
call Delay
;6th LED

movlw 20h
movwf PORTB
call Delay
btfsc PORTA,4
call Delay
;turn all off

movlw 00h
movwf PORTB
call Delay
btfsc PORTA,4
call Delay
;****Now go back to the start of the program

goto Start ;go back to Start and turn LEDs on again

;****Here is our Subroutine

Delay
movlw 30
movwf COUNT1 ;Load count1 with init value
movlw 10
movwf COUNT2 ;Load count2 with init value


Loop1 decfsz COUNT1,f ;This second loop keeps the LEDs
goto Loop1 ;turned off long enough for us to
decfsz COUNT2,f ;see it turned off
goto Loop1 ;
return


;****End of the program****

end ;Needed by some compilers, and also
;just in case we miss the goto instruction.

end ;Needed by some compilers, and also
;just in case we miss the goto instruction.

Ich gebe dir jetzt abner keine garantie das die entsprechenden Config-Werte für deine Versuche die richtigen sind....
Alle Config-Befehle kannst du am Ende der p16f88.INC Nachlesen, wofür die stehen und was die bewirken steht im Datenblatt!

Wenn du ein Brennprogramm von Sprut benutzt kannst du die Config-Werte auch direkt im Brennprogramm einstellen, auf der seite www.sprut.de ist das mit der Configuration auch noch mal erklärt.

Ein 100µF Elko schadet natürlich nicht.

pointhi
07.06.2009, 14:11
Ich bin selber noch Anfänger, und würde dir dieses Buch empfehlen:

PICs für Einsteiger
ISBN 3-7723-4994-3

Mir hat es viel geholfen und hat auch viele Anfängerfehler vermieden. Das Buch beschäftigt sich halt nur mit dem Controller 12F629 und 12F675, aber es ist eine gute Grundlage. Ich bin danach ohne Probleme gleich auf die 16Fxxx Reihe umgestiegen. Ich hab dass Buch beim Conrad bekommen
Und wegen dem Blinklicht: Dass wird in diesem Buch auch ausführlich beschrieben.

PICture
19.06.2009, 21:20
Hallo!

Wie wäre es mit dem Wiki Artikel?

http://www.rn-wissen.de/index.php/PIC_Assembler

MfG