Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

16F690 - XOR Toggling

Status
Not open for further replies.

jamo13

New Member
Hi there

I realise there is more than this post on toggling with an XOR operation on the 16F690 but I had read these, tried for days and need help...

I'm using MPLAB-X with a PicKit 2 and it's demoboard [04-01831 Rev2] to turn on and off the left LED (DS1) which is connected to the RC0 pin.

Flashing the LED works well if I move 0 or 1 to the RC0, it just doesn't with the XOR.

I've read the datasheet and cannot figure out why it's not working?

Can anyone help?

I'm guessing it's my setup somewhere but it could be anything...


My code is as follows:

Code:
            ORG         0x00           ;This is where we come on power up and reset

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

STATUS      equ         0x03            ;Address of STATUS register 
TRISC       equ         0x87            ;Address of TRISC register (bank 1)
ANSEL       equ         0x11E           ;Address of Anaglogue setup (bank 2)
ANSELH      equ         0x11F           ;Address of Anaglogue setup (bank 2)
PORTC       equ         0x07            ;Address of Port C (bank 0 or 3)
RP0         equ         0x05            ;Bit location of RP0
RP1         equ         0x06            ;and RP1.
COUNT       equ         0x20            ;Counter for our delay loop
TIME        equ         0xff            ;Variable for the delay loop

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

            bcf         STATUS,5        ;Ensure Bank 0 with
            bcf         STATUS,6        ;RP0 & RP1 = 0
            clrf        PORTC             ;Make all PortC outputs low

            bsf         STATUS,5        ;Switch to Bank 1 with
            bcf         STATUS,6        ;RP0 & RP1 = 1 (bit 5 set)
            clrf        TRISC               ;Set all of PortC to outputs

            bcf         STATUS,5        ;Switch to Bank 2 with
            bsf         STATUS,6        ;RP0 & RP1 = 2 (bit 6 set)
            clrf        ANSEL              ;Ensure PortC is digital
            clrf        ANSELH            ;Ensure PortC is digital

            bcf         STATUS,5        ;Switch to Bank 0 again
            bcf         STATUS,6        ;RP0 & RP1 = 1 (bit 5 set)

;****Setting for toggling the RC0 (LED)*************

            movlw       0x01            ;Set up our w register with 01h

;****Toggle the LED ***************************

start       xorwf       PORTC,1         ;toggle RC0, store the result in PortC

;****Add a delay*******************************

            call        delay

;****Now clear the WDT & go back to the start of the program****

            clrwdt                        ;This simply resets the WDT
            goto        start           ;go back to Start and turn LED on again

;****Subroutine to give a delay between bit movements******

delay
            movlw       TIME            ; Get the delay time,
            movwf       COUNT        ; and put it into a variable
loop1
            decfsz      COUNT,1         ;Decrement 1 from the delay time until it
            goto        loop1               ;reaches zero.

            return

;****End of subroutine**************

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

            end             ;Needed by some compilers, and also
                               ;just in case we miss the goto instruction.
 
Change this;
Code:
            movlw       0x01            ;Set up our w register with 01h
;****Toggle the LED ***************************
start       xorwf       PORTC,1         ;toggle RC0, store the result in PortC
[\code]

to this;
[CODE]
start       movlw       0x01            ;Set up our w register with 01h
;****Toggle the LED ***************************
            xorwf       PORTC,1         ;toggle RC0, store the result in PortC
[\CODE]

As you need to load the value into W every time before you do the XORWF. :)

(edit) Weird! The forum CODE tags seem to be broken?
 
Last edited:
Hey, thanks for the ideas. Unfortunately neither changed the outcome (LED1 is always on).

I have changed the code to the following:

Code:
;****Setting for toggling the RC0 (LED)*************

start       movlw       0x01            ;Set up our w register with 01h

;****Toggle the LED ***************************

            xorwf       PORTC,0         ;toggle RC0, store the result in PortC
            movwf       PORTC

But I'm not sure how to implement a shadow register?
 
Your delay is very short, so the LED will be toggling on/off at a very high frequency. To the human eye the LED will look "always on" as it is flashing much too fast to see.

Also your last code is wrong, by adding the MOVWF PORTC at the end you keep forcing the LED on. Remove that last line.

To toggle the LED you just need to XOR W (which is 0x01) with PORTC, and leave the result in PORTC. This has no chance of read-modify-write error (so you don't need a shadow register).

The correct operation is;
XORWF PORTC,f
 
Sorry mate, you're right it must have been late when I posted that.

Believe me when I say I have messed with the delay time to see if it was too fast or too slow and I'm fairly sure its not the delay period.

I think I originally had what you described. I.e I had the portC XORing with 0x01 which should have toggled the LED.

I've tried everything I can think of, and I'm certain it's something to do with port setup somehow....
 
It would be a good idea to get rid of this stuff;
Code:
;*****Set up the Constants********************
 
STATUS      equ         0x03            ;Address of STATUS register 
TRISC       equ         0x87            ;Address of TRISC register (bank 1)
ANSEL       equ         0x11E           ;Address of Anaglogue setup (bank 2)
ANSELH      equ         0x11F           ;Address of Anaglogue setup (bank 2)
PORTC       equ         0x07            ;Address of Port C (bank 0 or 3)
RP0         equ         0x05            ;Bit location of RP0
RP1         equ         0x06            ;and RP1.
COUNT       equ         0x20            ;Counter for our delay loop
TIME        equ         0xff            ;Variable for the delay loop

And just tell MPLAB which PIC you are using. You should never manually define SFRs (special function registers) as that is MPLABs job, and it will always get it right. :)

Also, your delay code with a max delay value of time=255 will only delay about 760 cycles. With a 4MHz xtal (1 mil cycles sec) your LED "flash" will be at 1 mil / (2* 760) or roughly 660Hz! Way too fast for you to see, it will just appear to be on all the time. And with a faster xtal than 4MHz it will be worse still.

There are some online code generators that will generate ASM code for different delay lengths, so you could use one of those to give you code for a 500mS delay. Also it is well worth becoming familiar with the timer0, as you can set that to rollover at a lowish frequency, then just count rollovers to give longish delays.

Once you are more familar with the PIC and timers there are many code examples here that will generate exact seconds and other exact periods from any xtal value;
https://www.romanblack.com/one_sec.htm
 
Oh man, I'm so happy. I took your advice about the delay time and after doing the math (which was good) I spotted an error in the code.

I had set up two loops for a delay that were adding (255 + 255 = 510) rather than multiplying (255 * 255 = 65025) so when I thought my delay was what I had calculated, it was in reality much much smaller.

After fixing the looping issue it flashed as per the calculations. Thanks for the advice.
 
Congrats! It can be daunting at first when even simple things like flashing a LED have problems. You should be proud that you have worked through it and things will only get easier and easier from now on.

I still urge you to get familiar with the timers, start with TMR0.

You said in your code that you now use 2 loops of 255 counts to get a delay of 65025 etc counts?

Using TMR0 you can do this with 4 instructions and no ram variables needed.
Code:
    MOVLW 0b00000111        ; set TMR0 to 256:1 prescaler
    MOVWF OPTION_REG        ; (this is done once near start of code)

    ; this code makes the delay of roughly 256*256 (65536 ticks) 
    CLRF TMR0               ; TMR0 will now count from 0-256
    BCF INTCON,T0IF         ; clear TMR0 overflow indicator flag
delay_x
    BTFSS INTCON,T0IF       ; wait until TMR0 overflows!
    GOTO delay_x            ;

I hope that makes sense. It can also be a good idea to heavily comment your code when you are doing early projects, so later on you can see exactly what the code was meant to do and what you were thinking. :)
 
Last edited:
Thanks. It's funny I've actually been working on just that.

I have the TMR0 working just as your code above, now I'm attempting the use an interrupt so that the chip can process other things in the mean time.
It's a bit of a WIP still but I'm getting there much faster with the tips.

The ultimate goal is to have designed a motion control circuit for a small robot that uses steppers.

Thanks again
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top