Continue to Site

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.

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

PIC16f877 Program Memory

Status
Not open for further replies.

Olshansk

New Member
I do not exactly understand how the program memory is set up in terms of paging.

Each page in the PIC16 can store 2048 instructions, and there are 4 such pages in total. I read that when a certain instruction being executed is past the 2048 line boundary, I need to set bits 3 and 4 of the PCLATH appropriately.

At the moment, the only thing I can think of is adding nop (skip/do nothing instructions) such that none of my subroutines contain code that lies in two pages. The only way I can currently determine whether an instruction (or subroutine) is on another page is by looking at the program memory in MPLAB (the IDE I'm using).

I was simply wondering if anyone could provide me with any more insight in this subject? Is there something I'm missing? Is there a conventional way of paging that I should be following?
 
For a start don't worry about it - you need to right a HUGE amount of code to get over the 2048 'limit'.

If you do get that big, then move subroutines to a higher page, and call them using the 'fcall' macro (which sets the paging bits for you). This is another reason for placing data tables etc. in a higher page of memory as well.

If you move to the enhanced 16F series (like the 16F1827 I'm using now) then it's less of a problem, as you have the BRA instruction which you can use like GOTO for jumps with in +/- 127 words which avoids the crossing 2K problem.
 
Thanks for the reply!

I'm working on a big program, so I just want to be prepared to know what to do in the case that I do end up crossing the 2k problem.

I found the macro below online, and logically it makes sense, but I was hoping you could confirm it is the right one, or if there are any issues with it.

Code:
fcall		macro subroutine_name
			local here
			lcall subroutine_name
			pagesel here
here:
			endm
 
The macros work fine, they just add extra page selection lines before and after the call - so waste a little space.

So like I said, only use them if you have to.
 
One "page" of memory is 2048 program ROM locations (0x0000 - 0x07FF or 0 - 2047). This is because call and goto instructions can only supply 11 of the address bits, so bits 12 and 13 have to come from the upper two bits of PCLATH when accessing memory locations which reside past the first 2048 byte boundary.

For instructions which modify the program counter directly (addwf PCL,F for instance), each "page" is broken up into 8 "boundaries" that are 256 bytes wide. This is because register PCL is only 8 bits wide and is the only directly writable program counter register, so the upper 5 bits of the program counter address have to come from PCLATH since PCH is not directly writable.

Make sense?
 
Last edited:
How exactly does the goto instruction work then? If the PIC16 is an 8 bit microcontroller, why am I able to supply an instruction with 11 bits?

Also, referring to the code in my last post, are the lcall instruction and the pagesel directive responsible for setting bits 12 and 13 of the PCLATH?

So what do I do when I encounter a subroutine whose code exists across the 2048 boundary, or when I have a table whose return statements lie across the 256 boundary? Would I have to separate them into to separate subroutines/tables, and call them separately?
 
The 8 bits refers to the size of the data that is processed not the instruction size.

Yes they set (and clear) the PCLATH bits.

You can use the macro or, if calling page 1, simply do,
Code:
        bsf   PCLATH,3          ;bank 1
        call  SubInPage1      
        bcf   PCLATH,3          ;bank 0

Note the importance of resetting the bit(s) back to bank 0. If you fail to do this subsequent calls/gotos will jump to bank 1.

The return instruction allways uses all 13 bits as they are pulled from the stack.

Mike.
 
PIC's are an 8 bit long instruction word processor. As Pommie stated, 8 bits refers to the data size, not the instruction size.

Both call and goto instructions supply 11 of the 13 program ROM address bits. The remaining two address bits must come from PCLATH in order to call or jump to code segments past the first 2048 addresses because of this instruction limitation.

When I do look up tables in my code organization, I always do my best to keep all tables in the first 256 addresses of code space. This helps to minimize if not prevent me from having to mess with PCLATH. If you have to call a table that is past a 256 byte boundary, you must modify bits 0-2 in PCLATH prior to calling the table.

If you call or jump to a location past the first 2048 ROM addresses, you must alter bits 3 and 4 in PCLATH prior to calling the subroutine or jumping to the code segment. The pagesel macro works wonderfully for this.
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top