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.

Crossing page boundary-Ensure page bits are set

Status
Not open for further replies.

sparky72

Member
Looking for a little help while I am experimenting with Nigel's 8x8 matrix experimental board using assembly language. I am trying to make a simple unique clock. So far I have the timing sequence set up properly and can read the time up to 2hrs but as the program gets larger mplab comes up with this message when trying to compile ,Crossing Page Poundary-Ensure Page Bits Are Set even though it says build succeeded. Since I am a beginner I do not know what to do from here. Any help that I may get will be greatly appreciated . Thanks
 
Post your code.... The pages in the mid sized pic's are 255 bytes so if your table crosses from one page to another the table may not be addressed in its entirety.... If you have more than 1 table ( under 255 bytes each ) you can set their perspective start positions, so they don't cross a boundary using org..


org 0x100 ; start of second page

table1: etc....

org 0x200 ; start ofthird page

table2: etc....
 
Post your code.... The pages in the mid sized pic's are 255 bytes so if your table crosses from one page to another the table may not be addressed in its entirety.... If you have more than 1 table ( under 255 bytes each ) you can set their perspective start positions, so they don't cross a boundary using org..


org 0x100 ; start of second page

table1: etc....

org 0x200 ; start of third page

table2: etc....

Not sure just how to do this but here is part of my code. It carries on the same with the code showing each minute starting at 12:00 to 1:50 . Anything past 1:50 and I start to get the warning message. As you can see I am not using tables. Not sure as to where I insert the org 0x100. Hope this helps. Thanks again or your help

LIST p=16F877A ;tell assembler what chip we are using
include "P16F87A.inc" ;include the defaults for the chip
ERRORLEVEL 0, -302 ;suppress bank selection messages
__config 0x393A ;sets the configuration settings (oscillator type etc.)




cblock 0x20 ;start of general purpose registers
count ;used in looping routines
count1 ;used in delay routine
counta ;used in delay routine
countb ;used in delay routine
tmp1 ;temporary storage
tmp2
p_temp ;save register for PCLATH
s_temp ;save register for STATUS
w_temp ;save register for W

;registers for display

row_pos ;position on row

zero ;zero storage
one ;one storage
two ;two storage
three ;three storage
four ;four storage
five ;five storage
six ;six storage
seven
d1
d2
d3
d4 ;seven storage

endc

ROW_PORT Equ PORTB ;row port
ROW_TRIS Equ TRISB

COL_PORT Equ PORTC ;column port
COL_TRIS Equ TRISC


org 0x0000
goto START

;**************************************************************************
; Interrupt routine
;**************************************************************************



; Interrupt routine handles TMR2 which generates a 1ms tick

; Interrupt vector

ORG 0x0004


INT
movwf w_temp ; Save W register
swapf STATUS,W ; Swap status to be saved into W
movwf s_temp ; Save STATUS register
movfw PCLATH
movwf p_temp ; Save PCLATH

btfss PIR1,TMR2IF ; Flag set if TMR2 interrupt
goto INTX ; Jump if not timed out

; Timer (TMR2) timeout


bcf PIR1,TMR2IF ; Clear the calling flag. Turns on Timer2


btfss row_pos, 0 ;check which ROW was last
goto Do_One
btfss row_pos, 1 ;check which ROW was last
goto Do_Two
btfss row_pos, 2 ;check which ROW was last
goto Do_Three
btfss row_pos, 3 ;check which ROW was last
goto Do_Four
btfss row_pos, 4 ;check which ROW was last
goto Do_Five
btfss row_pos, 5 ;check which ROW was last
goto Do_Six
btfss row_pos, 6 ;check which ROW was last
goto Do_Seven

Do_Zero

movlw 0xFF
movwf ROW_PORT ;turn off all rows
movwf row_pos
movf zero, w
movwf COL_PORT ;load columns
bcf row_pos, 0
bcf ROW_PORT, 0 ;turn ON row zero
goto INTX

