16F84A Beginners questions

Do you have a question? Post it now! No Registration Necessary

Threaded View


I'm trying to learn some basic embedded programming and I thought I would
start out with writing a few little programs for gold smart cards.

I've started out using MPLAB IDE and running my code in the simulator.
I've written a little program that writes a sequence to the file registers
0x0020 to 0x004F. The program works, sometimes. After resetting the
processor and clearing the memory the program will occasionally fail.
Rebuilding, adding a nop, deleting a blank line all seem to make it work
again, mostly.

The first three lines are:

MOVLW 0x010

I've set a break point after this and WREG is showing 0x006 and FSR is

I'm sure its something simple and I have no idea what it could be, can any
one suggest where I should be looking or any tests I can use to try to get
more info?


-- Michael Heydon

Re: 16F84A Beginners questions

Quoted text here. Click to load it
Why do you clear W if you are going to load 0x010 into it in the next
Quoted text here. Click to load it
You are doing this because you are going to use FSR to address the
file registers that you want to write the sequence to? If so, why do
you put 0x010 in it if you want to write to file regs 0x20 to 0x4f ??
How about you show us a bit more...
Quoted text here. Click to load it
What do you see if you step through it one instruction at a time?

Andy Wood

Re: 16F84A Beginners questions

Quoted text here. Click to load it
That is just me trying to figure out why it wasn't working. I have now
removed this instruction.

Quoted text here. Click to load it
Sorry typo, I'm writing to registers 0x10 to 0x4f

Quoted text here. Click to load it
Actually, thats a bit wierd, I reset the processor, clear the memory. WREG
becomes 0, on the first instruction WREG becomes FF, each step WREG
is decremented by 1. The actual instructions seem to be ignored, FSR
doesn't change.

Re: 16F84A Beginners questions

Quoted text here. Click to load it

<G> Right, I figured out what you're doing.  You're "clearing memory", all
of it, including the program memory.  When you do that memory appears to
contain ADDLW  0xFF (that is what a truly blank chip will execute).  You
can't clear all, you can only clear GPRs.  Make sure you view "Program
Memory" and you can see that you wiped your code away when you "cleared
memory".  ;-)  Click on Make again to reload the simulators memory with your
program.  This is why I don't use the simulator.  :-)

Re: 16F84A Beginners questions

Quoted text here. Click to load it

*slaps head* of course! I knew it would be something silly like that. That
explains why adding a nop or removing a blank line makes it work, the IDE
sees the file has changed and prompts me to rebuild.

Thanks alot :)

-- Michael Heydon

Re: 16F84A Beginners questions

Quoted text here. Click to load it

We're going to need to see more of your code.  Are you using interrupts?

Re: 16F84A Beginners questions

Quoted text here. Click to load it

I dont have anything setup to trigger interrupts but I'm also not
disabling them. I don't have any interrupt handling code either.

Below is the entire program:

list      p16%F84A
#include <p16F84A.inc>

ORG     0x000
goto    main


        movlw 0x010
        movwf FSR

        movlw 0x030
        movwf 0x00f

        movlw 0x000

                addlw 1
                movwf INDF
                incf FSR
                decfsz 0x00f,1
        goto loop


-- Michael Heydon

Re: 16F84A Beginners questions

Quoted text here. Click to load it

I just simulated it.  It was a pain because I haven't used the simulator in
years, so I had to learn how to use it again.  ;-)  Your code works fine,
except that it runs of the end.  Just because you have an end statement
doesn't mean the PIC will stop there.  The simulator will show you that if
you view the "Program Memory" and not just the code window.  The code window
is broken and makes it look like the program just stops at the end of the
loop, but it doesn't.  Outside of that, I don't know why you are having
trouble with it.

You did select the proper device in MPLAB right? (click on
"Configure->Select-device and make sure you have the 16F84A specified
there).  You should also specify ,F or ,W on your "incf FSR" statement.
Give your variables names, 0x0F is not very informative.  ;-)

