Sida 1 av 1

Pic16f877a problem med RRF. Försök till en s.k. nightrider

Postat: 16 februari 2012, 14:04:51
av Spket
Hej!
Efter några år uppe på vinden så har jag åter igen tagit ner mina elektronikprylar för att laborera lite. Mycket har försvunnit ur huvudet.
Har boken mikrocontrollers skriven av Lars Bengtsson (andra utgåvan) framför mig och sidan http://pcbheaven.com/picpages/General_k ... tructions/ för att försöka förstå hur alla fungerar. Utöver det så tittar jag i databladet för PIC16f877a http://ww1.microchip.com/downloads/en/D ... 39582b.pdf

Jag har stött på ett problem. Jag har 8st lysdioder som är kopplade PORTD på min pic. När jag försöker mig på att rotera bitarna så stannar den på 0x02 och vill inte fortsätta till 0x01.
Ett försök till en illustration.
10000000 - 01000000 - 00100000 - 00010000 - 00001000 - 00000100 - 00000010 (här stannar den). Värdet W vill alltså inte bli 00000001.

Koden. Jag har följt exemplet som följer med i PICKIT 2 men försökt få den till en annan pic med 8 utgångar i stället för 4.

Kod: Markera allt

	list		p=16f877A	; list directive to define processor
	#include	<p16f877A.inc>	; processor specific variable definitions
	
    __CONFIG   _CP_OFF & _LVP_OFF & _BODEN_OFF &  _WDT_OFF & _PWRTE_ON & _HS_OSC

#define	J 		0x20
#define	K 		0x21
#define	Display 0x22
org	0

Start:					;Initierar de första instruktionerna
bsf		STATUS,RP0		; Väljer Bank1
clrf	TRISD			; Gör alla portar på PORTD till output
bcf		STATUS,RP0		; Tillbaka till Bank0
movlw	0x80			; Laddar W med 10000000
movwf	Display			; Flytta W till Display


MainLoop:
movf	Display,w		; Flytta värdet i Display till W
movwf	PORTD			; Flytta W till PORTD
call	OndelayLoop		; Dröj här en stund

Rotate:
bcf		STATUS,C		; Rensa Carryn
btfss	Display,0		; Hoppa över nästa instruktion om bit0 i Display = 1
goto	Rotateright		; Hoppa till RotateRight
goto	Rotateleft		; Hoppa till RotateLeft

Rotateright:
rrf		Display,f		; Rotera värdet i Display åt höger, spara sen det nya värdet i Display
btfsc	Display,0		; Hoppa över nästa instruktion om bit0 i Display =0
goto	Rotateleft		; Hoppa till Rotateleft
goto	MainLoop		; Hoppa till MainLoop

Rotateleft:
rlf		Display,f		; Rotera värdet i Display åt vänster, spara sen det nya värdet i Display
btfsc	Display,7		; Hoppa över nästa instruktion om värdet i bit7 (MSB) i Display = 0
goto	Rotateright
goto	MainLoop




OndelayLoop:
     decfsz    J,f            ; Waste time.  
     goto      OndelayLoop         ; The Inner loop takes 3 instructions per loop * 256 loopss = 768 instructions
     decfsz    K,f            ; The outer loop takes and additional 3 instructions per lap * 256 loops
     goto      OndelayLoop         ; (768+3) * 256 = 197376 instructions / 1M instructions per second = 0.197 sec.
                                   ; call it a two-tenths of a second.
return



end						; Avslutar programmet

Tittade i simulatorn i MPLAB med några breakpoints. W fastnar alltså på 0x02 och sen så loopar den bara runt där.
Någon som har en idé om vad som kan vara felet?

Re: Pic16f877a problem med RRF. Försök till en s.k. nightrid

Postat: 16 februari 2012, 14:10:18
av sodjan
> Tittade i simulatorn i MPLAB med några breakpoints...

Ja, det beror ju helt på *var* du har satt dom.
Singelsteppa istället genom allt utan delayen.
Eller sätt en breakpoint direkt efter labeln "Rotateleft".

Jag tror jag ser vad som händer, men är inte helt säker...

Re: Pic16f877a problem med RRF. Försök till en s.k. nightrid

Postat: 16 februari 2012, 14:24:23
av Spket
Aha, tack för svaret
Jag tror jag ser problemet.
Den fastnar i en loop mellan RRF och RLF när Display får värdet 0x01.
Får försöka lista ut hur jag kommer därifrån.

Re: Pic16f877a problem med RRF. Försök till en s.k. nightrid

Postat: 16 februari 2012, 14:32:18
av sodjan
Japp, du kan inte hoppa direkt från "höger" till "vänster" utan att "passera gå", så att säga.
Ställ bara om "riktningen" och gå tillbaka till main istället...

Re: Pic16f877a problem med RRF. Försök till en s.k. nightrid

Postat: 16 februari 2012, 14:46:31
av Spket
Jag undrar om jag lekt rövare med exempel projektet från PICKIT2 innan. Den gör nämligen samma sak när jag testkör den i MPLAB. Ska klura lite mer på problemet.. Det är svårt det här med logiskt tänkande

Re: Pic16f877a problem med RRF. Försök till en s.k. nightrid

Postat: 16 februari 2012, 14:50:14
av sodjan
Aja, jag bli lite osäker nu när jag tittar igen.

Men, det är ju väldigt enkelt att singelsteppa...

Re: Pic16f877a problem med RRF. Försök till en s.k. nightrid

Postat: 16 februari 2012, 15:37:28
av Spket
Lyckades lösa den oönskade loopen genom att lägga till ett Register 'Direction' som blev 0(åt vänster) eller 1(åt höger) om värdet roterade in i Carry. Däremot så blev 'Display' till slut 0 och då fanns det ingen bit kvar att rotera. Löste detta genom att kolla om STATUS,Z blev 1. Då fick jag helt enkelt ladda 'Display' med ett nytt värde.

