Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Table read and program counter

Status
Not open for further replies.

tarts

Member level 2
Joined
Dec 13, 2009
Messages
43
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Activity points
1,615
Hi
I want to look up from table in pic16f887, but it seems that the PC overflows and I can't read the table correctly with these commands:
movfw offsetvalue
call table
...
table
addwf PCL
retlw x
retlw y
...
So i read this document: https://ww1.microchip.com/downloads/en/AppNotes/00556e.pdf
and added these (in bold) two lines

org 0x80
movlw HIGH Table
movwf PCLATH

movlw offset
call Table
.
.
.
org 0x320
Table:
addwf PCL,F
retlw ’A’
retlw ’B’

it seems to work fine as long as the PC counter doesn't overroll in the middle of the table. the last example in the document doesn't seem to work at all(example 5)

Code:
org 0x80
movlw LOW Table        ;get low 8 bits of address
addwf offset,F             ;do an 8-bit add operation
movlw HIGH Table        ;get high 5 bits of address
btfsc status,c              ;page crossed?
addlw 1                     ;yes then increment  high address
movwf PCLATH             ;load high address in latch
movf offset,w               ;load computed offset in w reg
call Table
.
.
org 0x9FD
Table:
movwf PCL,F               ;load computed offset in PCL
retlw ’A’            ;return the ASCII char A
retlw ’B’            ;return the ASCII char B
retlw ’C’            ;return the ASCII char C
.
.
.
With this code the table can be located anywhere in the code. But it doesn't work for me. If you look at the code you can see that the author never tested it. status,c should be written in capitals. i fixed that, but it still doesn't work.
does anyone know what's wrong with it?
 

I think that the table should start with the low byte at 0.
IE: org 0x900.

If the table starts at 0x9fd, you only have three locations before the low byte overflows.
 

I think that this is the point of this code. It should work even if the PC overflows.
 

Hey thanks.
I didn't realize I can actually write org 0xyyy in my code and change the location of my table( I taught these were added just to show where the instructions are located in the above example)
My code works now cause the lower bits doesn't overflow(table is not longer than 255 lines)

Now the problem is I can only use locations in first page. As soon as I use locations greater than 800h(that's where page 1 starts) it doesn't work anymore. 16f887 has 4 pages of flash memory. How can I use the other 3 flash memory pages? I'm reading the upper 5 bits with these two commands:
movlw HIGH table
movwf PCLATH
And then I'll call the table. What am I doing wrong?
 

I have tested the code and it works ok?
Use Mplab Sim and put PCL and PCLATH in the watch window.
Step through the code and you should see whats going wrong.
 

Ok I tried to simulate.
I put my table in address 0x1800(in the beginning of Page 3)

movlw HIGH table -----> worked ok. it loaded 11000 in w register(bits 3 and 4 are set because these bits determine the page number. 11 means page 3)

movwf PCLATH ------->writes the data correctly into PCLATH register

Then I call the table

addwf PCL -----> PCL equals 00 which is correct

now when exiting table PCLATH still shows 11000 which means it's still on page 3.
In simulation, code keeps running correctly, but in Proteus it gives stack underflow error while executing RETLW instruction.
it seems that the upper two bits of PCH are not cleared.

I tried to clear the bits manually and it helped. but this means I have to write two call instructions to be able to clear the bits before it returns
Code:
org 0x1800
table
			call		tab	
			bcf		PCLATH,4
			bcf		PCLATH,3
			return
			
tab			addwf	PCL
			retlw	0x3e
			retlw	0x51
				...
Is it supposed to work that way? I really don't like it as it adds additional 6 instruction cycles every time I look up from table. it's no big deal but I'd prefer some cleaner solution. Any thoughts?
 

I had a play with the code and the best I could come up with is to have a label after the table call, save the result of the table look up, and then set the PCLATH bits to the correct page.
The return from the table does work ok.
Not ideal, but you only have one call.

Code:
	movf 	offset,w      ;load computed offset in w reg 
	call 	Table 		;call the look up table
	movwf   saved		;save the result
setpage:
	movlw 	HIGH setpage 	;restore page select
	movwf 	PCLATH 

	goto 	start		;continue program
 

Not sure if I completely understand your code. You are saving higher 5 bits of PC after the call look up instruction? How can you look up from the table at the first place?
 

I only showed the bit that mattered?
This is the code I was playing with.

Code:
offset		EQU	0x7E
saved		EQU 0x7d

	org 	0x80 
start:
	movlw	1
	movwf	offset
	
	movlw 	LOW Table       ;get low 8 bits of address 
	addwf 	offset,F        ;do an 8-bit add operation 
	movlw 	HIGH Table      ;get high 5 bits of address 
	btfsc 	STATUS,C        ;page crossed? 
	addlw 	1               ;yes then increment  high address 
	movwf 	PCLATH          ;load high address in latch 
	movf 	offset,w		;load computed offset in w reg 
	call 	Table 			;call the look up table
	movwf 	saved			;save the result
setpage:
	movlw 	HIGH setpage 	;restore page select
	movwf 	PCLATH 
	goto 	start			;continue program
 
	org 0x1800 
Table: 
	movwf PCL,F       ;load computed offset in PCL 
	retlw 	1            ;return 1
	retlw 	2            ;return 2 
	retlw 	3            ;return 3


	END
 

Well it doesn't work for me. The problem is not only reaching the table but returning from it. You have to edit the page select bits in PCLATH before you return.

Are you sure your code works in real life? It will probably work in MPLab sim, but have you tested it in Proteus for example.
 

It works fine using Mplab Sim. Load it up and step through the code.
Mplab is a very good and powerful simulator. I have always found that if it works in Mplab Sim it will work in the hardware.

I don't use Proteus so I can't check it in that.
 

Yes it returns from the table with no problems in Mplab Sim, but did you noticed that the 3-th and 4-th bit of PCLACH are still set after returning from the table? This is theoretically not possible. These bits must be cleared somehow in order to return to page 0.
 

'retlw' loads 'wreg' with the return value then pops the top of the stack into the program counter for the return. The top of the stack contains the call address + 1 so it can return. Look at the instruction set reference manual.
You don't have to adjust the page bits for a return on a call over page boundaries.

The program counter is separate from PCLATH.
PCLATH is only moved to the program counter on a goto or call instruction.

Proteus is wrong!
 

Ok, I don't have the real thing to test it out, you might be right.

Executing any instruction with the PCL register as the
destination simultaneously causes the Program
Counter PC<12:8> bits (PCH) to be replaced by the
contents of the PCLATH register.
I taught that the retlw instruction was one of them, as the PCL seems to be the destination of this instruction.
Anyway, big thanks for helping out. I'll post the results as soon as I'll receive my PIC.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top