PIC16F684 Programming in Assembly

Thread Starter

Tomahawk640

Joined Feb 20, 2009
20
I'm relatively new to PIC programming, but I have some idea of what's going on. I'm working on a senior project that requires bipolar stepper motor control. The problem I'm having is that I need the program to start after a signal has been sent to one of the I/O pins. I went to a tutorial site: http://www.mstracey.btinternet.co.uk/pictutorial/progtut6.htm and tried copying and pasting some code. I keep getting the error "Register in operand not in bank 0. Ensure that bank bits are correct." However, just before the line that's giving the error, I changed the RP0 bit in the STATUS register to the correct setting, but it still gives me the error. I've posted this portion below. Any help you can provide would be greatly appreciated.

...
movlw 03h
movwf STATUS ;Address of the STATUS register
bsf STATUS, RP0
movlw 85h
movwf TRISA ;Address of the tristate register for port A
movlw 05h
movwf PORTA ;Address of Port A
bsf STATUS,5 ;Switch to Bank 1
movlw 01h ;Set the Port A pins
movwf TRISA ;to input.
bcf STATUS,5 ;Switch back to Bank 0
BTFSS PortA,0
...
 

Thread Starter

Tomahawk640

Joined Feb 20, 2009
20
Thank you, that cleared up the errors, but unfortunately, the program didn't work as intended. As soon as I gave it power the program started. I don't want anything to happen until I get a high signal on one of the pins.

Also, I thought I could handle this, but I've been having problems getting some of the conditional code to work. Towards the end of the section below, there's a conditional statement that will jump out of Loop after a variable reaches 0. For whatever reason it doesn't break out of the loop. Thanks again for any help you can provide.

...
movlw 05h
movwf COUNT1
...
Loop: ; Return Here for Next Value
addlw -1 ; add -1 to w?
btfsc STATUS,Z ; skip on no carry at digit Z
decfsz Dlay, f
goto $ - 3
movf i, w
call SwitchRead
movwf PORTC
incf i, f ; i=(i+1) % 8;
bcf i, 3

decfsz COUNT1, 1 ;decrease COUNT,skip next if=0
goto Loop
goto Loop2
...
SwitchRead:
addwf PCL, f ; Staying in First 256 Instructions
dt b'010100', b'011000', b'101000' ;ccw
...
 

Thread Starter

Tomahawk640

Joined Feb 20, 2009
20
Well, I decided to break it down to one step at a time. I just want it to run a certain amount of times before ending. I tried using a counter "INNER" below in "ccwLoop" to count down until it reached zero and then head for an infinite loop as shown below. However, the program stays in the loop for some reason. Does anyone have any idea why?

--code--
...
...
movlw 20
movwf INNER
ccwLoop:
call ccwstep
decfsz INNER, 1
goto ccwLoop

stopmotor2:
goto stopmotor2

ccwstep: ; Return Here for Next Value
;movlw HIGH ((250000 / 5) + 256);250ms
movlw HIGH ((100000 / 5) + 256);100ms
movwf Dlay
;movlw LOW ((250000 / 5) + 256);250ms
movlw LOW ((100000 / 5) + 256);100ms
addlw -1 ; add -1 to w
btfsc STATUS,Z ; skip on no carry at digit Z
decfsz Dlay, f
goto $ - 3

movf i, w
call SwitchRead
movwf PORTC

incf i, f ; i=(i+1) % 8;
bcf i, 3

return
SwitchRead:
addwf PCL, f ; Staying in First 256 Instructions
dt b'010100', b'011000', b'101000' ;ccw
return


end
 

Thread Starter

Tomahawk640

Joined Feb 20, 2009
20
At the beginning of the program:

...(just comments above this line)
LIST R=DEC
INCLUDE "p16f684.inc"
__CONFIG _FCMEN_OFF & _IESO_OFF & _BOD_OFF & _CPD_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTOSCIO

; Variables
CBLOCK 0x20
Dlay, i, INNER, OUTER
ENDC
 

Thread Starter

Tomahawk640

Joined Feb 20, 2009
20
For whatever reason it doesn't jump out of the loop. If I make INNER=1, the motor will only take 1 step, 2 it will take 2 steps, anything more than that and it'll just keep going.

I may as well just put up the whole program:



LIST R=DEC
INCLUDE "p16f684.inc"
__CONFIG _FCMEN_OFF & _IESO_OFF & _BOD_OFF & _CPD_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTOSCIO

; Variables
CBLOCK 0x20
Dlay, i, INNER, OUTER
ENDC

PAGE
; Mainline

org 0

nop ; For ICD Debug
movlw 20
movwf OUTER
movlw 1 << 2 ; Start with Bit 2 Active
movwf PORTC
movlw 7 ; Turn off Comparators
movwf CMCON0
bsf STATUS, RP0 ; Execute out of Bank 1
clrf ANSEL ^ 0x080 ; All Bits are Digital
movlw 1 << 2 ; Start with Bit 2 Active
movwf PORTC
movlw 7 ; Turn off Comparators
movwf CMCON0
bsf STATUS, RP0 ; Execute out of Bank 1
clrf ANSEL ^ 0x080 ; All Bits are Digital
movlw b'000011' ; RC5:RC2 are Outputs
movwf TRISC ^ 0x080
bcf STATUS, RP0 ; Return Execution to Bank 0

clrf i

;ccwLoop2:
movlw 20
movwf INNER
ccwLoop:
call ccwstep
decfsz INNER, 1
goto ccwLoop

stopmotor2:
goto stopmotor2
;decfsz OUTER, 1
;goto ccwLoop



