3.3 Functions in mikroC Pro for PIC

In general, it is a good programming practise to write a large complex program as a collection of smaller modules, where each module can be tested independent of the main code. A function can be thought of as a self-contained, testable program code, developed to perform a specific task. Functions are also created when it is required to repeat a certain algorithm at several different places of the main program. For example, it may be required to convert the temperature from °F into °C at several places in a program. Instead of repeating the code, it is more efficient and the program is more maintainable if a temperature conversion code is written in the form of a function. This function can then be called whenever it is required to make the required conversion.

The general format of a function declaration is as follows:

img

Functions usually (not always) perform a certain operation and return data to the calling program. The function type indicates the type of returned data, name is the name of the function, and the parameters (if any) should be separated by commas. The statements inside the function should be enclosed within a pair of curly brackets.

An example function declaration is given below, which calculates the circumference of a circle and returns to the calling program. Here, the radius of the circle is passed as an argument to the function:

img

Assuming that we wish to calculate the circumference of a circle whose radius is 2.5 cm, and store the result in a variable called Circ, the above function can be called, as shown below:

img

Some more examples are given below.

Example 3.8

Write two functions to calculate the area and volume of a cylinder. Show how these functions can be used in a program to calculate the area and volume of a cylinder whose radius and height are 3.0 and 12.5 cm, respectively. Store the area in variable c_area, and the volume in variable c_volume.

Solution 3.8

Figure 3.6 shows the two functions. Function Cyl_Area calculates the area of a cylinder. Similarly, Cyl_Volume calculates the volume of a cylinder.

Figure 3.6 Functions to calculate area and volume of a cylinder

img

The main program calling these functions is shown in Figure 3.7. The radius and height of the cylinder are used as parameters to the functions. The area is stored in variable c_area, and the volume is stored in variable c_volume.

Figure 3.7 Program to calculate the area and volume of a cylinder

img

3.3.1 Function Prototypes

If a function is not defined before it is used in the main program, then the compiler generates an error. This is because the compiler does not know what type of data the function returns and the type of its parameters. One way to avoid error messages is to create a function prototype and declare it at the beginning of the program before the function is called by the main program. A function prototype consists of the type and name of the function, followed by the types of its parameters. An example function prototype declaration is given below:

img

The name of the parameters are optional, and can be avoided as:

img

Figure 3.8 shows how the program shown in Figure 3.7 can be modified to use function prototypes. Here, the function prototypes are declared before the main program, and the two functions are declared after the main program, before they are declared.

Figure 3.8 Program in Figure 3.7 modified to use function prototypes

img

3.3.2 void Functions

A void function is one where the keyword void appears as the function's type specifier, to indicate that the function does not return any value to the calling program. Similarly, a function with no parameters is specified using the keyword void in its parameter list. Such a function is called with no parameters. An example void function is shown below, which simply sets all PORT B output pins to a high state. This function has no parameters and does not return any data:

img

3.3.3 Passing Parameters to Functions

It is important to realise that whenever a function is called with parameters (except an array, which is dealt with in the next section), all the parameters are passed to the function by value. This means that the values of these parameters are copied to the function and used locally by the function. The values of these parameters cannot be modified by the function. A simple example is given in Figure 3.9, to clarify this concept:

Figure 3.9 Passing parameters by value

img

In this example, the value of the function parameter (a) was 5 before calling the function. Inside the function, the local copy of this parameter is incremented to 6, but the value of this parameter is still 5 in the main program. When the function returns, variable b is assigned to value 6.

3.3.4 Passing Arrays to Functions

In some applications, we wish to pass arrays to functions. Passing a single element of an array is easy. All we have to do is index the element that we wish to pass. As described in the previous section, such a variable is passed to a function as a value. For example, to pass index 5 of array MyArray to a function called Sum and store the return value in a, we simply write:

img

Passing a complete array to a function is slightly more complicated. Here, we simply write the name of the array in the calling program. In the function header we have to declare an array of same type followed with a pair of empty brackets. It is important to realise that we are not copying the entire array to the function, but simply passing the address of the first element of the array, which is also equal to the name of the array. Because the address is passed to the function, the array elements are said to be passed by reference. As a result, the original array elements can be modified inside the function. An example is given below, to illustrate the process.

Example 3.9

Write a program to load an integer array called N with values 1 to 10. Then call a function to calculate the sum of the array elements and return the sum to the calling program.

Solution 3.9

The required program listing is given in Figure 3.10. Integer array N is initialised with values 1 to 10 in the main program. Then, function Sum is called and the array is passed to this function. The function calculates the sum of the array elements and returns the sum in variable s in the main program. Notice that the array is called N in the main program, but A in the function.

Figure 3.10 Passing an array to a function

img

3.3.5 Interrupt Processing

mikroC Pro for PIC supports interrupts in user programs. When an interrupt occurs, the processor stops whatever it is doing and jumps to the interrupt service routine (ISR). The PIC18 series of microcontrollers support both low-priority and high-priority interrupts. High-priority interrupts in mikroC Pro for PIC are handled as user functions, where the reserved word interrupt should be used as the function name. An example ISR is shown below:

img

Low-priority interrupts are declared using the keyword interrupt_low:

img

In the PIC18 microcontroller family, the FSR register contents are saved when an interrupt occurs and these registers are restored after returning from the ISR. We can use the following statement to instruct the compiler not to save/restore the register values during an interrupt (except the STATUS, WREG and BSR registers will be saved in high-priority interrupts).

img

Notice that functions can be called from interrupt service routines.

It is also permissible to give any other name to an interrupt service routine, by using the keyword iv. The vector address of the ISR must be declared in such cases. An example is given below, which gives the name MyISR to a high-priority interrupt:

img

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.197.212