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.

Calling Tables for PIC877A

Status
Not open for further replies.

jinchang

New Member
Hello,

I am having a little problem with the consistency with the results of the table calling. As the size of the code gets bigger (I am using assembly language), I was getting unexpected results as I was changing the absolute location of the table (where it is stored in the physical memory). I cannot figure out why the table calling result changes as the location of the table changes. They were all located on the same page, thus I thought the it would be the same as long as they are located on the same page.

Here is the sample code I was using and having a problem with...

movlw 0 ; Table address of start of message
movwf TEMP1 ; TEMP1 holds start of message address
movlw HIGH Table
movwf PCLATH
movf TEMP1, W
call Table
.
.
.

Table:
addwf PCL, F
retlw 'A'
retlw 'B'
retlw 'C'
retlw 'D'
.
.
.

As I move the table around (before the calling instruction or after.. or change in its absolute address due to other part of the code) it is returning this really funny results.

Can anyone take a look at my case and give me a suggestion?

Thank you.
 
I suspect you want to add the offset in W to the actual table address. The code below should work no matter where the routine and table reside in memory as long as they're on the same 4-Kword "page"...

Mike

Code:
SegData
        movwf   TEMP            ;                                 |B0
        movlw   high SegTable   ;                                 |B0
        movwf   PCLATH          ;                                 |B0
        movlw   low  SegTable   ;                                 |B0
        addwf   TEMP,W          ;                                 |B0
        skpnc                   ;                                 |B0
        incf    PCLATH,f        ;                                 |B0
        movwf   PCL             ;                                 |B0

SegTable
        dt      b'00111111'     ; "0"   -|F|E|D|C|B|A
        dt      b'00000110'     ; "1"   -|-|-|-|C|B|-
        dt      b'01011011'     ; "2"   G|-|E|D|-|B|A
        dt      b'01001111'     ; "3"   G|-|-|D|C|B|A
        dt      b'01100110'     ; "4"   G|F|-|-|C|B|-
        dt      b'01101101'     ; "5"   G|F|-|D|C|-|A
        dt      b'01111101'     ; "6"   G|F|E|D|C|-|A
        dt      b'00000111'     ; "7"   -|-|-|-|C|B|A
        dt      b'01111111'     ; "8"   G|F|E|D|C|B|A
        dt      b'01101111'     ; "9"   G|F|-|D|C|B|A
        dt      b'00000000'     ; " "    -|-|-|-|-|-|- 'nul' char
        dt      b'01000000'     ; "-"    G|-|-|-|-|-|- 'minus'
 
yes..
I am using it as a way to display a string on LCD.
I put the last entry on the table to be 0x00 and keep looping (with increasing the W register to display next letter) and stop to loop when it returns 0x00.

How can I make your code to do the same thing?
make it return from top to down one by one?
 
You would call SegData in a loop in order to use Mike's code.

skpnc = btfsc STATUS,C
dt = retlw

Mike.
 
I am sorry for asking further on this, but I am having a hard time understanding the code you provided.. So, I am not sure how to change this code to make the LCD display the string..

It maybe a stupid question but I do not know where in SegData calls the table and the where it will be returned to after the table is called. And to verify, the returning value is stored in W register, right?

Can you please explain how this code is working?
 
I'm not Mike K8LH but will try and expand on his code,

Here is Mike's code called from a loop so it displays Hello World.

Code:
PutMess		clrf	Count
Loop		movfw	Count		; get pointer
		call	SegData		; read table
		iorlw	0		; test for zero
		btfsc	STATUS,Z
		goto	DoneMess
	; call putLCD etc		; write to display
		incf	Count,F
		goto	Loop
DoneMess	return

SegData
	        movwf   TEMP            ;                                 |B0
	 	movlw   high SegTable   ;                                 |B0
		movwf   PCLATH          ;                                 |B0
		movlw   low  SegTable   ;                                 |B0
		addwf   TEMP,W          ;                                 |B0
		skpnc                   ;                                 |B0
		incf    PCLATH,f        ;                                 |B0
		movwf   PCL             ;                                 |B0

SegTable	dt	"Hello World",0

HTH

Mike.
 
Can the table be like this?
Code:
SegTable	dt	"Hello World",0
Does it mean:
Code:
SegTable
     addwf  PCL, f
     retlw  'H'
     retlw  'e'
.
.
.
and 0 is the offset?
 
Code:
SegTable	dt	"Hello World",0

Is the same as
Code:
SegTable  retlw   "H"
          retlw   "e"
          retlw   "l"
            .
            .
            .
          retlw   "l"
          retlw   "d"
          retlw   0

Mike.
 
Pommie said:
Code:
SegTable	dt	"Hello World",0

Is the same as
Code:
SegTable  retlw   "H"
          retlw   "e"
          retlw   "l"
            .
            .
            .
          retlw   "l"
          retlw   "d"
          retlw   0

Mike.
So the 'comma zero' is the last returned value right?
What are the high table and low table? addwf pcl, f is neglected because of them? Is this assembler directive?
 
bananasiong said:
So the 'comma zero' is the last returned value right?
Correct.
What are the high table and low table? addwf pcl, f is neglected because of them? Is this assembler directive?
High returns the high byte of a variable. So movlw high 0x1234 will move 0x12 into W. Low moves 0x34 into W. The addition is done by adding temp to W and then writing it to PCL. Try running it in MPSIM.

