Maker Pro
Maker Pro

16F84A Beginners questions

M

Mike

Jan 1, 1970
0
Hi,

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:

CLRW
MOVLW 0x010
MOVWF FSR

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

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?

Thanks

-- Michael Heydon
 
A

Andy Wood

Jan 1, 1970
0
Mike said:
Hi,

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:

CLRW
Why do you clear W if you are going to load 0x010 into it in the next
instruction?
MOVLW 0x010
MOVWF FSR
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...
I've set a break point after this and WREG is showing 0x006 and FSR is
0x0013.
What do you see if you step through it one instruction at a time?


Andy Wood
[email protected]
 
M

Mike

Jan 1, 1970
0
Why do you clear W if you are going to load 0x010 into it in the next
instruction?
That is just me trying to figure out why it wasn't working. I have now
removed this 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...
Sorry typo, I'm writing to registers 0x10 to 0x4f
What do you see if you step through it one instruction at a time?
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.
 
M

Mike

Jan 1, 1970
0
We're going to need to see more of your code. Are you using interrupts?

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

ORG 0x000
goto main

main

movlw 0x010
movwf FSR

movlw 0x030
movwf 0x00f

movlw 0x000

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

END

-- Michael Heydon
 
P

petrus bitbyter

Jan 1, 1970
0
Mike said:
Hi,

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:

CLRW
MOVLW 0x010
MOVWF FSR

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

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?

Thanks

-- Michael Heydon

Copied your code and made a complete program of it:

#include <p16f84a.inc>
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
 
M

Mike

Jan 1, 1970
0
<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. :)

*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
 
M

Mike

Jan 1, 1970
0
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.

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.
Give your variables names, 0x0F is not very informative. ;-)
I'm fairly new at this, and haven't gotten that far yet. Its on my TODO
list.

Thanks for your help

-- Michael Heydon
 
M

Mike

Jan 1, 1970
0
So your problem is outside the smal
part of code you provided. (As expected on my side.)

Turns out it was a user problem rather than a code problem, I was messing
up the simulator.
BTW. What's the use of clearing W just before writing 0x10 to it?

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

-- Michael Heydon
 
A

Alex Gibson

Jan 1, 1970
0
Mike said:
Hi,

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:

CLRW
MOVLW 0x010
MOVWF FSR

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

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?

Thanks

-- Michael Heydon

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 <P16f628.INC>
__config _CP_OFF & _PWRTE_ON & _HS_OSC & _WDT_OFF & _BODEN_ON &
_LVP_OFF
else ;Must be the 16F877
LIST P=16F877, 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
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
;--------------------------------------------------------------------------------------------------------------------------

Main

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


end

Another simple one but using a delay.

;--------------------------------------------------------------------------
list p=16f877 ; 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
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
 
A

Alex Gibson

Jan 1, 1970
0
Mike said:
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

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

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

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

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

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

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

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