# PIC 16F877A

#### Michael Jensen

Joined Nov 5, 2004
11
Hey everyone, this is my first post here -- I'm extreemly new to electronics and microcontrollers, I built a simple PIC circuit that I think should work, I used a really cheap programmer (CAPR-PI) to program the chip, it has 5 pins that go to the circuit and it was able to program and verify the device so that's why I think my circuit is electronically ok, I've also done a multimeter tests on most of the connections for continuity... I think the actual problem is probably with the assembly program I wrote....

Acording to the data sheets supplied by microchip, bits 5 and 6 of the status register determine what bank is active. but the compiler complains even after setting/clearing certain bits that I'm doing things with address space that's outside of bank 0 -- even tho at this point it should be in bank 1 (trying to set TRISD, and TRISE to 0 for output)

I'm having some basic compiler issues I guess is what it comes down to, at first it wouldn't even produce a .hex file, now it produces one but it still complains about a few things:
Message[302] C:\PIC\PROJECTS\COUNTER\COUNTER.ASM 35 : Register in operand not in bank 0. Ensure that bank bits are correct.
Message[302] C:\PIC\PROJECTS\COUNTER\COUNTER.ASM 36 : Register in operand not in bank 0. Ensure that bank bits are correct.
Warning[205] C:\PIC\PROJECTS\COUNTER\COUNTER.ASM 70 : Found directive in column 1. (end)

my short asm code is as follows:
--------------------------------------------------------------------------------------------
;TEST Program for the PIC Microcontroller 16F877a
;Michael Jensen 2004

STATUS equ 03h

TRISA equ 85h
TRISB equ 86h
TRISC equ 87h
TRISD equ 88h
TRISE equ 89h

PORTA equ 05h
PORTB equ 06h
PORTC equ 07h
PORTD equ 08h
PORTE equ 09h

;BANK 0 VARIABLES
COUNT equ 20h ; General Purpose registers that are
COUNT2 equ 21h ; used by the Delay Subroutine

OUT1 equ 22h ; Will Go out PORT D
OUT2 equ 23h ; Will Go out PORT E

;TRISA & B are in BANK 1, PORTA & B are in BANK 0

bcf STATUS,6 ;As long as we leave STATUS <6> at 0
;We should be able to swap between
;Bank 0 and 1 by setting/clearing
;STATUS <5>
bsf STATUS,5 ;Move to bank 1 (set STATUS bit 5)

clrf TRISD ;PORTD = OUTPUT <LINE 35>
clrf TRISE ;PORTE = OUTPUT <LINE 36>

bcf STATUS,5 ;Move to bank 0 (clear STATUS bit 5)

clrf COUNT
clrf COUNT2

clrf OUT1
clrf OUT2

Start:
movlw OUT1
movwf PORTD

movlw OUT2
movwf PORTE

call Delay

incfsz OUT1, 1
goto Start

incf OUT2, 1
goto Start

Delay:
decfsz COUNT, 1
goto Delay
decfsz COUNT2, 1
goto Delay
return

end ; The compiler seems to like having this more than not...
--------------------------------------------------------------------------------------------

If anyone could help with with these compiler messages I would appreciate it...

Mike.

#### Perion

Joined Oct 12, 2004
43
Hi,

I dunno.... I originally wrote a couple stupid ideas (forgetting you had no includes to define RP0 and RP1...) so I really don't know. It looks like it should work to me. Looks like Maxx has an idea [below] though I really can't see why you should have to do any error suppresion. But, whatever works I guess.

Perion

#### Maxx

Joined Oct 30, 2004
43
Are you using MPLAB as the compiler by any chance?

It seems to be a general warning and as far as i am aware has no affect on compiling the program.

There is a line of code you can add to suppress the error and allow the program to fully compile. I might not have the correct syntax as i only tend to use MPLAB when i'm in work and all of my code is there at the moment but i think off memory you need to add the line below.

errorlevel -302

Despite being a pic programmer for a few years, I've never really questioned this, i just add it as a matter of course since i converted over to MPLAB

There should be no problem in your code using STATUS,5 the convention of RP0 will actually throw an error unless you are using an include file or you declare it as an EQU

I haven't really looked in detail at the rest of your code as yet because i think the error level line will help you sort it out, even if only as a temporary measure.