Mike.
 
Here's a method I use for printing strings from tables located in-line with my code (below). You might replace the call Put232 instruction with a call PutLCD instruction or something similar.

Good luck with your project.

Code:
;******************************************************************
;
;  here's how I print in-line code strings in my programs (_Print is a macro)
;
;
        _Print  "Bill's Particle Accelerator Demo\r\n\n"
        _Print  "Main Menu\r\n"
;
;******************************************************************
Code:
;******************************************************************
;
;  _Print macro - print a string to the RS-232 port
;
_Print  macro   str             ;
        local   String, Print
        movlw   low String      ;
        movwf   PTRL            ;
        movlw   high String     ;
        movwf   PTRH            ;
        goto    Print           ;

String  dt      str,0
Print   call    PutString       ; print string
        endm

;******************************************************************
Code:
;******************************************************************
;
;  PutString Subroutine
;
;         - setup PTRL and PTRH to string address before entry
;         - string must be terminated with a 00 byte
;
PutString
        call    GetTable        ; get a table character            |B0
        andlw   b'11111111'     ;                                  |B0
        btfsc   STATUS,Z        ; a 00 byte, last character?       |B0
        return                  ; yes, return, else                |B0
        call    Put232          ; output character                 |B0
        incfsz  PTRL,F          ; increment pointer                |B0
        goto    PutString       ;                                  |B0
        incf    PTRH,F          ;                                  |B0
        goto    PutString       ;                                  |B0
;
GetTable
        movf    PTRH,W          ;                                  |B0
        movwf   PCLATH          ;                                  |B0
        movf    PTRL,W          ;                                  |B0
        movwf   PCL             ;                                  |B0

;******************************************************************
 
BOY! I'am really sorry about the formating! This is my first post. Just when you feel smart, something simple as TABS and SPACES jump up and bite you in the butt. But I'll figure it out, I think.

This rutine was writen for MPLAB. Just cut and paste it into MPLAB.
It uses 16 bit addressing for tables larger than 256 bytes, but should work
with smaller tables. Tables smaller than 256 bytes only require 8 bit addressing. As writen it should send the text string "ERROR" .
The data char will be in W. Just change CALL LCDPRT to CALL "your_rutine".


;***********************************************************************
CBLOCK 0x20
Text_Pointer_L
Text_Pointer_H
ENDC




; setup rutine
MOVLW LOW(Text_4) ;point to Text Data label in program memory
MOVWF Text_Pointer_L
MOVLW HIGH(Text_4)
MOVWF Text_Pointer_H
CALL Table_Print ;print text to LCD



;***********************************************************************
;table rutine

Table_Print
CALL T_PRT1 ; read one char to be place in W
ANDLW 0xff ; check for 0x00 at end of text string
BTFSC STATUS, Z ; for end of text
RETURN ; 0x00 end of text, exit rutine

CALL LCDPRT ; print character in W to LCD screen

;MS_Pause_MAC .10 ;************ delay to slow down print for effect
CALL T_PRT2 ; get character to be printed
GOTO Table_Print

T_PRT1 MOVF Text_Pointer_H, W ; point to location of char
MOVWF PCLATH
MOVF Text_Pointer_L, W
MOVWF PCL
;JUMPS TO TABLE FROM HERE THEN RETURNS WITH THE CHARACTER TO BE PRINTED IN W

T_PRT2 INCFSZ Text_Pointer_L, F ;increment char address
RETURN
INCF Text_Pointer_H, F
RETURN
;***********************************************************************
;data table
; Text_0 clears a line without having to clear the entire screen
Text_0 DT ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',0x00 ; 20 spaces
; Text_1 scrolling cursor
Text_1 DT 0x10,0xfe,0x10,0x11,0xfe,0x10,0x12,0xfe,0x10,0x13,0xfe,0x10,0x14,0xfe,0x10,0x15,0xfe,0x10,0x16,0xfe,0x10,0x17,0xfe,0x10,0x18,0xfe,0x10,' ',0x00
Text_2 DT 'S','T','A','R','T',0x00 ;"START"
Text_3 DT 'E','N','D',0x00 ;"END"
Text_4 DT 'E','R','R','O','R',0x00 ;"ERROR"
 
Last edited:
Hi NosePicker,

Welcome to the forum.

To post code you need to surround it with code tags. Type "[" then "code" then "]" and at the end of your code type "[" then "/code" then "]".
Or, go to the advanced tag and use the code button.

BTW, did you realise that instead of
Code:
Text_4       DT    'E','R','R','O','R',0x00 ;"ERROR"
You can type,
Code:
Text_4       DT    "ERROR",0

Mike.
 
I was going to mention that too but figured if he hadn't picked that up by himself from all of the previous posts that he just wasn't really paying attention (grin)...
 
LOL, In my defense, for not noticing the blatantly obvious,
It's Sunday,
I spent 3 hours out driving with my No 2 daughter as she has her test Tuesday.:eek:
I spent 3 hours in the local bar because I could.:D :D
Spent 1 hour watching Grey's anatomy. Yes I know - sad.:eek:
Another hour watching life on mars (just started here).:)

And there are my mitigating circumstances for stating the bleeding obvious.:D :D

Mike.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top