Ny kod

Kod: Markera allt

	list		p=16f877A	; list directive to define processor
	#include	<p16f877A.inc>	; processor specific variable definitions
	
    __CONFIG   _CP_OFF & _LVP_OFF & _BODEN_OFF &  _WDT_OFF & _PWRTE_ON & _HS_OSC

#define	J 		0x20
#define	K 		0x21
#define	Display 0x22
#define Direction 0x23
org	0

Start:					;Initierar de första instruktionerna
bsf		STATUS,RP0		; Väljer Bank1
clrf	TRISD			; Gör alla portar på PORTD till output
bcf		STATUS,RP0		; Tillbaka till Bank0
movlw	0x80			; Laddar W med 10000000
movwf	Display			; Flytta W till Display
clrf	Direction		; Rensa Direction
bcf		STATUS,Z

MainLoop:
movf	Display,w		; Flytta värdet i Display till W
movwf	PORTD			; Flytta W till PORTD
call	OndelayLoop		; Dröj här en stund

Rotate:
bcf		STATUS,C		; Rensa Carry
btfss	Direction,0		; Om bit0 i Direction = 1, hoppa över nästa instruktion
goto	Rotateright
goto	Rotateleft

Rotateright:
rrf		Display,f		; Rotera värdet i Display åt höger, spara sen det nya värdet i Display
btfsc	STATUS,C		; Roterade värdet in i Carryn?
bsf		Direction,0		; I så fall sätt bit0 i Direction = 1
btfsc	STATUS,Z		; Gjorde det så att värdet blev 0?
goto	Hoger0			; I så fall hoppa till Hoger0
goto	MainLoop		; Hoppa till MainLoop

Rotateleft:
rlf		Display,f		; Rotera värdet i Display åt vänster, spara sen det nya värdet i Display
btfsc	STATUS,C		; Roterade värdet in i Carryn?
bcf		Direction,0		; I så fall sätt bit0 i Direction = 0
btfsc	STATUS,Z		; Gjorde det så att värdet blev 0?
goto	Vanster0		; I så fall hoppa till Vanster0
goto	MainLoop

Vanster0:
movlw	0x01			; Ladda W med 0x01
movwf	Display			; Flytta W till Display
goto	MainLoop

Hoger0:
movlw	0x80			; Ladda W med 0x80
movwf	Display			; Flytta W till Display
goto	MainLoop


OndelayLoop:
     decfsz    J,f            ; Waste time.  
     goto      OndelayLoop         ; The Inner loop takes 3 instructions per loop * 256 loopss = 768 instructions
     decfsz    K,f            ; The outer loop takes and additional 3 instructions per lap * 256 loops
     goto      OndelayLoop         ; (768+3) * 256 = 197376 instructions / 1M instructions per second = 0.197 sec.
                                   ; call it a two-tenths of a second.
return



end						; Avslutar programmet
Kanske finns ett lättare sätt att lösa det på men detta klurade jag ut nästan helt själv!

Edit:
Kom på ett enklare sätt att ladda 'Display' med ett nytt värde genom instruktionen BSF

Kod: Markera allt


	list		p=16f877A	; list directive to define processor
	#include	<p16f877A.inc>	; processor specific variable definitions
	
    __CONFIG   _CP_OFF & _LVP_OFF & _BODEN_OFF &  _WDT_OFF & _PWRTE_ON & _HS_OSC

#define	J 		0x20
#define	K 		0x21
#define	Display 0x22
#define Direction 0x23
org	0

Start:					;Initierar de första instruktionerna
bsf		STATUS,RP0		; Väljer Bank1
clrf	TRISD			; Gör alla portar på PORTD till output
bcf		STATUS,RP0		; Tillbaka till Bank0
movlw	0x80			; Laddar W med 10000000
movwf	Display			; Flytta W till Display
clrf	Direction		; Rensa Direction
bcf		STATUS,Z

MainLoop:
movf	Display,w		; Flytta värdet i Display till W
movwf	PORTD			; Flytta W till PORTD
call	OndelayLoop		; Dröj här en stund

Rotate:
bcf		STATUS,C		; Rensa Carry
btfss	Direction,0		; Om bit0 i Direction = 1, hoppa över nästa instruktion
goto	Rotateright
goto	Rotateleft

Rotateright:
rrf		Display,f		; Rotera värdet i Display åt höger, spara sen det nya värdet i Display
btfsc	STATUS,C		; Roterade värdet in i Carryn?
bsf		Direction,0		; I så fall sätt bit0 i Direction = 1
btfsc	STATUS,Z		; Gjorde det så att värdet blev 0?
bsf		Display,7		; I så fall gör bit7 i Display=1
goto	MainLoop		; Hoppa till MainLoop

Rotateleft:
rlf		Display,f		; Rotera värdet i Display åt vänster, spara sen det nya värdet i Display
btfsc	STATUS,C		; Roterade värdet in i Carryn?
bcf		Direction,0		; I så fall sätt bit0 i Direction = 0
btfsc	STATUS,Z		; Gjorde det så att värdet blev 0?
bsf		Display,0		; I så fall gör bit0 i Display=1
goto	MainLoop


OndelayLoop:
     decfsz    J,f            ; Waste time.  
     goto      OndelayLoop         ; The Inner loop takes 3 instructions per loop * 256 loopss = 768 instructions
     decfsz    K,f            ; The outer loop takes and additional 3 instructions per lap * 256 loops
     goto      OndelayLoop         ; (768+3) * 256 = 197376 instructions / 1M instructions per second = 0.197 sec.
                                   ; call it a two-tenths of a second.
return



end						; Avslutar programmet