Do_One
movlw 0xFF
movwf ROW_PORT ;turn off all rows
movwf row_pos
movf one, w
movwf COL_PORT ;load columns
bcf row_pos, 1
bcf ROW_PORT, 1 ;turn ON row one
goto INTX

Do_Two
movlw 0xFF
movwf ROW_PORT ;turn off all rows
movwf row_pos
movf two, w
movwf COL_PORT ;load columns
bcf row_pos, 2
bcf ROW_PORT, 2 ;turn ON row two
goto INTX

Do_Three
movlw 0xFF
movwf ROW_PORT ;turn off all rows
movwf row_pos
movf three, w
movwf COL_PORT ;load columns
bcf row_pos, 3
bcf ROW_PORT, 3 ;turn ON row three
goto INTX

Do_Four
movlw 0xFF
movwf ROW_PORT ;turn off all rows
movwf row_pos
movf four, w
movwf COL_PORT ;load columns
bcf row_pos, 4
bcf ROW_PORT, 4 ;turn ON row four
goto INTX

Do_Five
movlw 0xFF
movwf ROW_PORT ;turn off all rows
movwf row_pos
movf five, w
movwf COL_PORT ;load columns
bcf row_pos, 5
bcf ROW_PORT, 5 ;turn ON row five
goto INTX

Do_Six
movlw 0xFF
movwf ROW_PORT ;turn off all rows
movwf row_pos
movf six, w
movwf COL_PORT ;load columns
bcf row_pos, 6
bcf ROW_PORT, 6 ;turn ON row six
goto INTX

Do_Seven
movlw 0xFF
movwf ROW_PORT ;turn off all rows
movwf row_pos
movf seven, w
movwf COL_PORT ;load columns
bcf row_pos, 7
bcf ROW_PORT, 7 ;turn ON row seven

INTX
movfw p_temp
movwf PCLATH ; Restore PCLATH
swapf s_temp,W
movwf STATUS ; Restore STATUS register - restores bank
swapf w_temp,F
swapf w_temp,W ; Restore W register
retfie


;program initialisation

START
BANKSEL ADCON1 ;disable analogue inputs
movlw 0x06
movwf ADCON1
BANKSEL PORTA
bsf STATUS, RP0 ;select bank 1
movlw b'00000000' ;Set port data directions, data output
movwf ROW_TRIS
movwf COL_TRIS
bcf STATUS, RP0 ;select bank 0

clrf COL_PORT ;turn OFF all LED's
movlw 0xFF
movwf ROW_PORT

movlw 0x01
movwf row_pos


; Set up Timer 2.

; movlw b'01111110' ; Post scale /16, pre scale /16, TMR2 ON
;uncomment previous line, and comment next line, to slow multiplexing speed
;so you can see the multiplexing happening
movlw b'00010110' ; Post scale /4, pre scale /16, TMR2 ON
movwf T2CON

bsf STATUS, RP0 ;select bank 1

movlw .249 ; Set up comparator
movwf PR2

bsf PIE1,TMR2IE ; Enable TMR2 interrupt

bcf STATUS, RP0 ;select bank 0

; Global interrupt enable

bsf INTCON,PEIE ; Enable all peripheral interrupts
bsf INTCON,GIE ; Global interrupt enable

bcf STATUS, RP0 ;select bank 0


;main program loop


MAIN



;TWELVE
movlw 0x80
movwf zero ;b'10000000'
movlw 0x98
movwf one ;b'10011000'
movlw 0xA4
movwf two ;b'10100100'
movlw 0xA4
movwf three ;b'10100100'
movlw 0xA4
movwf four ;b'10100100'
movlw 0xA4
movwf five ;b'10100100'
movlw 0x98
movwf six ;b'10011000'
movlw 0xF8
movwf seven ;b'11111000'
call Delay1Minute


;TWELVE_ONE
movlw 0x80
movwf zero ;b'10000000'
movlw 0x9C
movwf one ;b'10000100'
movlw 0x88
movwf two ;b'10001000'
movlw 0x88
movwf three ;b'10001000'
movlw 0x88
movwf four ;b'10001000'
movlw 0x98
movwf five ;b'10011000'
movlw 0x88
movwf six ;b'10001000'
movlw 0xF8
movwf seven ;b'11111000'
call Delay1Minute

