# PIC instruction!

Status
Not open for further replies.

#### t.man

##### New Member
does it mean "banksel" is not executed?
when i build this code i get this message output for both
Code:
	clrf TRISB ;make them all output
:

and
Code:
movwf OPTION_REG

Message[302] ...... : Register in operand not in bank 0. Ensure that bank bits are correct.

the code:
Code:
;toggle LED for each tmr0 overflow
;developer: ????
;version 0.0
;for PIC: 16f877a
;
;

processor 16f877A

include "p16f877A.inc"

__config _CP_OFF & _WDT_OFF & _PWRTE_ON & _RC_OSC

org 0x00
goto main

org 0x04
goto ISR

init
banksel TRISB
clrf TRISB ;make them all output
movlw b'10000100'; clock/32
banksel OPTION_REG
movwf OPTION_REG
banksel PORTB
clrf PORTB ;all output pins low
bsf INTCON, TMR0IE;tmr0 overflow
bsf INTCON, GIE;enable interrupts
return

main
call init;set up the PIC

loop
goto loop;do nothing, interrupt will take you out of here

ISR
xorlw 0x01
movwf PORTB;toggle LED
retfie
end

is there a thing called internal oscillator in PIC16f877a?

#### Nigel Goodwin

##### Super Moderator
Message[302] ...... : Register in operand not in bank 0. Ensure that bank bits are correct.

It's not an error message, just to inform you - you can disable with the error level instruction.

is there a thing called internal oscillator in PIC16f877a?

Not fully, it requires external components as well - although the oscillator itself is internal.

#### t.man

##### New Member
It's not an error message, just to inform you - you can disable with the error level instruction.
i just wondered what action should i take to make it happy?

Not fully, it requires external components as well - although the oscillator itself is internal.

i just see that i'm prescaling my clock with 32...but i don't know its value. how do i set the value of this internal clock?

does the value determined by these external components? i.e R and C?

#### ericgibbs

##### Well-Known Member
i just wondered what action should i take to make it happy?

i just see that i'm prescaling my clock with 32...but i don't know its value. how do i set the value of this internal clock?

does the value determined by these external components? i.e R and C?

processor 16f877A
include "p16f877A.inc"

errorlevel -302 , -207 ; suppress message 302 from list file

#### Pommie

##### Well-Known Member
There is no internal oscillator on an 877. If you switch to the 887 then that has an internal oscillator that can run from 32k to 8MHz. You appear to be using an external RC oscillator and so should have a resistor and capacitor on the osc pin.

As for banksel, I hate it, it is the dumbest macro ever written and Microchip should be ashamed of it. I did write my own version of it that was much more efficient but stopped using it as it just bloats your source code.

Mike.

#### t.man

##### New Member
There is no internal oscillator on an 877. If you switch to the 887 then that has an internal oscillator that can run from 32k to 8MHz. You appear to be using an external RC oscillator and so should have a resistor and capacitor on the osc pin
.

how do i determine my frequency from these components?

#### t.man

##### New Member
another quick problem:
my program doesn't seem to return from interrupt:

i added this line to the code:
bcf INTCON,TMR0IF

and then it changes from:
ISR
movlw 0x01
xorwf PORTB,1;toggle LED
retfie
end

to:
ISR
movlw 0x01
xorwf PORTB,1;toggle LED
bcf INTCON,TMR0IF
retfie
end

is it the right thing to do?

#### birdman0_o

##### Active Member
You need to save the W and STATUS registers in an interrupt:

When you enter

Code:
ISR
MOVWF	W_TEMP						;
SWAPF 	STATUS,W   					; Context Saving
MOVWF 	STATUS_TEMP					;

and

Code:
Exit
SWAPF 	STATUS_TEMP,W				; Restore Status and W
MOVWF 	STATUS						;
SWAPF 	W_TEMP,F					;
SWAPF 	W_TEMP,W					;
RETFIE

When you Exit

#### birdman0_o

##### Active Member
What are you trying to do by the way

Last edited:

#### kpatz

##### New Member
As for banksel, I hate it, it is the dumbest macro ever written and Microchip should be ashamed of it. I did write my own version of it that was much more efficient but stopped using it as it just bloats your source code.
I made my own macro too (I called it selbank), which keeps track of what bank was last selected so it can assemble in only the instructions needed to select the correct bank.