ccwstep: ; Return Here for Next Value
;movlw HIGH ((250000 / 5) + 256);250ms
movlw HIGH ((100000 / 5) + 256);100ms
movwf Dlay
;movlw LOW ((250000 / 5) + 256);250ms
movlw LOW ((100000 / 5) + 256);100ms
addlw -1 ; add -1 to w
btfsc STATUS,Z ; skip on no carry at digit Z
decfsz Dlay, f
goto $ - 3

movf i, w
call SwitchRead
movwf PORTC

incf i, f ; i=(i+1) % 8;
bcf i, 3

return

;stopmotor:
;goto stopmotor


SwitchRead:
addwf PCL, f ; Staying in First 256 Instructions
dt b'010100', b'011000', b'101000' ;ccw
return


end
 

n9352527

Joined Oct 14, 2005
1,198
Right, I see where the problem is. That SwitchRead function, what exactly are you trying to do there? Try commenting that call and check the loop again, the loop will work as intended.

In SwitchRead, you are offsetting the PCL by the value in W, which is copied from variable i. i starts from 0 and increased by one, but bit 3 is resetted every time. So i goes from 0 to 7 (0000 0111). Now, you have 3 data table (!), with only 6 bits defined, as the PCL offset destination. Because that PIC has 14 bits opcodes, that data table will be padded to 14 bits. Bits 6 and 7 from the low 8 bits will be 0, and bits from the high 6 bits will be 0x34, the default retlw instruction. Resulting in retlw instruction, returning the 6 bits in data table each time, which is written to PORTC.

Is this what you are trying to do? If yes, then fine (although it is not exactly the clearest way of doing that look up table). Why don't you use series of 'retlw value' instructions instead?

The mistake is you only have 3 offset destinations in the data table, plus one more in the following return instruction (without setting W return value). But you have 8 offsets in total (0-7). After the first 4 jumps, the value of i is 4, then you are offsetting the PCL past the data table, the return and the end of the program. No guessing what's the default value is there, and where the PCL actually ends up.

Either you clear bit 2 of i, instead of bit 3 (giving you 4 offsets, which 3 will return set values, and one default return, are you sure this is the correct intention?). Or add more dt to cover all 8 offsets.
 

Thread Starter

Tomahawk640

Joined Feb 20, 2009
20
I was taking a pre-existing program and modifying it to what I needed, as I said I'm still relatively new to this so I didn't know exactly how the instructions in the table worked as well some other spots. It makes sense that PCL went from 0 to 7...the original program was intended for another stepper motor that had 8 values in the table. I will try clearing bit 2 of i. Thank you so much!
 

Thread Starter

Tomahawk640

Joined Feb 20, 2009
20
OK, I got it to work, thanks again! I do need to make more modifications to the program like having it exit a loop from a start only when an input is detected in PORTA (don't want it to start right away), I'll need a delay after the turns are complete, and I need it to turn in the opposite direction the same amount of turns as the first. So if I run into any more problems, I'll just ask.
 

Thread Starter

Tomahawk640

Joined Feb 20, 2009
20
I was able to get everything I wanted to work except the input requirement in PORTA. I tried taking the code straight from http://www.mstracey.btinternet.co.uk/pictutorial/progtut6.htm since the register addresses are the same, but if I apply a signal to the RA0 pin nothing happens:


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 08h ;First counter for our delay loops
COUNT2 equ 09h ;Second counter for our delay loops
;****Set up the port****
bsf STATUS,5 ;Switch to Bank 1
movlw 01h ;Set the Port A pins:
movwf TRISA ;bit 1to output, bit 0 to input.
bcf STATUS,5 ;Switch back to Bank 0
Start:
btfss PORTA, 0 ;skip next line if bit 0 is set in PORTA
goto Start
 

n9352527

Joined Oct 14, 2005
1,198
RA0 is multiplexed with analog pin for the comparator. Get the datasheet and find out how to set those pins to digital IO and turn off the comparator. It should be in the register CMCON0.
 

Thread Starter

Tomahawk640

Joined Feb 20, 2009
20

n9352527

Joined Oct 14, 2005
1,198
Always go to Microchip site for the current datasheet. The current revision is F (41202F). Look at page 58 and 61. Set bits 0 - 2 (CM<2:0>) of CMCON0 to turn off comparator and set the pins to digital IO.
 

Thread Starter

Tomahawk640

Joined Feb 20, 2009
20
Hate to say it, but I still can't get it to work. I should have PORTA ready for input and the comparators should be off and the I/O has been turned to digital. This is what I've tried:


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
;****Set up the port****
bsf STATUS,5 ;Switch to Bank 1
movlw 01h ;Set the Port A pins:
movwf TRISA ;bit 1to output, bit 0 to input.
bcf STATUS,5 ;Switch back to Bank 0

movlw b'111'
movwf CMCON0
Start:
btfss PORTA, 0 ;skip next line if bit 0 is set in PORTA
goto Start
 

n9352527

Joined Oct 14, 2005
1,198
Try moving the CMCON0 setting up, before changing the TRISA setting. What do you have connected to RA0 pin? Try putting a delay after setting PORTA and reading RA0.
 

Thread Starter

Tomahawk640

Joined Feb 20, 2009
20
I tried moving the CMCON0 setup before the TRISA setting and adding a delay with the same problem. I'm connecting a wire from the power supply to RA0 to set it.
 

n9352527

Joined Oct 14, 2005
1,198
That wire might create a problem. There are bounce and floating pin to consider. Try connecting a resistor from Vcc to that pin, and a switch from the pin to ground. Close the switch on power up and open it to set the pin.

Does the pin always read low? Or are there occasions when the pin reads high?
 
Top