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.

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?
 
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.
 
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?
 
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

Add this line.:)
 
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.
 
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?
 
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?
 
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
 
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).
 
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:
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?.
 
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.
 
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.:confused:

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

Mike.
 
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:
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.

Latest threads

New Articles From Microcontroller Tips

Back
Top