Re: 16F84A Beginners questions

Quoted text here. Click to load it

I've just been reading about end vs loops/sleep in another thread. I'll
have to have a play with that.

Anthony Fremont actually figured out what I was doing wrong in the thread
above. I was clearing all memory, turns out that includes program memory.

Quoted text here. Click to load it
I'm fairly new at this, and haven't gotten that far yet. Its on my TODO

Thanks for your help

-- Michael Heydon

Re: 16F84A Beginners questions

Quoted text here. Click to load it

Copied your code and made a complete program of it:

#include <p16f84a.inc>
 MOVLW 0x010

Running it on MPLAB IDE v7.20 showed no problem at all. The simulator just
showed the expected changes. While animated, step by step or run. The latter
with a breakpoint on the nop of course. So your problem is outside the smal
part of code you provided. (As expected on my side.)

BTW. What's the use of clearing W just before writing 0x10 to it?

petrus bitbyter

Re: 16F84A Beginners questions

Quoted text here. Click to load it

Turns out it was a user problem rather than a code problem, I was messing
up the simulator.

Quoted text here. Click to load it

That was me trying to figure out why it wasn't working, it is gone now.

-- Michael Heydon

Re: 16F84A Beginners questions

Quoted text here. Click to load it

Don't depend on the simulator to much.

The more recent versions of mplab are good but old versions pre mplab 5/6
had all sorts of weirdness.

Few tips

1. Always intialise your variables.
Pic micro controller file registers are not initialised to any specific
value by
default. Always initialise your variables to zero to start with, this avoids
unexpected surprises.

2. Indent conditionally executing code after a skip instruction
Doing this makes conditionally executing instructions stand out especially

3. Let the assembler do the calculations for you.
Helps make your code more portable to other applications. Saves you having
work it out and potentially making a mistake.

4. Use microchip include files without modification

5. Keep your code as simple as possible
Makes it a lot easier to debug.

6. Develop your application in terms of functional blocks and interfaces
Instead of one large application, develop it as a series of steps or blocks.
block should be simulated and tested on hardware before proceeding.

7. Establish a plan to test and confirm your code is correct
Test your code each step of the way and do not move on to the next step
until you
are 100% satisfied with the performance of the code up to that point.

8. Avoid changing register banks unless it is absolutely necessary
Ideally, an application should be designed so that all of the bank 1
registers and
hardware are initialised after reset and then execute in bank 0 for the rest
of the

9. Don't allow code to go over page boundaries
If your code is larger than 2048 instructions place subroutines in the upper
Code that is allowed to drift over page boundaries can have problems with
correct PCLATH register contents.
Beware when using large tables in your programs place them at the beginning
if necessary.

10. Use the __Config for fuse settings
Look in the definition (include or *.inc) file for the fuse settings for the
pic you
are using. Make sure to enable the fuse options you need and disable the
Makes it easy to see what the configuration fuses you are using and stops
tutors asking difficult questions when you are demonstrating your
Usually using hex values for config fuses means you don't understand them
just copied it from someone else or from the net.
If you are using the watchdog timer, keep it disabled until you have
debugging all the other functions.

11. Simulate as much of your application as possible
The time used to develop a stimulus file and single step through it will be
several times over in the time needed to debug the application if simulation
not been carried out.

12. Keep subroutine calling to a minimum
Pics have a limited stack and are not designed for recursive functions in
applications. This means minimize calling subroutines from inside other
subroutines. For both 16f628 and 16f877 make sure, the maximum calling depth
is less than eight.
NB interrupt handlers use the same stack. To work out maximum calling depth,
add the maximum depth of the interrupt handler execution with the maximum
depth of the main part of the program.

