PDA

View Full Version : Writing PBP Commands/macros



awmt102
- 30th April 2010, 18:02
Hi all,

I learnt how to program PICs using Microchips C18. Its only since starting a new job that I have begun learning PBP as its what everyone else uses. The good news is that I like it and am perfectly happy using it.

The only thing I miss is functions. Subs are OK but not being able to pass arguments to them is a little annoying and makes the code a little untidy IMO. So I did some searching in the forums to see if its possible to make custom functions in PBP.

From what I can see there is no way to create custom functions that operate exactly the same as LCDOUT or SHIFTOUT etc. Is this true, or is there some way this can be done?

The only thing I did find is a post by Darrell Taylor about calling PBP from an assembler macro (this can be seen in his LCDBargraphs project) and I got this working quite nicely. However I found one thing that I could not work out. The following works fine and 97 is passed to the macro correctly (which writes it to an LCD ("a")):



temp = 97
@ MyFunction _temp

However the following does not work and nothing is written to the LCD:



@ MyFunction 97

Can anyone tell me why this is? I cannot see why there is a difference.

Bruce
- 30th April 2010, 20:15
Without seeing your function it's hard to tell what's wrong, but it's easy to pass numeric values.

Try something like this;


PIN VAR BYTE BANKA SYSTEM ' system vars in access ram
TIME VAR WORD BANKA SYSTEM
NUMS VAR BYTE BANKA SYSTEM
LOOPS VAR BYTE
X VAR BYTE

ASM
PULSE MACRO PinToPulse,TimeToPulse,NumberOfLoops
MOVLW PinToPulse
MOVWF PIN
MOVLW LOW TimeToPulse
MOVWF TIME
MOVLW HIGH TimeToPulse
MOVWF TIME+1
MOVLW NumberOfLoops
MOVWF NUMS
CALL _DOPULSE
ENDM
ENDASM

MAIN:
@ PULSE 0,256,10 ; Pulse RB0, pause 256mS, 10 times
PAUSE 1000
GOTO MAIN

DOPULSE:
FOR LOOPS = 1 TO NUMS
HIGH PIN
PAUSE TIME
LOW PIN
PAUSE TIME
NEXT LOOPS
RETURN

awmt102
- 1st May 2010, 19:31
Hi Bruce, thanks for the reply,

I use the following code and INCLUDE it in my main PBP file:



' ================================================== ============================
' Constants
' ================================================== ============================


CONTROL_BYTE con $40 ' write operation to device address $00

' Port Expander Registers
IOCON con $0A
IODIRA CON $00
IODIRB CON $01
GPIOA CON $14
GPIOB con $15


' ================================================== ============================
' Pin Definitions
' ================================================== ============================

SCLK var PORTC.3
SDI var PORTC.4
SDO var PORTC.5

nCS var PORTA.2
nRST var PORTA.3

REGISTER_BYTE var byte
DATA_BYTE var byte


goto EndOfPortExpander
' ================================================== ============================
' Macros
' ================================================== ============================

asm
PE_Init_As_Outputs macro ; Send appropriate initialisation bytes for Outputs
L?CALL _PE_INITIALISE_OUTPUTS
endm

PE_Write macro Data, Register ; Write Data to the Port Expander Register
MOVLW Data
MOVWF _DATA_BYTE
MOVLW Data
MOVWF PORTB
MOVLW Register
MOVWF _REGISTER_BYTE
L?CALL _SEND_PE_BYTE
endm
endasm


' ================================================== ============================
' Subs
' ================================================== ============================

PE_INITIALISE_OUTPUTS:

nRST = 0 ' reset the port expander
pause 10
nRST = 1

REGISTER_BYTE = IOCON
DATA_BYTE = %00100000
gosub SEND_PE_BYTE ' setup IOCON for Bank 0 non-sequetial operation

REGISTER_BYTE = IODIRA
DATA_BYTE = $00
gosub SEND_PE_BYTE ' set PORTA as output

REGISTER_BYTE = IODIRB
DATA_BYTE = $00
gosub SEND_PE_BYTE ' set PORTB as output


return

SEND_PE_BYTE:

nCS = 0 ' enable PE
Shiftout SDO, SCLK, 1, [CONTROL_BYTE,REGISTER_BYTE,DATA_BYTE]
nCS = 1 '
pause 10

return

EndOfPortExpander:

The problem I am having is when invoking the PE_WRITE macro. To check what is being passed to the macro I am writing Data to PORTB. When I invoke the following:


@ PE_Write 55h, _GPIOA

I get 55h on PORTB - it works correctly. However when I call the following:



Temp VAR BYTE
Temp = $55
@ PE_Write _Temp, _GPIOA

I get 22h on PORTB. I have tried other numbers for Temp but they all show 22h on PORTB.

I can only think that this is some kind of type mismatch but I don't see how. Any ideas?

Bruce
- 1st May 2010, 22:52
MOVLW 55h moves the literal value of 55h into W.

MOVLW _Temp loads the address of _Temp into W. If you look at the .lst file you'll
see _Temp is located at 22h in RAM.

_Temp is a file register. If you want the value in _Temp in W use MOVF _Temp,W.

Darrel Taylor
- 2nd May 2010, 00:21
Ditto what Bruce said.
But I would add ...

When working at the ASM level, everything is just Numbers.
The assembler doesn't know anything about Byte Word or Long variables.
And it has no way of knowing if you passed it a constant, variable or your birthday.

If you pass a constant, the number is the value of the constant.
Passing a variable, will give the starting address of that variable in RAM.
Passing a Label, will give the address to a piece of code in Flash.
They are all just numbers, and it's up to you to handle them properly.

If you look through PBP's .mac files, you'll see that there is a different macro for each possibility of inputs.

LCDOUT?C ; expects to be passed a constant.
LCDOUT?B ; will work with a byte variable
... the other vars each have their own LCDOUT macro ...

The ?CB suffix indicates the type of input, in PBP they are ...

A = W register (Accumulator)
C = Constant
B = Byte variable
W = Word variable
N = Long variable
T = Bit variable

Placing the suffix there, doesn't do anything by itself, it's just an easy way to recognize which macro you need to use, depending on the type of inputs you have.

With your PE_Write macro, there should be at least 4 versions.
And keeping with the PBP syntax, they might be called ...



; : Data, Register
;-------------------------------------
PE_Write?CC ; Constant, Constant
PE_Write?CB ; Constant, Byte
PE_Write?BC ; Byte, Constant
PE_Write?BB ; Byte, Byte


Fortunately, PBP already has all the macros you need to move the different values around, so you don't really need to do MOVF, MOVWF, etc ... and those macro's will handle all the Banking issues that are difficult to manage with MOVF type instructions.
Those Macro's have the Name of MOVE?, and use the same suffixes shown above.

So the first macro using two constants would look like ...

ASM
PE_Write?CC macro Data, Register
MOVE?CB Data, _DATA_BYTE
MOVE?CB Data, PORTB
MOVE?CB Register, _REGISTER_BYTE
L?CALL _SEND_PE_BYTE
endm


The second macro with a constant Data, and Byte Register


PE_Write?CB macro Data, Register
MOVE?CB Data, _DATA_BYTE
MOVE?CB Data, PORTB
MOVE?BB Register, _REGISTER_BYTE
L?CALL _SEND_PE_BYTE
endm

Note that there is only one character different between the last two code sections (in blue).

The third macro ... Byte Data, Constant register ...


PE_Write?BC macro Data, Register
MOVE?BB Data, _DATA_BYTE
MOVE?BB Data, PORTB
MOVE?CB Register, _REGISTER_BYTE
L?CALL _SEND_PE_BYTE
endm


And the forth ... Byte Data, Byte register ...


PE_Write?BB macro Data, Register
MOVE?BB Data, _DATA_BYTE
MOVE?BB Data, PORTB
MOVE?BB Register, _REGISTER_BYTE
L?CALL _SEND_PE_BYTE
endm
ENDASM


You can probably see that if you consider ALL the possibilities, there's a lot of macros to write for a single function.

To use them, simply choose the macro that fits your inputs...

@ PE_Write?CC 55h, _GPIOA

Temp = $55
@ PE_Write?BC _Temp, _GPIOA

Reg = GPIOA
@ PE_Write?BB _Temp, _Reg


HTH,

awmt102
- 7th May 2010, 15:05
Bruce,

Thanks for the reply, looks like I have fallen foul of the curse of high level languages and forgotten all my assembler! I will have to go and brush up I think!:-D

Darrell,

Thanks also, I had seen the ?CB notation in your LCD Bargraphs but couldn't find any reference to it with google. I have now got my macros working nicely, thankyou.

I am guessing that since "everything is just numbers" there is no clever way to tidy it up and automatically detect what you have passed the macro?

Thanks

Andy