Файл: Microcontroller based applied digital control (D. Ibrahim, 2006).pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 14.06.2025
Просмотров: 3299
Скачиваний: 1
PRE-PROCESSOR COMMANDS |
101 |
int total = 0; int i;
for(i = 0; i < 10; i++)total = total + a[i]; return(total);
}
and the function can be called from the main program as:
sum(t);
where array t is an integer array with 10 elements, i.e. int t[10].
In the header of the function, a is declared as an array and this is equivalent to declaring it as a pointer, i.e. the above function can also be written as:
int sum(int *a)
{
int total = 0; int i;
for(i = 0; i < 10; i++)total = total + a[i]; return(total);
}
or as
int sum(int *a)
{
int total = 0; int i;
for(i = 0; i < 10; i++)total = total + *(a+i); return(total);
}
4.18 PRE-PROCESSOR COMMANDS
Lines that begin with a ‘#’ character in column 1 of a C program are called pre-processor commands. The C language relies on the pre-processor to extend its power. Some of the commonly used pre-processor commands are described in this section.
4.18.1 #define
This command is used to replace numbers and expressions with symbols. Some examples are given below:
#define |
PI |
3.14159 |
#define |
MAX |
1000 |
#define |
MIN |
0 |
102 PROGRAMMING PIC MICROCONTROLLERS IN C
When these symbols are used in the program their values are substituted to where the symbols are. For example,
if(result > MAX)
is changed by the pre-processor into
if(result > 1000)
#define commands can be complex, such as:
#define |
MULT(a, |
b) |
2*(a |
+ b) |
#define |
SECONDS |
(60* |
60* 24) |
In the last example, the pre-processor will replace every occurrence of SECONDS by the string (60* 60* 24).
Other examples of #define are:
#define |
SQ(x) |
((x) * (x)) |
where SQ(x) will be replaced with ((x) * (x)). For example, SQ(a + b) will be replaced with ((a + b) * (a + b)).
#define can also be used to define macros. A macro is frequently used to replace function calls by in-line code, which is more efficient. An example is given below:
#define MIN(x, y) (((x) < (y)) ? (x): (y))
which compares x and y and if x is less than y, the result is x, otherwise the result is y. After this definition, an expression such as:
k = MIN(u, v);
gets expanded by the pre-processor to:
k = (((u) < (v)) ? (u): (v));
Example 4.3
An integer consists of two bytes. Write a macro to extract the upper and the lower bytes of an integer. Call the upper byte ubyte and the lower byte lbyte.
Solution
We can shift right eight times to extract the upper byte:
#define ubyte(x) |
(unsigned char)(x >> 8) |
The lower byte can be extracted by masking the integer with hexadecimal number 0xFF.
#define lbyte(x) |
(unsigned char)(x & 0xff) |
Notice that because the x is an integer, the result is converted into a character by preceding it with ‘(unsigned char)’. This is called casting in C.
Example 4.4
Write a macro to set or clear a bit of a variable.
PRE-PROCESSOR COMMANDS |
103 |
Solution
If we name the macro to set a bit as bit set,
#define bit set(var, bitno) ((var) = (1 (bitno)))
and the macro to clear a bit as bit reset,
#define bit reset(var, bitno) ((var) &= (1 (bitno)))
we can now set bit 3 of the variable x to 1 with the following statement:
bit set(x, 3);
Similarly, bit 6 of the variable q can be cleared to 0 with the following statement:
bit set(q, 6);
4.18.2 #include
This command causes the pre-processor to replace the line with a copy of the contents of the named file. For example,
#include <myproject.h>
or
#include ‘myproject.h’
causes the contents of file myproject.h to be included at the line where the command is issued. When developing programs with the PICC Lite compiler, the following line must be included
at the beginning of all programs:
#include <pic.h>
The file pic.h includes all the PIC microcontroller register definitions.
4.18.3 #asm and #endasm
These pre-processor commands are used to include assembler instructions in C programs. The
#asm command identifies the beginning of the assembly code, and #endasm identifies the end of the assembly code. For example,
...
...
i = 10;
#asm
movlw 10h
#endasm
...
...
104 PROGRAMMING PIC MICROCONTROLLERS IN C
4.19 ACCESSING THE EEPROM MEMORY
Some PIC microcontrollers (e.g. PIC16F84) have EEPROM memories which can be used to store nonvolatile data. PICC Lite provides instructions for reading and writing to this memory. The EEPROM WRITE command is used to write a data byte to the EEPROM memory. For example, the following command writes 0x2E to address 2 of the EEPROM memory:
EEPROM WRITE(2,0 × 2E);
Similarly, the EEPROM READ command is used to read a data byte from the EEPROM memory. For example, the following command reads a byte from address 5 of the EEPROM memory and loads it into the variable k:
k = EEPROM READ(5);
4.20 INTERUPTS IN C PROGRAMS
Interrupts are very important in real-time programs. Most PIC microcontrollers offer internal and external interrupt facilities. Internal interrupts are usually timer-generated interrupts, while the external interrupts are triggered by activities on the I/O pins. When an interrupt occurs the processor jumps to the interrupt service routine where the interrupt is serviced. Medium-range microcontrollers (such as the PIC16F84) have only one ISR, which is at address 0x04 of the program memory. If interrupts from multiple sources are expected then the interrupting device can be found by inspecting the INTCON register bits.
Interrupts can be used in PICC Lite programs in the form of special functions. When an interrupt occurs the program jumps to this special function where the interrupt is handled. ISR function must have the name interrupt followed by a user-selected function name, and the function must not return any value and must not have any arguments. For example, an ISR function named my int is given below:
void interrupt my int(void)
{
statement;
statement;
...
statement;
}
Interrupts must be enabled before they can be recognized by the microcontroller. The ei() and di() instructions enable and disable global interrupts, respectively. Additionally, the interrupt control bit of each interrupt source must be enabled in the appropriate SFR register (e.g. T0IE bit in INTCON must be set to 1 to enable timer interrupts).
The PIC microcontroller only saves the program counter on stack when an interrupt occurs. The PICC Lite compiler determines which registers and objects are used by the interrupt function and saves these appropriately.
STRUCTURE OF A C PROGRAM |
105 |
4.21 DELAYS IN C PROGRAMS
There are many real-time applications where the microcontroller is too fast and we need to slow it down to see, for example, the flashing of an LED. The PICC Lite compiler offers two types of delay functions: a microsecond delay function, and a millisecond delay function. The file
DelayUs(200);
Similarly, function DelayMs(x) is used to create delays in the range 1 to 255 ms. The following function call creates a 10 ms delay:
DelayMs(10);
Longer delays can be created by using the above delay functions in loops. These delay functions are by default based on the assumption that the microcontroller operates with a 4 MHz clock frequency. If the clock rate is different, then the new clock rate must be specified at the beginning of the program. For example, if the clock rate is 2 MHz, then the following lines must be included at the beginning of the program:
#undef XTAL FREQ #define XTAL FREQ 2MHZ
4.22 STRUCTURE OF A C PROGRAM
The simplest C program consists of three lines:
main(void)
{
}
main is the starting point of the main program and the statements of the main program are written inside a pair of curly brackets.
A more useful program which calculates the average of three numbers 5, 7 and 9 is given below:
main(void)
{
float average;
average = (5 + 7 + 9)/3;
}
It is always a good practice to include comments in programs to describe the operation of the various parts of the program. Comment lines should also be included at the beginning of a program to describe the aim of the program, the author, filename, date, and any modifications.
106 PROGRAMMING PIC MICROCONTROLLERS IN C
Also, the file
// |
********************************************************** |
// |
|
// |
AVERAGE PROGRAM |
// |
================== |
// |
//Author: D. Ibrahim
//Date: February 2005
//File: AVERAGE.C
//This program calculates the average of three numbers 3, 5, and 9
//**********************************************************
#include <pic.h>
//Main Program
//************
//
main(void)
{
float average;
average = (3 + 5 + 9)/3;
}
When functions are used in programs, they should normally be included before the main program. An example is given below.
Example 4.5
Write a program to calculate the square of a number. The square should be calculated using a function.
Solution
// |
********************************************************** |
// |
|
// |
SQUARE PROGRAM |
// |
================ |
// |
//Author: D. Ibrahim
//Date: February 2005
//File: SQUARE.C
//This program calculates the square of an integer number
//**********************************************************
#include <pic.h>
//Functions
PIC MICROCONTROLLER INPUT–OUTPUT INTERFACE |
107 |
// ********
int square of number(int x)
{
int k;
k = x * x; return(k);
}
//Main Program
//************
main(void)
{
int p, z;
p = 5;
z = square of number(p);
}
4.23 PIC MICROCONTROLLER INPUT–OUTPUT INTERFACE
A microcontroller communicates with the outside world using its input–output ports. These ports can be analog or digital. Analog ports are used to read data from analog devices, e.g. the voltage across a resistor. Digital ports are used to read data from digital devices, e.g. the state of a switch. Microcontroller outputs are usually connected to LEDs, LCDs, buzzers, sevensegment displays and similar devices. The input can be a push-button switch, a keyboard or a similar device.
PIC microcontroller output ports can source and sink 25 mA of current. When an output port is sourcing current, the current flows out of the port pin. Similarly, when an output port is sinking current, the current flows towards the output pin. Devices such as LEDs, LCDs and other small devices which operate with up to 25 mA can be connected to the microcontroller output ports. Devices which require larger currents can be connected to the microcontroller ports by using a transistor switch to increase the current capability of the port pin.
4.23.1 Connecting an LED
Most LEDs operate with about 2V and they draw about 10 mA from the power supply. An LED can be connected to the output port of the PIC microcontroller by using a series current limiting resistor, as shown in Figure 4.3.
Assuming the output voltage Vo of the port pin is +5 V when it is at logic 1, the value of the resistor can be calculated as
R |
= |
Vo − 2 |
= |
5V − 2V |
≈ |
330 . |
|
10 m A |
10 m A |
||||||
Example 4.6
An LED is connected to bit 0 of port B (i.e. pin RB0) of a PIC16F84 microcontroller. Write a program to flash the LED at 100 ms intervals. The hardware set-up is shown in Figure 4.4, where the microcontroller is operated with a 4 MHz crystal.
108 PROGRAMMING PIC MICROCONTROLLERS IN C
2V
Vo |
R |
Output port
LED 10mA
PIC
Microcontroller
Figure 4.3 Connecting an LED
+5V |
||||
14 |
||||
4.7K |
VDD |
6 |
330 |
|
RB0 |
||||
4 |
MCLR |
|||
LED |
||||
PIC 16F84
Vss |
5 |
||
OSC1 |
OSC2 |
||
16 |
15 |
||
C |
C |
||
1 |
4MHZ |
2 |
|
22pF |
22pF |
||
Figure 4.4 Hardware setup for the Example 4.6
Solution
The required program is given in Figure 4.5. At the beginning of the program port B is configured as an output port. The LED is then turned on by sending a logic 1 to the port pin (RB0 = 1). After 100 ms delay the LED is turned off (RB = 0) and this cycle is repeated forever.