• 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.

Assembly Knight Rider Program

Status
Not open for further replies.

Cantafford

Member
Hello,

I have 8 leds connected to PORTB of PIC16f870 and I'm trying to make them turn on and off in a knight rider fashion(light up one by one from left to right then one by one from right to left). I'm using RLF and RRF instructions.
I wrote this program:

Code:
#include "p16F870.inc"

; CONFIG
; __config 0xFF3A
 __CONFIG _FOSC_HS & _WDTE_OFF & _PWRTE_OFF & _CP_OFF & _BOREN_OFF & _LVP_OFF & _CPD_OFF & _WRT_ALL

cblock 0x20
 d1
 d2
 d3
 ledctr
 endc


RES_VECT  CODE    0x0000            ; processor reset vector
    GOTO    MAIN                  ; go to beginning of program

; TODO ADD INTERRUPTS HERE IF USED

MAIN_PROG CODE                      ; let linker place main program

MAIN

    BANKSEL STATUS
    bsf STATUS, C

    BANKSEL TRISB
    movlw b'00000000'
    movwf TRISB
   
    BANKSEL PORTB
    clrf PORTB
    rlf PORTB
   
    LOOP
   
     movlw 0x07
     movwf ledctr
     
    _RotatePortLeft
      rlf PORTB
      call _delay_1s
      decfsz ledctr
      goto _RotatePortLeft
     
     movlw 0x07
     movwf ledctr
     
     _RotatePortRight
      rrf PORTB
      call _delay_1s
      decfsz ledctr
      goto _RotatePortRight
     
    GOTO LOOP
   
   
     _delay_1s
     movlw h'D0'
     movwf d1
     _actualdelay
      decfsz d1
      goto _actualdelay
      return
   
    END
All the LEDs stay off...

I noticed that if I clear the PORTB register then I do rlf PORTB the first LED lights up. But then if I do rlf again all the LEDs are off. Perhaps I do not understand the RRF instruction properly. Shouldn't the second LED light up when I do that?
 

Cantafford

Member
I'm using a 20Mhz crystal oscillator.
I have used microchip's delay calculator to get a delay of 1 second:
http://www.piclist.com/tecHREF/piclist/codegen/delay.htm

As seen in the code my configuration bits are like this:
Code:
; CONFIG
; __config 0x3F39
 __CONFIG _FOSC_XT & _WDTE_OFF & _PWRTE_OFF & _CP_OFF & _BOREN_OFF & _LVP_OFF & _CPD_OFF & _WRT_ALL
I have selected crystal oscillator.

This is the final code(with the included delay calculated with that calculator):
Code:
#include "p16F870.inc"

; CONFIG
; __config 0x3F39
 __CONFIG _FOSC_XT & _WDTE_OFF & _PWRTE_OFF & _CP_OFF & _BOREN_OFF & _LVP_OFF & _CPD_OFF & _WRT_ALL

cblock 0x20
 d1
 d2
 d3
 ledctr
 endc


RES_VECT  CODE    0x0000            ; processor reset vector
    GOTO    MAIN                  ; go to beginning of program

; TODO ADD INTERRUPTS HERE IF USED

MAIN_PROG CODE                      ; let linker place main program

MAIN

    BANKSEL STATUS
    bsf STATUS, C

    BANKSEL TRISB
    movlw b'00000000'
    movwf TRISB
   
    BANKSEL PORTB
    clrf PORTB
    rlf PORTB
   
    LOOP
   
     movlw 0x07
     movwf ledctr
     
    _RotatePortLeft
      rlf PORTB
      call _delay_1s
      decfsz ledctr
      goto _RotatePortLeft
     
     movlw 0x07
     movwf ledctr
     
     _RotatePortRight
      rrf PORTB
      call _delay_1s
      decfsz ledctr
      goto _RotatePortRight
     
    GOTO LOOP
   
_delay_1s
            ;4999993 cycles
    movlw    0x2C
    movwf    d1
    movlw    0xE7
    movwf    d2
    movlw    0x0B
    movwf    d3
