PDA

View Full Version : PBP, Assembly Interupts and variables



Chris Barron
- 14th February 2006, 17:55
I have a variable assigned as

CONTROL VAR BYTE at the start of my program

In the assembler interupt I set bit 1 with
bsf _CONTROL,1

and later in Basic I check for the bit set with
IF CONTROL.1 =1 THEN
;do action
ENDIF

I _know_ for sure that the line immediately before bsf _control,1 is
executed correctly, leading to the assumption that this line gets executed too.

The problem is that I can never get the final Basic test to be true even
though I know that the bit is set in the interupt.

I normally program in assembler so PBP is new to me, what are the conditions
which need to be met in order to share a variable, and why won't this code work?

Regards
Chris

There are 10 types of people in the world.......
....Those who understand binary and those who don't !

languer
- 14th February 2006, 19:12
What chip are you using?
The interrupt control register should already be mapped in the INC file for that chip. This would be the name you use (instead of CONTROL) -> most likely INTCON. As it is CONTROL is a variable and when you do bsf _CONTROL,1 you're trying to set the flag on the register located at CONTROL (whatever that value happens to be at the time). So depending on how that variable is defined (or initialized) you may be setting a flag in the INTCON register or some where else. When you read CONTROL.1 you're just reading the variable, not the register (see you never change the variable in assembly - you try to set the flag in the register pointed to by CONTROL).

Just look at the INC file, but it would probably be something like this:


asm
bsf INTCON,1
endasm
...
IF INTCON.1 =1 THEN
;do action
ENDIF

Chris Barron
- 14th February 2006, 19:38
What chip are you using?

>Its the 16F690

The interrupt control register should already be mapped in the INC file for that chip. This would be the name you use (instead of CONTROL) -> most likely INTCON.

Yes, I am dealing with INTCON too, in the usual way. The lines of code I wrote in the example just refer to the relevant parts of my program.
I use 'Control' to indicate certain functions have created an interupt. For example, if the Usart receives a byte of data I set Control,1. if the interupt is caused by a succesion of timer 1 overflows, enough to create a 1second time period I set bit Control,0.

I am doing it this way because i need the interupt accuracy for timing purposes, IE without the latency created when dealing with interupts through PBP.

Later, when the interupt is over, and at a time convenient to me (in programming terms) I check the bits of CONTROL and act accordingly
. In this way the data never overflows and the timing period is accurate regardles of what pbp instruction is being executed. Perhaps if executing a long pause statement 5 data bytes could be received, this would cause an overflow error.


As it is CONTROL is a variable and when you do bsf _CONTROL,1 you're trying to set the flag on the register located at CONTROL (whatever that value happens to be at the time).

> Erm, I'm not quite sure that's entirely true. The command actually sets bit number 1 in the address pointed to by the label CONTROL. That's what Microchip datasheets have always said anyway....




So depending on how that variable is defined (or initialized) you may be setting a flag in the INTCON register or some where else. When you read CONTROL.1 you're just reading the variable, not the register (see you never change the variable in assembly - you try to set the flag in the register pointed to by CONTROL).

> ah okay, i see what details you're saying I've got confused about, but it's not the case. CONTROL is declared as a user variable, and presumably pbp is assigning it to an address at or above $20. The INTCON register is at a lower address, and it has to be fair to assume that pbp absolutely does perform this action, otherwise it would never work.

I am going to be using FSR and INDF at a later point but it's commented out at the moment so that's not a cause of confusion at the moment.


Just look at the INC file, but it would probably be something like this:


asm
bsf INTCON,1
endasm
...
IF INTCON.1 =1 THEN
;do action
ENDIF



Do you mean the LST file instead ? The INC file contains the address of the SFR's and the numbers and names of the bits in those registers, as well as the config data setups, and badram data area info.

I suppose in simple form my question is this............
WHen the manual says that if I declare a variable with VAR BYTE in basic and I can access that variable with an underscore in front of it's name in assembler how come nothing changes when I bsf a bit in assembler and try reading it back it's state later on ?

Bruce
- 14th February 2006, 21:59
Assuming you're actually setting bit 1 in CONTROL, this will work;

IF CONTROL.0[X] THEN ' IF CONTROL.BIT.X = 1 THEN do something.

X is the bit index pointer 0 to 7. The .0 just tells PBP it's a bit.

If your variable is in bank 0, this works fine. If it's not, or you're just
not sure, then use CHK?RP in your assembler routine to look up the
bank for the var you're using.

ASM
CHK?RP _CONTROL
bsf _CONTROL,1
ENDASM

CHK?RP is a PBP macro that just looks up the variable register bank.

Chris Barron
- 14th February 2006, 22:13
[QUOTE=Bruce]Assuming you're actually setting bit 1 in CONTROL, this will work;

IF CONTROL.0[X] THEN ' IF CONTROL.BIT.X = 1 THEN do something.

X is the bit index pointer 0 to 7. The .0 just tells PBP it's a bit.

Yes, the '.0' at the end of CONTROL.0 is how I have pointed to bit0 of register 'CONTROL' .

But the good news is that by declaring the Restore variables of system registers , WSAVE,PSAVE and SSAVE, in lower-case as wsave,ssave and psave the problem is gone............

Looked at pbppic14.lib and can see that the interupt handler in there uses the lower case version. My target chip ,16F690 has4K memory and uses the lib procedures.

So I'm happy now that that code works but now I have another problem......
In the interupt I increment a register once every 20mS

Later in the basic code I try making PORTC = TICKS (ticks is the incremented register). LED's attached to portC show the value of ticks but then it's as if the port is cleared because all led's quickly go blank, until the next time TICKS changes (I presume)

Weird...I see that PORTH is mapped to PORTC, so do I have to call PORTC with PORTH, or run the risk of the PORTH value over-riding the value I set it to ?

Learning curves are here for a reason I suppose !

Bruce
- 14th February 2006, 22:41
so do I have to call PORTC with PORTH

No just access/use PORTC as you would normally.

Can you post your code? That would make it a lot easier to isolate
what's going on when you're placing ticks on portc.

Chris Barron
- 15th February 2006, 08:09
'It's a newbie thing' , as they say.

I turned off the enthusiasm and got down to reading the documentation.

The PORTH - PORTC define is a non-issue, as you say Bruce. PORTC is referenced as PORTC in the 16F68x.inc file, correctly.

The error was that I didn't notice the section of the manual dealing with interrupts for when the target device has more than 2K of codespace - I have added my own interrupt handler stub when PBasic has added one for me already. Consequently, when my stub runs after Pbasic's stub W is actually saved as the last action of the PBasic stub, and not the last value of the runtime code. Also there may have been another error with my restoration of the context registers, but I couldn't check it - I blew away and re-wrote the assembler interrupt stub completely and now it runs just as expected.


Thanks to everyone for their suggestions.

RTFM, as they say.........

Chris