;TWELVE_TWO
movlw 0x80
movwf zero
movlw 0xBC
movwf one
movlw 0xA0
movwf two
movlw 0x98
movwf three
movlw 0x84
movwf four
movlw 0xA4
movwf five
movlw 0x98
movwf six
movlw 0xF8
movwf seven
call Delay1Minute


;TWELVE_THREE
movlw 0x80
movwf zero
movlw 0xB8
movwf one
movlw 0x84
movwf two
movlw 0x84
movwf three
movlw 0x98
movwf four
movlw 0x84
movwf five
movlw 0xB8
movwf six
movlw 0xF8
movwf seven
call Delay1Minute

;TWELVE_FOUR
movlw 0x80
movwf zero
movlw 0x88
movwf one
movlw 0x88
movwf two
movlw 0xFC
movwf three
movlw 0xA8
movwf four
movlw 0x98
movwf five
movlw 0x88
movwf six
movlw 0xF8
movwf seven
call Delay1Minute

;TWELVE_FIVE
movlw 0x80
movwf zero
movlw 0x98
movwf one
movlw 0xA4
movwf two
movlw 0x84
movwf three
movlw 0xBC
movwf four
movlw 0xA0
movwf five
movlw 0xB8
movwf six
movlw 0xF8
movwf seven
call Delay1Minute


;TWELVE_SIX
movlw 0x80
movwf zero
movlw 0x98
movwf one
movlw 0xA4
movwf two
movlw 0xA4
movwf three
movlw 0xB8
movwf four
movlw 0xA0
movwf five
movlw 0x9C
movwf six
movlw 0xF8
movwf seven
call Delay1Minute

;TWELVE_SEVEN
movlw 0x80
movwf zero
movlw 0xA0
movwf one
movlw 0x90
movwf two
movlw 0x88
movwf three
movlw 0x84
movwf four
movlw 0x84
movwf five
movlw 0xBC
movwf six
movlw 0xF8
movwf seven
call Delay1Minute

;TWELVE_EIGHT
movlw 0x80
movwf zero
movlw 0x98
movwf one
movlw 0xA4
movwf two
movlw 0xA4
movwf three
movlw 0x98
movwf four
movlw 0xA4
movwf five
movlw 0x98
movwf six
movlw 0xF8
movwf seven
call Delay1Minute

And so on.
 
Last edited:
You may want to read up on using program loops. It would save a lot of code.
 
So not Tables????

goto's and calls are 511 byte jumps.... There is nothing wrong here, other than your code is too widespread..

Make subroutines and reuse code... I think the messages are not "errors" but "warnings"... This always happens as the assembler doesn't see the bank selections...... You can actually turn these warnings off...
 
So not Tables????
that come up when mplab compiles the code.
goto's and calls are 511 byte jumps.... There is nothing wrong here, other than your code is too widespread..

Make subroutines and reuse code... I think the messages are not "errors" but "warnings"... This always happens as the assembler doesn't see the bank selections...... You can actually turn these warnings off..

Yes Ian you are correct. These are warnings when mplab compiles the code. When the warnings come up my time display starts to screw up. Would removing these warnings help, and if so how do I turn them off? I am wondering how I can reuse the code since every time display is different. My clock works like this.On the 8x8 matrix the left column and part of the top row keeps track of the 12 hours, and the right column keeps track of the 10s of minutes, while the minute is displayed in the center. Thanks again for your input
 
Last edited:
No!!! Take heed of the warnings... Go through each one and make sure the correct bank is selected at each warning..

I always use the "banksel" directive to ensure the correct bank is selected... make sure you're always back in bank 0 when you are done..
 
I think that the problem is that the code is so spread out that it is larger than 2048 instructions. The 16F877 has and instruction set that only supports 11 bit CALL and GOTO, but total address space needs 13 bit to address it. The remaining 2 bits are called in from PCLATH, bits 3 and 4. You need to get those correct before each CALL or GOTO or the program counter will jump to the wrong place.