Of course the problem is, branches and calls make it not always possible to know where you're coming from so for the first banksel in a routine I have another macro called fselbank that doesn't check, but it sets the macro variables so subsequent selbanks work correctly.

Microchip should have provided a single-word bank select instruction, and wrote the assembler to (optionally) automatically insert whatever bank-select instructions are needed whenever you access a register. That and they should have organized the registers in the banks better. Having the TRISx and PORTx registers in separate banks was a dumb move IMHO.

They should also provide something to allow automatic bank selection for file registers in different banks in relocatable modules (where the location isn't known until link time).

#### Nigel Goodwin

##### Super Moderator
Having the TRISx and PORTx registers in separate banks was a dumb move IMHO.

Presumably there's a very good reason for it been like that.

#### birdman0_o

##### Active Member
How many instructions does "Banksel" use up?

#### kpatz

##### New Member
It depends on how many bank-selection bits are present in the status register. I believe most PIC16 series have 2, so banksel generates 2 bsf or bcf instructions everytime it's used.

If any PICs have more than 4 banks, thus needing a 3rd bank select bit, that's another instruction.

The macro I made keeps track of each bit so it generates only the instructions needed to change the bits that need to be changed. So, on a PIC16F818 for example it'll generate 0, 1, or 2 instructions. And if I'm not using anything in the last 2 banks (bank2&3) the macro will generate a maximum of 1 instruction.

Last edited:

#### Nigel Goodwin

##### Super Moderator
How many instructions does "Banksel" use up?

Look at the code it creates - it's nothing drastic, but it creates more lines than it needs. As far as I'm aware, the version Pommie wrote (amongst many other peoples versions), just creates the lines it needs to - so I don't understand Pommie's aversion to it?.

#### kpatz

##### New Member
Oops, duplicate... delete...

Last edited:

#### birdman0_o

##### Active Member
I see what I misunderstood after looking at a disassembly. The assembler uses a macro which checks which bank you want to select which returns 0,1,2 instructions that sets the right bits in the Status register. There isn't actually a bunch of instructions checking the actual program.

#### Pommie

##### Well-Known Member
My aversion to the use of even my (more efficient) macro was the fact it makes the source unreadable. In effect you need a banksel before every memory access. Much better to learn which registers are in which bank and use a single bsf etc to switch banks at the appropriate time. Microchip, in their wisdom, removed all the register addresses from the data sheet sections - EG, timer 1 section.

On a 16F876, using banksel, writing to a tris register can take 6 instructions. This is supposed to be an efficient chip.

Mike.

#### kpatz

##### New Member
Well, you could use a movlw (value) followed by a movwf STATUS to set all the bank bits with 2 instructions, but you'll also overwrite other status bits you might not want to lose.

My macro is called like banksel but is called selbank, and it assembles only the instructions needed based on the last bank selected, so it's more efficient than the one provided by Microchip. If there's a chance that the bank bits won't match what the macro thinks they are (such as after a branched-to section of code) I have a fselbank macro that sets all the bits (2 instructions) and updates the macro variables so that subsequent selbanks work properly. Also, if I'm only using banks 0 and 1 on a chip with 4 banks, I can define a value that tells the macro to not add instructions for setting the second bit, allowing for 1-instruction bank setting.

Another cool macro I created is movlbw(1-6). Actually, 6 macros but the only difference is the number of arguments accepted. Each argument is a bit value like those used in bsf, bcf, btfss, btfsc etc. They are logically ORed together by the macro and used to build a literal that is then moved into W with a movlw instruction. This is handy for setting bit-oriented status registers using the bit names without having to use a bunch of bcf and bsf instructions. Instead you call the appropriate movlbw macro, then movwf the end result to the register.

IMHO, Microchip should have put all the registers relevant to a particular function in the same bank. For example, PORT and TRIS registers should have been put in the same bank; all the A/D registers in the same bank, etc.

Last edited:

#### birdman0_o

##### Active Member
I have no problem memorizing the banks, and if I forget I just check the memory block diagram on the datasheet.

This makes the code more efficient when you know which bank the code is selecting. You can group items in the same bank and perform a function on them before switching back instead of continuous switching between banks.

Status
Not open for further replies.

Replies
6
Views
5K
Replies
10
Views
2K
Replies
4
Views
3K
Replies
17
Views
9K
Replies
6
Views
3K