Goodluck

#### Michael Jensen

Joined Nov 5, 2004
11
Thanks for responding guys, This has really got me stumped...

I'm using MPLAB 6.50, it builds the hex file even with the errors, I used the error supression and no difference that I can tell other than it hides the messages, one thing that has me irked allready about mplab is that the errors/warnings show up as messages, and that the messages show up as errors/warnings
(as compared to what I'm used to -- It warns me about my end statement, and about finding "directives" etc, and gives messages about things that could be fatal to the program execution...)

I looked up some examples using includes instead of massive equs so I decided to include the correct header file for my program, the new code follows this post...

I've loaded my code into some 16f877 emulators, and setting bit 5 of status just doesn't seem like an ok thing to do -- nothing is letting me do it -- the thing loves dinking around in bank 0..., i even tried movlw FFh, movwf STATUS ;<SATUS=3> and in the emulators status holds 0F... ??? Why??? I'm going to be a bald 21 year old real quick at this rate... I'm going to take a closer look at the "fuses" (I think that's what they're called, the setup bits, maybe theirs a setup bit for something that says "STAY IN BANK 0 CONSTANTLY" and it's set to 1.... )

I also load my program into the emulator and it shows Bank 1 addresses 88h & 89h as being FF, and 07 respecitevly (TRISD & E, E only has 3 pins, so 07=00000111b)

New Code:
---------------------------------------------------------------------------------------------
;TEST Program for the PIC Microcontroller 16F877a
;Michael Jensen 2004

list p=16f877a
include <p16f877a.inc>

errorlevel -302

;THE INCLUDE MAKES THESE LINES NOT NECESSARY

;BANK 0 VARIABLES
COUNT equ 20h ; General Purpose registers that are
COUNT2 equ 21h ; used by the Delay Subroutine

OUT1 equ 22h ; Will Go out PORT D
OUT2 equ 23h ; Will Go out PORT E

org 0x0000
;TRISA & B are in BANK 1, PORTA & B are in BANK 0

bcf STATUS,RP1 ;As long as we leave STATUS <6> at 0
;We should be able to swap between
;Bank 0 and 1 by setting/clearing
;STATUS <5>

bsf STATUS,RP0 ;Move to bank 1 (set STATUS bit 5)

movlw 0h
movwf TRISD ;PORTD = OUTPUT
movwf TRISE ;PORTE = OUTPUT

bcf STATUS,RP0 ;Move to bank 0 (clear STATUS bit 5)

clrf COUNT
clrf COUNT2

clrf OUT1
clrf OUT2

Start:
movlw OUT1
movwf PORTD

movlw OUT2
movwf PORTE

call Delay

incfsz OUT1, 1
goto Start

incf OUT2, 1
goto Start

Delay:
decfsz COUNT, 1
goto Delay
decfsz COUNT2, 1
goto Delay
return

end ; The compiler seems to like this...

#### Michael Jensen

Joined Nov 5, 2004
11
Ugh, I can be a real smart idiot some times ;-)

The problem is with the hardware I built, I was using the emulators wrong, the program is MOSTLY fine, I did find a logic bug tho

movlw OUT1
movwf PORTD
movlw OUT2
movwf PORTE

was actually putting the literal values of OUT1/OUT2 into w, and not
the memory in locations 22,23 ...

I'll have to figure that out later -- back to square 1 :-(

Thanks for the help again guys, maybe when I'm more electronics mature I'll come and ask for help again ;-)

::Shakes head in shame, defeated by own handi-work (or lack-there-of) ::

#### Perion

Joined Oct 12, 2004
43
Good work!

BTW - movlw k copies a LITERAL value k to W - movf f,d copies the CONTENTS of f to d (d=0 - destination is W). That's why movlw OUT1 copies the address of OUT1 instead of it's contents since OUT1 is just an alias for address location 22h.

Perion
[also playing with PIC but should be sleeping :blink: ]

#### Maxx

Joined Oct 30, 2004
43
Originally posted by Michael Jensen@Nov 6 2004, 11:42 AM
I did find a logic bug tho

movlw OUT1
movwf PORTD
movlw OUT2
movwf PORTE

was actually putting the literal values of OUT1/OUT2 into w, and not
the memory in locations 22,23 ...

Ok lets put this one right for now and hopefully save you some of the headache

Rich (BB code):
movf        OUT1,w      ;Moves the contents of the file named OUT1 into W
movwf      PORTD        ;Moves the contents of w into PORTD
movf        OUT2,w      ;Moves the contents of the file named OUT2 into W
movwf      PORTE        ;Moves the contents of w into PORTE
Also can i recommend a couple of other things

Make the first line of your program code (after the ORG 0x000) a goto instruction pointing to another location (say ORG 0x010) to start your main code. The reason being it will reserve a small amount of space for the interrupt vector address at ORG 0x004 I'll give an example below of how i would usually set up a pic.

Rich (BB code):
ORG         0x000
goto         INIT_PIC      ;goto an initialisation routine to setup ports,and options etc.

ORG         0x004          ;This location is reserved for a future ISR if needed
goto         INTERRUPT

INTERRUPT                  ;Interrupt Label
;<---- An ISR can go in here if needed later
retfie                            ;A return from interrupt, handy if you enable
;interrupts by mistake when they are not needed.

ORG        0x010
INIT_PIC                      ;Initialise/setup port directions etc, etc.
clrf           PORTD          ;Make all port outputs logic 0
clrf           PORTE          ;Make all port outputs logic 0

bsf           STATUS,RP0  ;Select page 1
clrf           TRISD          ;Set the port direction to all pins as output
clrf           TRISE          ;Set the port direction to all pins as output
movlw      00h              ;<---- Choose your own options here
movwf      OPTION_REG  ;Sets up some options (see data sheet)
bcf           STATUS,RP0  ;Return back to page 0

End                                ;End directive
Above is a similar sort of setup that i usually use in most of my pic programs it is should work ok as is but you might want to add or remove bits as necescary.

Also i would take a closer look at your delay routine, i'm not sure how much of a delay you need but suspect that would execute pretty fast. It's quite common to make use of TMR0 and it's prescaler which is great for reliable delays.

One step at a time though eh, lol

Goodluck m8

Let us know how you get on

#### Maxx

Joined Oct 30, 2004
43
Yuck sorry about all the spacing messed up, it looked just fine on preveiw.

I'm sure you will sus it out.

#### Michael Jensen

Joined Nov 5, 2004
11
Thanks Maxx, I appreciate the help -- I suspected it was something as simple as removing an lw and adding an f (movlw - movf) And thanks for the interupt help, I agree that it is a good idea to handle them just in case I have them enabled by accident...
I will have to take a look at the options reg and see what mine has...

Last night I tried re-verifying the device, erasing it, and reprogramming it -- all operations failed, so my hack of a hardware project failed on me a little bit -- I ripped all the wiring out and I'm gonna start over, I think I learned a little bit from the mistakes I made, so I guess I'm moving in the right direction...

Thanks for the help guys, I'll let you know if I can get my bit counter to work... (or maybe sooner if I break something else!) ;-)

Mike

#### Maxx

Joined Oct 30, 2004
43
Mike is it essential that you use a 16F877A to learn with?

If you are intending to start over with the hardware it might be worth you looking into using a PIC 16F84 It's a much less complicated device and there are literally hundreds of applications already written for it out there.

Yes i know it's virtually obsolete these days often being replaced by other devices such as the 16F627/8 but the F84 with it's simplicity would be a great starting point.

You only need to change between 2 memory pages instead of 4 for example and there is much less built in hardware to have to set up and initialise. Such as no analogue inputs to contend with in the configuration etc. Obviously with it only being an 18 pin device you get a lot less output ports than you need for your program, but a great starting point to stick a couple of LED's and switches on 'till you get used to things.

If you get a program running well on the F84 you can then convert it over to something more powerfull later on by adding the extra configurations needed.

#### Michael Jensen

Joined Nov 5, 2004
11
Actually It's not essential, I could go with one of the lower 8 pin PICs (I don't have the # right now but I've seen the advertised for like under \$2 for non-bulk) I kind of did want to play with analogue input tho -- Actually I got on here to let you know I got the thing rewired, and I have no problem programming/erasing/verifying the device now -- I just wrote the old .hex file to it and read it back/verified it twice -- no probs -- That I think, is awesome -- the original setup I had was extreemly sloppy, so I'm a lot more pleased with this setup -- Still no blinking lights yet tho -- And yeah I could go with the simpler device I suppose, I just don't want to have to wait another 2 weeks for it to come in the mail; Sorry for the scatter brained post, it's 3 AM.... I'll keep you posted on my progress with this thing...

EDIT: Hey, a hypothetical question:
If I did get this working -- Do I _realllly_ need OUT1 & OUT2? could I just count on PORTD, and PORTE, (incfsz PORTD)?

#### Michael Jensen

Joined Nov 5, 2004
11
Still not blinking -- about the only thing I'm not sure about in this circuit is the crystal, Maybe I should just try the resistor capacitor thing...

Actually I was testing to see if the led's were plugged in backwards (for a second I thought they were but I don't think they are anymore) when I pluged them back in they lit up for a second and then once all the way in they stopped -- is 330 Ohms from each pin to each led too much? I'm still new to electronics but I figured if each pin is going to output 5v to a 2v led at .01 amps it should be 3/.01=300ohm...

What do you think? -- I wonder...

#### Michael Jensen

Joined Nov 5, 2004
11
It's alive!

It was that damn unreliable execuse for an oscilator, I replaced with about a 47k resistor and a small cap, it runs really slow tho -- without ANY delay it was pretty fast -- but not TOO fast ---- with a 40h instruction delay loop (not 256, or 65535, but count down once from 40h or 64d) it takes about 1 second per delay....

I'm guessing each time the cap fills up and discharges it goes forward once, so possibly a smaller resistor might make it go at a more comfy speed -- is there an easy forumla you can use to calculate speed given by the Resistor + Cap?

P.S. Thanks for all the help so far Maxx...

#### Maxx

Joined Oct 30, 2004
43
Ok i'll probably forget some of the questions you asked but i'll try to remember them in this post.

Firstly the resistor value on the LED's is fine and the Ohm's law formula you used is perfectly correct taking into acount the LED voltage drop. I usually use something in the region of 330 to 470 ohms. The pic can source and sink upto about 20 mA per output pin but personally i would stick with the 9 to 10 mA that you are using now.

Counting using the ports instead of out 1 and 2 etc is possible but under certain circumstances it can cause problems. I don't know the full details of the reasons but it's something to do with the PIC reading the output port before the increment or something similar. If there is an external influence like a voltage applied externally for some reason etc when it does the read it could read the wrong value back into the PIC. I'm sure just driving a few LED's you would have no major problems doing this.

RC oscilators, there will be a relationship with the chosen values but this only applies upto a certain point. There is limits on the accuracy and linearity for values outside a certain range. I don't know the formula off the top of my head and i'm not sure which way speed wise an increase or decrease of values has on the PIC. Usually with oscilators larger values slow things down and smaller values speed things up.

Personally i usually use ceramic resonators and not RC oscilators, However i'm fairly sure the F877 has its own built in oscilator that you might be able to take advantage of at some point. If you do use a crystal, externally remember to add a couple of capacitors between each pin and zero volts, usually about 22pF to 33pF and remember to set the configuration bits to XT mode.

As for other PICS such as the 8 pin range the 12F683 features analogue input and i think off the top of my head the 12F675 does too but don't quote me on that one. At the moment I've just received a few samples of the 12F683 which is fairly new out and very new to me but looks pretty impressive, for it's size.

Most of the info can be found in the data sheets and it might be worth you downloading a copy of the Midrange microcontroller handbook.

Not sure if i have covered everything you asked but i'll leave it at that for now, I'm glad you have had some success though, there will be no stopping you now

Oh and P.S. I'll know who to ask when i try to learn C++ won't i, lol

Goodluck m8, feel free to ask if i can help anymore

#### Michael Jensen

Joined Nov 5, 2004
11
I think next time I order another PIC I will go with a simpler one, And order a few ceramic resonators at different ranges, (I found out about these while I was trying to figure out how to hook up the OSC I got, they seem much simpler to use, and I wish that I would have bought some of these instead of what I got, a crystal oscilator -- not just a normal crystal like all the schematics I've seen use, at least that's my understanding)

And yeah like that mouse and the lion thing -- if you ever need help with anything that I can be of service in, let me know -- As far as forums go, I participate in a few but I'm off and on, so I could be hard to get a hold of this way -- you can always reach me at mtj419@yahoo.com

Thanks again,
Mike

#### Michael Jensen

Joined Nov 5, 2004
11
Hey, I built a small webpage to show it off to a few friends, if you're interested in looking at my sloppy wiring job (which is saddly a lot better than the previous one) you can check out this section of my webpage (not big on GFX or anything, but it's functional. I'm not extreemly artsy in this catagory...)

it's at:
http://www.geocities.com/mtj419/pic/counter.html

-- Mike

#### Perion

Joined Oct 12, 2004
43
Originally posted by Maxx@Nov 8 2004, 12:46 PM
Counting using the ports instead of out 1 and 2 etc is possible but under certain circumstances it can cause problems. I don't know the full details of the reasons but it's something to do with the PIC reading the output port before the increment or something similar. If there is an external influence like a voltage applied externally for some reason etc when it does the read it could read the wrong value back into the PIC. I'm sure just driving a few LED's you would have no major problems doing this.
Just out of curiosity... I'm guessing he could probably get away with using INCFSZ PORTD,1 to directly modify the port since all bits are configured as outputs, they're altered at a fairly low update frequency and little capacitance to deal with. But like you said - it's probably not such a hot idea.

The way I understand it, the problem is when using two (or more) consecutive write instructions to a port (like BSF, BCF, etc.), since they read-modify-then write, it's possible for the later write instruction to read in the results of the previous write instruction before it has actually had time settled into a well defined state.

The other problem seems to be when using at least one port bit bi-directionally with others configured as outputs. When re-configuring the bi-directional bit from an input into an output type, its output data latch is in an unknown state. If another bit of that port is written to before explicitly setting the state of the bi-directional one(s), since it reads in the whole port, performs the operation, then writes back the whole port's bit state, it can turn on or off the newly configured bit in a surprising way! Is that the way you understand the problem? Have you ever actually had any problems like this?

Perion

#### Michael Jensen

Joined Nov 5, 2004
11
Another Question; I was talking to an electronics teacher at my school, and he told me that instead of tying the leds to ground and powering them with the PIC, I should have tied them to power, and "sank" them with the PIC. (Put 1s out to turn them off, and 0s to turn them on, making the PIC end grounding the LEDs to turn them on) I belive he's right and this will work -- he said the reason for doing it backwards like that is because the processor should be able to sink current better than it can supply current -- but he wasn't sure if that problem had been fixed recently or not and thought that it might be just his gray hair talking -- any insights?

#### Maxx

Joined Oct 30, 2004
43
Originally posted by Perion@Nov 9 2004, 03:58 PM
The way I understand it, the problem is when using two (or more) consecutive write instructions to a port (like BSF, BCF, etc.), since they read-modify-then write, it's possible for the later write instruction to read in the results of the previous write instruction before it has actually had time settled into a well defined state.

The other problem seems to be when using at least one port bit bi-directionally with others configured as outputs. When re-configuring the bi-directional bit from an input into an output type, its output data latch is in an unknown state. If another bit of that port is written to before explicitly setting the state of the bi-directional one(s), since it reads in the whole port, performs the operation, then writes back the whole port's bit state, it can turn on or off the newly configured bit in a surprising way! Is that the way you understand the problem?

Yup thats pretty much the way i understand it or something along those lines anyway.

Sorry for the delay i haven't been online for ages, been mad busy.

#### Maxx

Joined Oct 30, 2004
43
Originally posted by Michael Jensen@Nov 12 2004, 10:30 PM
Another Question; I was talking to an electronics teacher at my school, and he told me that instead of tying the leds to ground and powering them with the PIC, I should have tied them to power, and "sank" them with the PIC.
You're ok to do either method with a PIC as long as you don't exceed about 20mA
I think off memory they can sink slightly more than they can source but personally i think it's best not to run things right up to the maximum limits.

Yes your teacher is right to some extent but PIC's are designed to be able to drive LED's directly in either the source or sink mode. So it makes for easier and more logical program design to use logic 1 to switch the LED on like you have done.