13. Double check the part number on the pic you have.
Some pics have two versions - original and 'A' version.
Differences in hardware can be nil or quite a lot. Check the datasheet.
If the pic your trying to use with your Digital Systems kit is an 'A'
version you
Will need to download version 1.95 or higher of winpicprog
(Look in the winpicprog forum under announcements www.winpicprog.co.uk)
Taken from "A bakers dozen rules to help avoid application software
pg 520 Programming and Customizing PICmicro Microcontrollers
by Myke Predko ISBN 0-07-136172-3 2002.
Alex Gibson version 2.1 01.02.2004

Re: 16F84A Beginners questions

Quoted text here. Click to load it

Best thing to start with is flash a led or two.
Then build up from there.

Haven't use an 16f84 or 84A for years.

A good habit to get into is putting the config fuse line into the asm file,
so you can always find it easily.

;  Program works for both 16F628 and 16F877  just change processor
#define Processor   16F877 ; or 16F628

  if Processor == 16F628
     list p16%f628     ; set processor type
     #include <P16f628.INC>
     __config _CP_OFF & _PWRTE_ON & _HS_OSC & _WDT_OFF & _BODEN_ON &
  else ;Must be the 16F877
     LIST      P16%F877, F=INHX8M
     #include <P16F877.inc>
     ; code protect off  debug off   program memory write protection off
     ; low voltage programming off brown out detection on , watch dog timer
     ; High speed(>4MHz) xtal program write on


    org     0x00
    call    Setup
    goto    Main
    org     0x04
    goto    IntService
    goto    Stop

; Interrupt Service Routine


; Setup
    bsf     STATUS,RP0 ;
    bcf     STATUS, RP1 ; Bank 1 selected
    movlw   H'F0'
    movwf   TRISB       ; High Nibble input, low outputs
    bcf     STATUS, RP0 ; Bank 0 selected
    clrf    PORTB       ; All outputs of Port B reset
; Main


    btfss   PORTB,4
    goto    LedOff
    bsf     PORTB,0
    goto    MainLoop
    bcf     PORTB,0
    goto    MainLoop


Another simple one but using a delay.

     list p16%f877                 ; list directive to define processor
     #include <p16f877.inc>        ; processor specific variable definitions
     ; configuration fuse settings
     ;    code protect off  watch dog timer off, brown out enable , program
write on ,   high speed oscillator on
     ;  write enable on , low voltage programming off and code protect data

DT0       EQU       0X20  ; name location 0x20 to DT0
DT1       EQU       0x21  ; name location 0x21 to DT1
DT2       EQU       0x22  ; name location 0x22 to DT2

   ORG       0x0000  ; program start address

MAIN                ; Main loop
   banksel   0                  ; bit set flag RP0 in status
register ->select bank 0
          clrf      TRISB
          clrf      PORTB
          banksel   0                   ; bit clear flag -> select bank 0
          ;MOVLW  .7
   ;MOVWF  ADCON1    ;PortA and PortE all digital I/O

NOW       CALL      DELAY  ; call subroutine delay
   BSF       PORTB,0  ; bit set flag porta location 0 to 1
   CALL      DELAY  ; call subroutine delay
   BCF       PORTB,0  ; bit clear flag porta location 0 to 0
   GOTO      NOW   ; goto label NOW

;********* DELAY LOOP ********

DELAY         ; subroutine delay
   MOVLW     0X05  ; move literal 0x05 to W register ->puts 5 in the w reg
   MOVWF     DT0   ; move contents of w reg to memory location DT0
   CLRF      DT1   ;clear flag DT1
   CLRF      DT2   ;clear flag DT2 -> set it to 0
   DECFSZ    DT2   ; decrement DT2 skip next if DT2 is zero
          GOTO      SD1   ; GOTO label SD1

          DECFSZ    DT1   ; decrement DT1 skip next if DT10 is zero
          GOTO      SD2   ; GOTO label SD2

   DECFSZ    DT0   ; decrement DT0 skip next if DT0 is zero
   GOTO      SDEL  ; GOTO label SDEL
          RETURN    ; return to calling location

  END       ; END of assembly file

Site Timeline