Writing PBP Commands/macros


Closed Thread
Results 1 to 6 of 6
  1. #1
    Join Date
    Jul 2009
    Posts
    15

    Default Writing PBP Commands/macros

    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")):

    Code:
    temp = 97
    @    MyFunction     _temp
    However the following does not work and nothing is written to the LCD:

    Code:
    @    MyFunction    97
    Can anyone tell me why this is? I cannot see why there is a difference.

  2. #2
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    Without seeing your function it's hard to tell what's wrong, but it's easy to pass numeric values.

    Try something like this;
    Code:
    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
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  3. #3
    Join Date
    Jul 2009
    Posts
    15


    Did you find this post helpful? Yes | No

    Default

    Hi Bruce, thanks for the reply,

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

    Code:
    ' ==============================================================================
    ' 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:

    Code:
    @   PE_Write 55h, _GPIOA
    I get 55h on PORTB - it works correctly. However when I call the following:

    Code:
    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?

  4. #4
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    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.
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  5. #5
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

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

    Code:
    ;             :   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 ...
    Code:
    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
    Code:
    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 ...
    Code:
    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 ...
    Code:
    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...
    Code:
    @  PE_Write?CC   55h, _GPIOA
    
    Temp = $55
    @  PE_Write?BC   _Temp, _GPIOA
    
    Reg = GPIOA
    @  PE_Write?BB   _Temp, _Reg
    HTH,
    DT

  6. #6
    Join Date
    Jul 2009
    Posts
    15


    Did you find this post helpful? Yes | No

    Default

    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

Members who have read this thread : 2

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts