2
\$\begingroup\$

I am having trouble writing the code for flashing 6 LED's from PORTC on the PIC16F690 microcontroller. The LED's should flash like the lights on a runway.

With the code that I currently have the LED's are flashing in pairs and out of order.

Here is the code that I have currently:

list p=16F690
radix hex
include "P16F690.INC"
__config _WDT_OFF & _BOR_OFF & _PWRTE_ON & _INTOSCIO & _MCLRE_OFF
errorlevel -302
org 0

count equ 20        ;we're going to need two variables
count2 equ 21

call initial
call Blink

initial         ; initialize registers
    bsf STATUS, RP0
    movlw B'00000000'
    movwf TRISC
    bcf STATUS, RP0
    bsf STATUS, RP1
    clrf ANSEL
    clrf ANSELH
    bcf STATUS, RP1
    return

Blink            ;flip the LED on or off
    movlw B'00000001'
    rlf PORTC,F
    call Delay
    call Blink

Delay           ; waste time
    movlw 0xFF
    movwf count
    movwf count2
Delayloop
    decfsz count,f
    goto Delayloop
    decfsz count2,f
    goto Delayloop
    return

END
\$\endgroup\$
4
  • 1
    \$\begingroup\$ Please explain the exact behaviour you expect from the LEDs and the behaviour you are seeing now. \$\endgroup\$ Commented Jan 31, 2015 at 23:38
  • \$\begingroup\$ And what's that "movlw B'00000001'" doing right after Blink label? \$\endgroup\$ Commented Jan 31, 2015 at 23:42
  • \$\begingroup\$ Assuming all the rest is working you probably just need to move your (attempt of) initialization of PORTC right at the end of Initial sub. \$\endgroup\$ Commented Jan 31, 2015 at 23:43
  • \$\begingroup\$ At the moment the LED's are flashing in pairs through the pins in PORTC. However I would like the LED's to flash one by one, starting from RC0 to RC7. \$\endgroup\$
    – mrplow911
    Commented Jan 31, 2015 at 23:50

2 Answers 2

3
\$\begingroup\$

There are some problems with your code. I will point them out in order of which I think they may be the actual problem here. The ones at the bottom are just best-practice tips.


Initalise PORTC

You never initialise PORTC. The value of PORTC is unknown on a Power-On Reset. You will have to set it to some value in your initial routine:

movlw 0x01
movwf PORTC

This sets it to have one LED on, which is probably what you want. After that, with RLF, you will start rotating this bit to light other LEDs.

It may be that this is the idea behind these lines in blink:

movlw B'00000001'
rlf PORTC,F

However, the first line doesn't have any effect: it stores 0b00000001 in W, but W is never used. RLF takes register PORTC, rotates it and stores it back in PORTC - W isn't used. Also, you execute movlw B'00000001' every time you loop through blink. Even if this would correct, than the value of PORTC would never change because its reset all the time: you have to initialise the port in the initial routine, and change it in the blink routine.


Call and goto

Blink            ;flip the LED on or off
    movlw B'00000001'
    rlf PORTC,F
    call Delay
    call Blink

There are three different types of instructions to jump in code: GOTO, CALL and RETURN.

  • With GOTO, you simply jump in the code - it's as easy as that.

  • With CALL, you implement GOTO but also push the current program counter on the stack. This stack is a LIFO (last in first out) memory module in which in this case program locations can be stored.

  • With RETURN, you pop the last element from the stack and jump to that location. Essentially you jump to the instruction after the last executed CALL. This is what you use in the beginning where you call to Initial and then return and call to Blink.

The stack of this chip has eight levels, as described in section 2.3.2 of the datasheet. That means you can push a maximum of eight program locations on this stack. After that, the first index is overwritten (the stack is implemented as a circular buffer). This essentially means that it is then not possible to go back to the first CALL instruction, and that the controller will jump to another position. This may cause many unexplainable problems in more advanced software.

With the code I quoted above, you continuously call Blink, but there is no RETURN instruction. This means you will keep pushing stuff to the stack without popping it. The stack is being overwritten all the time. Since you don't use RETURN there, it doesn't matter so much. But in this situation you should really use GOTO instead of CALL:

Blink            ;flip the LED on or off
    movlw B'00000001'
    rlf PORTC,F
    call Delay
    goto Blink

Since GOTO doesn't use the stack, this is no problem.


Org 0 and 4

You've put lots of stuff on org 0. This is not good practice. As can be read in section 2.1 of the datasheet, this chip has an interrupt vector at org 4. This means that when an interrupt occurs, the program counter will jump to location 4, almost directly after 0. This is why we normally implement just a GOTO instruction on org 0. Something like this:

org 0
    goto start
org 4
    retfie            ; return from interrupt (alternatively you could have 
                      ; an interrupt handler here)

start: 
    ; your main code...

Explicit radices

As I already mentioned in the comments: in the top of your program you stated radix hex (and this is also the default). Because of this you can use EQU 20 to select register 0x20. However, it's much clearer when you just use EQU 0x20 or EQU 20h. When others read your code, they don't have to search for the radix specification or the assembler's default.


Delay generator

Maybe you know already about this, but you may find this interesting: http://www.piclist.com/techref/piclist/codegen/delay.htm

This is a delay generator which will generate a delay of a specific time for you. Your delay routine is perfect as far as I can see now, but if you're ever looking for something that calculates it exactly, here you go!

\$\endgroup\$
6
  • \$\begingroup\$ Did it also help? :) \$\endgroup\$
    – user17592
    Commented Feb 1, 2015 at 1:15
  • \$\begingroup\$ So far I am still trying to debug. As of now, no LED's are lighting up. But I do understand my code much better. \$\endgroup\$
    – mrplow911
    Commented Feb 1, 2015 at 1:19
  • \$\begingroup\$ I will look in the morning then to see if I can spot something else. \$\endgroup\$
    – user17592
    Commented Feb 1, 2015 at 1:20
  • \$\begingroup\$ Hey Camil great answer, about the "RLF rx,d" instruction he uses 'F' as 'd', while in the spec 'd' should either be 0 or 1. I'm guessing 'F' equals '1' in this case, but wouldn't be better to just put '1' there? \$\endgroup\$ Commented Feb 1, 2015 at 14:44
  • \$\begingroup\$ @VladimirCravero F indeed equals 1 in this cases, and instead of 0 one could use W. My opinion would be that F and W is more expressive and preferable (just as using BANKSEL instead of changing the RPx bits manually, and as using PORTA instead of 0x05) - but it's all opinions of course. Do you have a particular reason to prefer 1 over F? \$\endgroup\$
    – user17592
    Commented Feb 1, 2015 at 14:46
2
\$\begingroup\$

There is so much bad programming in your example that a proper answer would take too long. There is absolute mode, manual bank setting, fixed placement of variables, hidden but implied assumptions about the bank setting, and overflowing of the call stack. What a mess! Maybe I have time to wade thru all that tomorrow.

However, the code at BLINK is particularly confused and likely the source of the trouble. I can't even guess what you think loading 1 into W is supposed to accomplish. The lack of comments is downright irresponsible. In your description above the code, you talk of several LEDs, but the comment at BLINK talks only of flipping a single LED. The real bug seems to be that RLF doesn't work as you seem to think, although without comments one can't tell what you are thinking. Note that the rotate is performed on 9 bits, the register and the C bit.

This should be easy to debug. Load this into MPLAB and run it in the simulator. Then you can single step thru the program and see what every instruction is doing.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.