PDA

View Full Version : Functions in Pic Basic Pro



bumlife
- 3rd April 2007, 22:37
I wanted to know if it is possible to write function in picbasic. By functions i am referring to the functions that you write in higher level languages like C, where you can pass a value to this function, it performs some operations and then returns a value. i have gone through the pic basic pro manual and i havent found anything that will do this. The closest thing is the gosub routine but gosub doesnt return a value, but other than that i havent found anything else. I want to use functions so that i can make the program more efficient and to save space of the program memory space, and also make debugging easier. The PIC i am using is an 18F2550. So if anyone has any suggestions please let me know.

skimask
- 3rd April 2007, 22:53
I wanted to know if it is possible to write function in picbasic. By functions i am referring to the functions that you write in higher level languages like C, where you can pass a value to this function, it performs some operations and then returns a value. i have gone through the pic basic pro manual and i havent found anything that will do this. The closest thing is the gosub routine but gosub doesnt return a value, but other than that i havent found anything else. I want to use functions so that i can make the program more efficient and to save space of the program memory space, and also make debugging easier. The PIC i am using is an 18F2550. So if anyone has any suggestions please let me know.

"CALL" will get you to an assembly language subroutine, but won't return a value. However, you can access any values defined in PBP (i.e. X) from assembly by prefixing that variable with an underscore (i.e. _x). Therefore, you're able to set X (in PBP) to something, call a sub, work on _X (in assembly), then after returning, you still have X (in PBP). Just don't use X anywhere else. Just pretend you pushed it onto the stack and popped it when you got back.
That's my simplified answer. There's at least 2 (probably a whole lot more) others here on the list that are FAR, FAR more versed in PBP/Assembly interaction than I.
We'll see what they have to say.

mister_e
- 3rd April 2007, 23:34
It's not possible in PBP.. but using MPASM macro you will be able to.

BrianT
- 4th April 2007, 01:08
Not entirely sure I see your problem. You can easily pass values to a subroutine and the subroutine can return new values for the program to act on.

For example, I can set up an array of characters to send and then call a custom built TRANSMIT subroutine. That subroutine might have error checking and require a handshake or acknowledgement from the distant receiver. The results of that acknowledgement or other parameters like time of transmission, etc are stored in variables that are accessible to the main program once the subroutines finishes.

Likewise I can call a RECEIVE subroutine that gets a group of characters and stores them in an array for the main program to use.

If you need speed, and you can handle assembler, then the subroutine can include blocks of assembly language by using the ASM/ENDASM instructions

Darrel Taylor
- 4th April 2007, 02:26
Sure you can use global variables in Subroutines,
And you can get values returned to you from the subroutine,

But what you can't do with PBP, is embed a call to a subroutine (function) and have the result returned into the current formula.

I'm sure what everyone wants is to do something like this.

Function Val(str as String) : as WORD
,,,,
End Function

' And then be able to

MyVar = 100 * Val(MyString) + 10 / 2

Never going to happen with PBP.

There's lots of ways to do the same thing. But the easy way? Nope!
<br>

bumlife
- 4th April 2007, 21:27
Thanks for the help. I was also thinking along the same line as you guys were, to just use global variables to emulate the function operation, but i wanted to make sure. I also have a question about the way to structure a program so that i can use gosub routines and global variables to emulate functions. I am currently working on a RFID entry system, and i am using a HTRC110 reader chip to communicate with the PIC and the transponders. Now to communicate with the reader chip i need to initialize a serial interface,this is the code to get that done

SCLK VAR PORTB.0
DIN VAR PORTB.1
DOUT VAR PORTB.2
LOW DIN
LOW SCLK
HIGH SCLK
HIGH DIN
LOW SCLK
LOW DIN

Now every time i need to send a command to the reader chip i need to send these commands first to initialize the interface and then the necessary command.Using a gousb routine i can modify it so that i can just call this code piece every time i need to use this code. My question is where in the program should i place this routine, should it be at the start of the program or towards the end. If i put it in the beginning this code will run regardless of whether it was called to be run or not. My question is how to code it so that i can optimize it so that the pic is not running code when its not beign used. Also is there a way to execute commands that start in the middle of a program. For example if i have a program that is a 100 lines, is there a way to start the program execution at line 50 instead of line 1? I know that its probably unlikely but i would like to know if there was a way.

I have also attached my current code, so if you guys have any suggestion please let me know, and again thanks for the help

paul borgmeier
- 4th April 2007, 21:59
For your first part – when I have a large program and want to use a function-like appraoch, I do something like this.


' Variables for use inside functions
temp1 var word
temp2 var word
temp3 var word

' for Divide Function
Numerator var temp1
Denominator var temp2
DivAnswer var temp3

' for Square Function
tobesquared var temp1
SqrAnswer var temp2

Main:

' Do lots of stuff here

Numerator = 45
Denominator = 5
Gosub Divide
Serout, Portb.1, 2, (#DivAnswer)

' More stuff here

tobesquared= 9
Gosub Squared
Serout, Portb.1, 2, (#SqrAnswer)

' Do more stuff

Goto Main

' Divide Function
Divide:
DivAnswer = Numerator/Demonimator
Return

' Squared Function
Squared:
SqrAnswer = tobesquared * tobesquared
Return
In this manner, I can use names that make sense but reuse the globals each time.

For your second part try something like this:



...
counter var byte
compare var bit
counter = 0

GOTO Main ' jump over subroutine (to wherever I want, even line 100)
'Init ABIC Suroutine
INTABIC:

LOW DIN
LOW SCLK
HIGH SCLK
HIGH DIN
LOW SCLK
LOW DIN
RETURN

Main:
for counter = 7 to 0 step -1
if config_page_1.0[counter] Then
HIGH DIN
else
LOW DIN
ENdif
HIGH SCLK
LOW SCLK
next counter

GOSUB INITABIC

for counter = 7 to 0 step -1
if config_page_3.0[counter] Then
HIGH DIN
else
LOW DIN
ENdif
HIGH SCLK
LOW SCLK
next counter

GOSUB INITABIC

etc.

GOTO Main
END