16F84A Beginners questions


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:


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

Reply to
Loading thread data ...

Why do you clear W if you are going to load 0x010 into it in the next instruction?

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

What do you see if you step through it one instruction at a time?

Andy Wood snipped-for-privacy@trap.ozemail.com.au

Reply to
Andy Wood

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

Reply to
Anthony Fremont

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

Sorry typo, I'm writing to registers 0x10 to 0x4f

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.

Reply to

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 p=16F84A #include

ORG 0x000 goto main


movlw 0x010 movwf FSR

movlw 0x030 movwf 0x00f

movlw 0x000

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


-- Michael Heydon

Reply to

"Mike" schreef in bericht news: snipped-for-privacy@mheydon.net...

Copied your code and made a complete program of it:

#include CLRW MOVLW 0x010 MOVWF FSR nop end

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

Reply to
petrus bitbyter

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. ;-)

Reply to
Anthony Fremont

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. :-)

Reply to
Anthony Fremont

*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

Reply to

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.

I'm fairly new at this, and haven't gotten that far yet. Its on my TODO list.

Thanks for your help

-- Michael Heydon

Reply to

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

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

-- Michael Heydon

Reply to

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 definition ; ; ;------------------------------------------------------------------------------------------------------------------------ #define Processor 16F877 ; or 16F628 ;************************************************************

if Processor == 16F628 list p=16f628 ; set processor type #include __config _CP_OFF & _PWRTE_ON & _HS_OSC & _WDT_OFF & _BODEN_ON & _LVP_OFF else ;Must be the 16F877 LIST P=16F877, F=INHX8M #include ; code protect off debug off program memory write protection off ; low voltage programming off brown out detection on , watch dog timer off ; High speed(>4MHz) xtal program write on __config _CP_OFF & _DEBUG_OFF & _WRT_ENABLE_OFF & _LVP_OFF & _BODEN_ON & _WDT_OFF & _HS_OSC & _PWRTE_ON endif

;------------------------------------------------------------------------------------------------------------------------- ; VECTORS ;-------------------------------------------------------------------------------------------------------------------------

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

;------------------------------------------------------------------------------------------------------------------------- ; Interrupt Service Routine ;-------------------------------------------------------------------------------------------------------------------------

IntService retfie

;-------------------------------------------------------------------------------------------------------------------------- ; Setup ;-------------------------------------------------------------------------------------------------------------------------- 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 return ;-------------------------------------------------------------------------------------------------------------------------- ; Main ;--------------------------------------------------------------------------------------------------------------------------


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


Another simple one but using a delay.

;-------------------------------------------------------------------------- list p=16f877 ; list directive to define processor #include ; 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 off __CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _HS_OSC & _WRT_ENABLE_ON & _LVP_OFF & _DEBUG_OFF & _CPD_OFF

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 SDEL CLRF DT1 ;clear flag DT1 SD2 CLRF DT2 ;clear flag DT2 -> set it to 0 SD1 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

Reply to
Alex Gibson

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.

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

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

  1. Use microchip include files without modification

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

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

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

  1. 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 application.

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

  1. 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 rest. Makes it easy to see what the configuration fuses you are using and stops the tutors asking difficult questions when you are demonstrating your assignments. Usually using hex values for config fuses means you don't understand them and just copied it from someone else or from the net. If you are using the watchdog timer, keep it disabled until you have finished debugging all the other functions.

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

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

  2. 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
    formatting link
    Taken from "A bakers dozen rules to help avoid application software problems" pg 520 Programming and Customizing PICmicro Microcontrollers by Myke Predko ISBN 0-07-136172-3 2002. Alex Gibson version 2.1 01.02.2004
Reply to
Alex Gibson

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.