The warnings come from the compiler realising that the jump is to a destination that has the top two bits of the destination address different from the instruction address.

For example, if I have

Org 0x000
Do_this
movlw 0x00
return

Org 0x800
Do_that
movlw 0xff
return


Then
call Do_this
and
call Do_that
will both result in exactly the same instruction, which will have an address within it of 0x000, as it only has space for the 11 bits.

To get
call Do_that
to work, you need to make sure that bits 3 and 4 of PCLATH are at 1 and 0, so you would need code like this:-

movlw 0x08
movwf PCLATH
call Do_that


You have to set the bits back to zero for calling DO_this



 
No!!! Take heed of the warnings... Go through each one and make sure the correct bank is selected at each warning..

I always use the "banksel" directive to ensure the correct bank is selected... make sure you're always back in bank 0 when you are done..
I think that it is the program memory pages that the OP is having trouble with, rather than the data memory banks.
 
Looking for a little help while I am experimenting with Nigel's 8x8 matrix experimental board using assembly language. I am trying to make a simple unique clock. So far I have the timing sequence set up properly and can read the time up to 2hrs but as the program gets larger mplab comes up with this message when trying to compile ,Crossing Page Poundary-Ensure Page Bits Are Set even though it says build succeeded. Since I am a beginner I do not know what to do from here. Any help that I may get will be greatly appreciated . Thanks

As far as I can tell, a lot of your program is made of big look-up tables, which are storing the shape of the characters to display. I think that you would do much better to store the values you want in program space and read them as values rather than executing them as code. The data sheet has examples of "Flash Program Read" (it's section 10.1.4 in the data sheet version that I have).

I suggest you have code that broadly has parts that
1) count up the time
2) use the time to decide where in program memory the correct shape is stored
3) collect the shape data
4) display the shape data

The last two parts might not be run completely one after the other. You could have code that collects one line of shape data, and then displays that line, and so on for all 8 lines of data.

You should get familiar with indirect addressing.
 
...And so on.
That can lead to wild speculation...

You have a 17 word code block for every minute of the day. At least, that's how it appears.

Given that there are 720 minutes in a 12 hour period, or if this is a 24 hour clock, then 1440 minutes, multiply that by the 17 words in each code block and you get 12240 (or 24480) words of code. I haven't checked the specs of a 16F877A, but I suspect that it's not going to fit. Hence, my earlier comment about using a loop.
 
That can lead to wild speculation...

You have a 17 word code block for every minute of the day. At least, that's how it appears.

Given that there are 720 minutes in a 12 hour period, or if this is a 24 hour clock, then 1440 minutes, multiply that by the 17 words in each code block and you get 12240 (or 24480) words of code. I haven't checked the specs of a 16F877A, but I suspect that it's not going to fit. Hence, my earlier comment about using a loop.

You are correct Bob. The 16f877A chip only has 8192 single word instructions. The clock is only for a twelve hour period. Not just sure how I would implement a loop in my code. Thanks for your input.
 
You are correct Bob. The 16f877A chip only has 8192 single word instructions. The clock is only for a twelve hour period. Not just sure how I would implement a loop in my code. Thanks for your input.

Check out tutorial 13.4, which uses a large table for generating a font, and another large table to hold a string to display.

This tutorial contains all you need to generate a clock (or any other text/numeric) display.
 
Check out tutorial 13.4, which uses a large table for generating a font, and another large table to hold a string to display.

This tutorial contains all you need to generate a clock (or any other text/numeric) display.

Thanks Nigel for your response. Here is what I have done so far using the font table. Each display in the RETLW table has the minute displayed in the center of the 8x8 matrix, with the hrs represented in the left column and top row of leds, and the 10,s of minutes in the right column of leds. I put a one minute delay at the end of the ScrollR8 code. The code compiles with no errors and when activated the display works great from 12:00 to 1:35 but then returns to 12:00 again not going through the remainder of the RETLW displays. Since there are (12x60 minute ) 720 displays to show , will the 16f877A chip handle it. Hope this explains what I am trying to do. Take care
 