_delay_1s_0
    decfsz    d1, f
    goto    $+2
    decfsz    d2, f
    goto    $+2
    decfsz    d3, f
    goto    _delay_1s_0

            ;3 cycles
    goto    $+1
    nop

            ;4 cycles (including call)
    return
     
   
    END
Here is how I interfaced everything in proteus:


My LEDs won't light up at all :(
 

Cantafford

Member
I noticed something weird. If I write a delay and blink one LED with it I may get it to blink every second. But If I try blinking more LEDs(once one turns off the next one will light up) they are going very fast(they are not blinking every 1 second as the one led would if it was only it)
 

Cantafford

Member
I have tied the MCLR to 5v and I'm using that code which I provided. Still nothing :(. I guess I will try on my laptop see if it works there.
 

Cantafford

Member
Tried on my latpop as well still nothing :(. Think I'm missing something really simple about setting the oscillator.
 

MrDEB

Well-Known Member
HOLY COW!! now I see how using SWORDFISH is so much easier and shorter.
just designate ports then toggle in sequence.
Just a guess I think this Knight Rider routine could be done in 10 lines or less?? But then I am not a great code writer.
 
Some of your problems:

The XT oscillator mode is only for crystals up to 4MHz. For 20MHz you should use the HS oscillator mode. Also, your 33pF capacitors are a bit high for 20MHz; typical is 18-22pF.

You need to turn off debug in your config word. You've left it on.

It's typical to enable the power up timer. You have it off.

I've never seen this: "RES_VECT CODE 0x0000"
If you're compiling with MPASM you should be using "ORG 0x0000".

Nigel pointed out that the syntax for your RLF and RRF instructions is wrong. You haven't corrected them.
 
Last edited:

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
The XT oscillator mode is only for crystals up to 4MHz. For 20MHz you should use the HS oscillator mode. Also, your 33pF capacitors are a bit high for 20MHz; typical is 18-22pF.
ISIS does not model the OSC.... So forget that...
Nigel pointed out that the syntax for your RLF and RRF instructions is wrong. You haven't corrected them.
rrf and rlf default to register so forget that...
I've never seen this: "RES_VECT CODE 0x0000"
If you're compiling with MPASM you should be using "ORG 0x0000".
This is relocatable code..
I also think the issue is you have compiled for re-locatable code.... I have compiled with absolute code..
 

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
HOLY COW!! now I see how using SWORDFISH is so much easier and shorter.
just designate ports then toggle in sequence.
Just a guess I think this Knight Rider routine could be done in 10 lines or less?? But then I am not a great code writer.
If I wrote this in basic, then compiled it, then showed you the assembled version, you would understand..
 

Cantafford

Member
Ok. I'm almost there. I fixed the delay thingy. Now the delay works fine. I can calculate it properly now. I think it had something to do with the debugging session beiing on as upand_at_them said. I'm using pickit 3 now instead of simulator and it works fine(the delay calculation).

However the LEDs still do not light up. I think I'm not understanding how RLF command works. To my understanding:
rlf means rotate (or shift) the data stored in whatever register or PORT that we say through carry and store the answer back in our register or PORT or store the answer in our w (working) register. So in our case we are shifting all the data in PORTB one space to the left, the left most bit will be shifted into the carry flag of our status register and whatever was in the carry flag will be shifted into the right most bit of PORTB. Or something like that. Still I don't understand why the tutorial I watched works and mine doesn't.

So I do not understand why we are setting the carry bit at the beginning of the program(I followed a tutorial to write that code). Shouldn't we clear the carry bit (bcf STATUS, c) at the beginning of the code instead of setting it so we do not have 2 LEDs light up at the same time?

I simplified the code in this manner. I'm trying to rotate the leds to the left. If I'll manage to do this then it will be a simple problem of rrf'ing them back:

Code:
#include "p16F870.inc"

; CONFIG
; __config 0xFF3A
 __CONFIG _FOSC_HS & _WDTE_OFF & _PWRTE_OFF & _CP_OFF & _BOREN_OFF & _LVP_OFF & _CPD_OFF & _WRT_ALL

 cblock 0x20
 d1
 d2
 d3
 ledctr
 endc

RES_VECT  CODE    0x0000            ; processor reset vector
    GOTO    MAIN                   ; go to beginning of program

; TODO ADD INTERRUPTS HERE IF USED

MAIN_PROG CODE                      ; let linker place main program

MAIN
   
   BANKSEL STATUS
   bsf STATUS, C

   BANKSEL TRISB
   movlw b'00000000'
   movwf TRISB
   
   BANKSEL PORTB
   movlw b'00000001'
   movwf PORTB
   
   loop
    rlf PORTB
    call _delay_1s
   
    GOTO loop                         ; loop forever
   
_delay_1s
            ;4999993 cycles
    movlw    0x2C
    movwf    d1
    movlw    0xE7
    movwf    d2
    movlw    0x0B
    movwf    d3
_delay_1s_0
    decfsz    d1, f
    goto    $+2
    decfsz    d2, f
    goto    $+2
    decfsz    d3, f
    goto    _delay_1s_0

            ;3 cycles
    goto    $+1
    nop

            ;4 cycles (including call)
    return

    END
 

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
As asked by upand_at_them... Why are you using relocatable code??

Both sets of code works for me... Your first ISIS screenshot shows 14 warnings.... Can you open the warning box and do a screen shot for me..
 

Cantafford

Member
As asked by upand_at_them... Why are you using relocatable code??

Both sets of code works for me... Your first ISIS screenshot shows 14 warnings.... Can you open the warning box and do a screen shot for me..
I'm not on my PC right now I'm somewhere else. I recreated the schematic here and I have no warnings in proteus. I will take that screenshot when I get home and post it here. But I think those warnings are gone. I think they were there because I used goto instead of call for some label that had return at the end.

I do not knowwhat relocable code is. I will do some research about that now. I just followed a tutorial to set up the environment.
Can you please tell me how do i switch from that to absolute code?
 

Cantafford

Member
I have read about relocatable code vs absolute code. I think I may have an ideea which is what now.
I have re-written my code as this. Is this(the way the code is now) absolute code?

Code:
    org 00h
  
    clrw ; clear status register
  
    bsf 03h, 5 ; select bank1
    bsf 03h, 6
    movlw b'00000000' ; PORTB made as output
    movwf 86h
  
    bcf 03h, 5 ; select bank0
    bsf 03h, 6
    clrf 06h ; clear PORTB
  
    bsf 03h, 0 ; clear carry flag
  
    loop
  
    rlf 06h, 1
    call _delay_1s
  
  
    goto loop
  
  
_delay_1s
            ;4999993 cycles
    bcf 03h, 5 ; select bank0
    bsf 03h, 6      
      
    movlw    0x2C
    movwf    20h
    movlw    0xE7
    movwf    21h
    movlw    0x0B
    movwf    22h
_delay_1s_0
    decfsz    20h, f
    goto    $+2
    decfsz    21h, f
    goto    $+2
    decfsz    22h, f
    goto    _delay_1s_0

            ;3 cycles
    goto    $+1
    nop

            ;4 cycles (including call)
    return
  
  
    END
The code behaves exactly like before btw.

Also please tell me if I understand the RLF instruction properly by looking at this example.

Say I have Reg = 1100 and carry bit C = 0
1st RLF => Reg = 1000, C=1
2nd RLF => Reg = 0001, C=1
3rd RLF => Reg = 0011, C=0
 
Last edited:

Cantafford

Member


I think I'm doing something wrong with the RLF command. But then again in the tutorial which I watched this worked fine and also you say my code works for you.
 

Cantafford

Member
I'll do a video... Showing your code ( slightly modified ) running...

I don't use MPLAB for assembly BTW.. I use ISIS inbuilt code generator... Far simpler..
Ok cool. I didn't know ISIS had a code generator. I'll probably start learning that in the next days or so. Wanna finish a tutorial playlist on assembly first.
 
Status
Not open for further replies.

Latest threads

EE World Online Articles

Loading
Top