PIC16F684 Programming in Assembly

Discussion in 'Programmer's Corner' started by Tomahawk640, Feb 20, 2009.

  1. Tomahawk640

    Thread Starter Member

    Feb 20, 2009
    20
    0
    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
    ...
     
  2. bertus

    Administrator

    Apr 5, 2008
    15,649
    2,348
  3. Tomahawk640

    Thread Starter Member

    Feb 20, 2009
    20
    0
    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
    ...
     
  4. Tomahawk640

    Thread Starter Member

    Feb 20, 2009
    20
    0
    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
     
  5. n9352527

    AAC Fanatic!

    Oct 14, 2005
    1,198
    4
    I can't see anything wrong with the loop. Where do you declare the INNER register?
     
  6. Tomahawk640

    Thread Starter Member

    Feb 20, 2009
    20
    0
    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
     
  7. Tomahawk640

    Thread Starter Member

    Feb 20, 2009
    20
    0
    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
     
  8. n9352527

    AAC Fanatic!

    Oct 14, 2005
    1,198
    4
    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.
     
  9. Tomahawk640

    Thread Starter Member

    Feb 20, 2009
    20
    0
    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!
     
  10. n9352527

    AAC Fanatic!

    Oct 14, 2005
    1,198
    4
    And add another dt entry. It has to be 4 entries for i value from 0 to 3.
     
  11. Tomahawk640

    Thread Starter Member

    Feb 20, 2009
    20
    0
    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.
     
  12. Tomahawk640

    Thread Starter Member

    Feb 20, 2009
    20
    0
    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
     
  13. n9352527

    AAC Fanatic!

    Oct 14, 2005
    1,198
    4
    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.
     
  14. n9352527

    AAC Fanatic!

    Oct 14, 2005
    1,198
    4
    double post
     
  15. Tomahawk640

    Thread Starter Member

    Feb 20, 2009
    20
    0
  16. n9352527

    AAC Fanatic!

    Oct 14, 2005
    1,198
    4
    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.
     
  17. Tomahawk640

    Thread Starter Member

    Feb 20, 2009
    20
    0
    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
     
  18. n9352527

    AAC Fanatic!

    Oct 14, 2005
    1,198
    4
    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.
     
  19. Tomahawk640

    Thread Starter Member

    Feb 20, 2009
    20
    0
    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.
     
  20. n9352527

    AAC Fanatic!

    Oct 14, 2005
    1,198
    4
    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?
     
Loading...