You need to start looking at this another way...

How many bitmaps have you got to display...ie.. The 8x8 matrix needs to show what??? Then you need to store each one in a table... Then have a small routine that collects the 8 sequences and puts them where they need to go..

You can get access to the 170 sets of 8 by using large table code ( In the same place as you got the rest of it )
Note the high and low table parameters..

Code:
ASCII_Table            ;perform read from long table
     movlw   High(Table)
     addwf   offsetH, W
     movwf   PCLATH
     movlw   Low(Table)
     addwf   offsetL, w
     btfsc  STATUS  , C
     incf   PCLATH, f
     MOVWF  PCL

Using a table and a simple routine will cut your code down to a manageable size..
 
You need to start looking at this another way...

How many bitmaps have you got to display...ie.. The 8x8 matrix needs to show what??? Then you need to store each one in a table... Then have a small routine that collects the 8 sequences and puts them where they need to go..

You can get access to the 170 sets of 8 by using large table code ( In the same place as you got the rest of it )
Note the high and low table parameters..

Code:
ASCII_Table            ;perform read from long table
     movlw   High(Table)
     addwf   offsetH, W
     movwf   PCLATH
     movlw   Low(Table)
     addwf   offsetL, w
     btfsc  STATUS  , C
     incf   PCLATH, f
     MOVWF  PCL

Using a table and a simple routine will cut your code down to a manageable size..

Ian, I have tried nigel's code (tutorial 13_3) using the ASCII table above. But since I have 720 sets of 8 code it seems that the 16f877A can not handle that much . Like I say, the clock works well up to 1 hr and 35 minutes then reverts back to start all over again. Getting frustrated. Thanks again for your patience and input.
 
you said:
Ian, I have tried nigel's code (tutorial 13_3) using the ASCII table above. But since I have 720 sets of 8 code it seems that the 16f877A can not handle that much . Like I say, the clock works well up to 1 hr and 35 minutes then reverts back to start all over again. Getting frustrated. Thanks again for your patience and input.

Let me help you.... If you show me a sample of your output ie... "12:00".. How is it being displayed?? How many 8x8 LED panels are you using???

I would imagine there will be many duplications in the data.... There are also many ways to optimize...
 
Ian, I have tried nigel's code (tutorial 13_3) using the ASCII table above. But since I have 720 sets of 8 code it seems that the 16f877A can not handle that much .

You're going about this entirely incorrectly - why on earth would you have 720 sets of characters?

You only need characters for 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 and : - that's only 11 characters - however, it would be easier to use the full ASCII character set from my tutorials and pick the ones you want, there's plenty of space.

Programming is all about loops and sub-routines, you don't use linear programming, it's almost impossible to program like that, and incredibly wasteful and difficult.
 
Let me help you.... If you show me a sample of your output ie... "12:00".. How is it being displayed?? How many 8x8 LED panels are you using???

I would imagine there will be many duplications in the data.... There are also many ways to optimize...


OK Here is what I am doing. I am using one 8x8 matrix that is being multiplexed. The display on the matrix is as such. The left outside column and part of the top row of leds represents the hours. (eg: The bottom left hand corner led of the matrix represents hour 1 o'clock if lit. The next led above it represents 2 o'clock if lit and so on up and across the top until you get to 12 o'clock. The right hand column represents the 10's of minutes. (eg: the bottom right hand corner represents 10 when lit. The next led above it represents 20 when lit and so on. Now the center of the matrix represents the actual numbers using the different combinations of leds to display 0 t0 9. Hope I have explained it well enough. Thanks. Take care

12:00 would show up on the matrix as such. Left hand column and four leds of the top row would represent the 12th hour if lit, if the number 0 is lit up with it in the center of the matrix it would represent 12:00 o'clock. If the bottom right hand corner led is lit also ,it would be 12:10.
 
Last edited:
Status
Not open for further replies.

Latest threads

Back
Top