![]() | ![]() | ![]() |
| | |||||||
| Micro Controllers Discuss all aspects of micro controllers - building them, coding them, etc. All controllers are welcome - PIC, BASIC, Z8 Encore!, etc. |
| | LinkBack | Thread Tools | Display Modes |
| | (permalink) |
| ok I've been stuck for 2 days, tried everything I could find on the net and read the “Implementing a Table Read" (AN556) Application note about 25 times and I just can't figure it out! I'm reading tables that contain text menus that will be displayed on a LCD screen. Everything was going great and all until I started to add interrupt code just before the tables and everything shifted in memory to go over the 0x100 border, now everything before the border works great with my display code but nothing after it works. Here is a snipet of my original code... Code: DisplayBatID call LCD_Clr
clrf count ;set counter register to zero
DisplayBatID_1 movf count, w ;put counter value in W
call BatIDL1 ;get a character from the text table
xorlw 0x00 ;is it a zero?
btfsc STATUS, Z
goto DisplayBatID_2
call LCD_Char
incf count, f
goto DisplayBatID_1
DisplayBatID_2 call LCD_Line2
clrf count ;set counter register to zero
DisplayBatID_3 movf count, w ;put counter value in W
call BatIDL2 ;get a character from the text table
xorlw 0x00 ;is it a zero?
btfsc STATUS, Z
goto DisplayBatID_4
call LCD_Char
incf count, f
goto DisplayBatID_3
DisplayBatID_4 bcf flags, change
retlw 0x00 Then after my problems started to appear, I tried to implement the code in the application note from Microchip but nothing good has worked and I'm pretty much stumped right now. So I'm hoping someone else might have stumbled on this problem and could give me a push in the right direction. I'm pretty much confused about the HIGH and LOW directives or whatever they call them as seen in the application note. BTW I'm using a PIC16F873 MCU Thanks! | |
| |
| | (permalink) |
| You didn't post the most relevant code, the one which makes the actual table read! I assume that PCLATH is at it default power-up value of 0. In this case, all instructions using the "ADDWF PC,F" or "MOVWF PC,F" instructions will end up in the first 256 locations in memory. Since you are putting the interrupt service routines in those locations, you are running out of space there. The quick fix is to relocate the table outside this range, preferably at the start of a 256 byte boundary. You then simply initialize PCLATH to point to that location. Attached is sample code to illustrate: Code: ;
call GET_TABLE_VALUE
;
; additional code follows here
;
goto elsewhere
GET_TABLE_VALUE:
movwf temp ; temporarily save WREG
;
movlw HIGH TABLE_START
movwf PCLATH
;
movf temp,W
movwf PC,F
;
;----------------------------------------------------
ORG (HIGH $ + 1)*100h ; start on the next page
TABLE_START:
retlw 0
retlw 1
; .
; .
; .
; .
retlw d'254'
retlw d'255'
;----------------------------------------------------
__________________ "Having to do with Motion Control" | |
| |
| | (permalink) | |
| Quote:
| ||
| |
| | (permalink) |
| :idea: They way I impliment long lookup tables is to load PCLATH as well in the look up BEFORE the jump......... LOOKUP_LONG MOVF LU_HIGH,W ;MOVE LOOKUP HIGH TO W MOVWF PCLATH ;STORE IN PC LATCH HIGH MOVF LU_LOW,W ;MOVE LOOKUP LOW TO W ADDWF PCL,F ;ADD TO PROGRAM COUNTER LOW RETLW XX RETLW XX ;ETC This is very similar to you earlier code, but you were loading a fixed literal into pc latch high. Your calling code (to the look up) will have to keep track of pc latch high, if you know the starting value then on increasing "LU_LOW" if carry is set then increase "LU_HIGH" code to call lookup.... INCF LU_LOW,F ;INCREASE LOOK UP LOW BTFSC STATUS,C ;IS CARRY SET? INCF LU_HIGH,F ;YES, INCREASE LOOK UP HIGH VALUE Hope this helps!
__________________ Regards MATT! | |
| |
| | (permalink) |
| Thanks guys for the replies, but I finally figured it out. Here is the code I finally came up with (that I forgot to post in my original question), pretty much what I already had going and was wondering why it would not work! Code:
DisplayBatID call LCD_Clr
clrf offset ;set offset register to zero
movlw d'1' ;set count register to the first
movwf count ;|character in the table
DisplayBatID_1
movf count, w ;put count value in offset
movwf offset ;|
movlw LOW BatIDL1 ;get low address of the table
addwf offset, f ;add the low address of the offset value
movlw HIGH BatIDL1 ;get high adress of the table
btfsc STATUS, C ;check if carry bit is set from the add operation
addlw 1 ;if carry set add 1 to w
movwf PCLATH ;place the high address in PCLATH
movf offset, w ;place low address in w
call BatIDL1 ;get a character from the text table
xorlw 0x00 ;is it a zero?
btfsc STATUS, Z ;check if zero bit is set from the above compare
goto DisplayBatID_2 ;if zero set get out of here
call LCD_Char ;zero not set, display character
incf count, f ;increment count register
goto DisplayBatID_1 ;start again and get next character in table
DisplayBatID_2 call LCD_Line2
clrf offset ;set offset register to zero
movlw d'1' ;set count register to the first
movwf count ;|character in the table
DisplayBatID_3
movf count, w ;put count value in offset
movwf offset ;|
movlw LOW BatIDL2 ;get low address of the table
addwf offset, f ;add the low address of the offset value
movlw HIGH BatIDL2 ;get high adress of the table
btfsc STATUS, C ;check if carry bit is set from the add operation
addlw 1 ;if carry set add 1 to w
movwf PCLATH ;place the high address in PCLATH
movf offset, w ;place low address in w
call BatIDL2 ;get a character from the text table
xorlw 0x00 ;is it a zero?
btfsc STATUS, Z ;check if zero bit is set from the above compare
goto DisplayBatID_4 ;if zero set get out of here
call LCD_Char ;zero not set, display character
incf count, f ;increment count register
goto DisplayBatID_3 ;start again and get next character in table
DisplayBatID_4 bcf flags, change
retlw 0x00 After looking at the application note from Microchip, it flashed in my face that this is what they were doing also but just did not notice it before!!! Now that it works, I try to optimise the code a little, I probably can cut down on the variable registers (offset and count) so that only one is required and save a few instructions in the process. In reply to Matt... Not sure how your code works but from what I can see it should not work at all because the "incf HU_LOW,F" does not affect the Carry bit. So your "incf LU_HIGH,F" right after your carry test would never be executed. This is why I use the "addwf" instead of a standard "incf" instruction in my code instead of incrementing it. It's also why I must use two different registers to keep track of where I am in my offset calculations and carry over test! In reply to Nigel and motion... I tought of doing this (changing the location of my tables) but I have so many messages to display I'm going over 3 memory boundaries. If I would add other tables in the middle of them so that relevant messages are grouped together, I would have to recode a bunch of code to take in to account the changes each time! Anyway thanks to everyone for the suggestions, I think all I needed was a good 5 hours of sleep | |
| |
| | (permalink) | |
| Quote:
| ||
| |
| | (permalink) |
| :wink: Yes you are right exo,nclark, I relised last night, when I checked my code, I should have checked it first instead of guessing!!! :wink: Check the Z flag, the staus is not affected.... opps! but you get the idea I hope! Anyway I hope this helps..... whoever it was meant to help!! :lol:
__________________ Regards MATT! | |
| |