ESD Ch3
ESD Ch3
1
I HC QUC GIA TP.H CH MINH
TRNG I HC BCH KHOA
KHOA IN-IN T
B MN K THUT IN T
11
Embedded System Design
Chapter 3: C Programming for PIC
Microcontroller
B mn K Thut in T - HBK
References
Textbook
Martin Bates, Programming 8-bit PIC Microcontrollers in
C, Newnes, 2008
Many C compilers for PIC:
MikroC (www.mikroe.com)
PICC18 (www.htsoft.com)
MPLAB C18, C30 (www.microchip.com)
CCS C (www.microchipc.com/reviews/CCS_C/)
2
3/12/2012
2
B mn K Thut in T - HBK
Outline
2.1 PIC16 C Getting Started
Simple program and test circuit
Variables, looping, and decisions
SIREN program
2.2 PIC16 C Program Basics
Variables
Looping
Decisions
2.3 PIC16 C Data Operations
Variable types
Floating point numbers
Characters
Assignment operators
2.4 PIC16 C Sequence Control
While loops
Break, continue, goto
If, else, switch
2.5 PIC16 C Functions and Structure
Program structure
Functions, arguments
Global and local variables
2.6 PIC16 C Input and Output
RS232 serial data
Serial LCD
Calculator and keypad
2.7 PIC16 C More Data Types
Arrays and strings
Pointers and indirect addressing
Enumeration
3
B mn K Thut in T - HBK
2.1 PIC16 C Getting Started
Microcontroller programs contain three main features:
Sequences of instructions
Conditional repetition of sequences
Selection of alternative sequences
Listing 2.1 A program to output a binary code
/* Source code file: OUTNUM.C
Author, date, version: MPB 11-7-07 V1.0
Program function: Outputs an 8-bit code
Simulation circuit: OUTBYTE.DSN
*******************************************************/
#include "16F877A.h" // MCU select
void main() // Main block
{
output_D(255); // Switch on outputs
}
4
3/12/2012
3
B mn K Thut in T - HBK
Figure 2.1 MPLAB IDE Screenshot
5
B mn K Thut in T - HBK
Figure 2.2 ISIS dialogue to attach program
6
3/12/2012
4
B mn K Thut in T - HBK
Setup IO Ports
Port modes
#use fast_io(port): leaves the state of the port the same unless re-
configured
#use fixed_io(port_outputs=pin, pin): permanently sets up the data
direction register for the port
#use standard_io(port): default for configuring the port every time its used
Set directions
set_tris_a(value);
value = get_tris_a();
Read / write IO ports
value = input_A();
output_A(value);
output_high(pin); //set an output to logic 1
output_low(pin); //set an output to logic 0
7
B mn K Thut in T - HBK
PIC16 C Program Basics
Variables
Looping
Decisions
The purpose of an embedded program is
to read in data or control inputs,
to process them and operate the outputs as required.
The program for processing the data usually contains repetitive loops
and conditional branching, which depends on an input or calculated
value.
2.2 PIC16 C Program Basics
8
3/12/2012
5
B mn K Thut in T - HBK
Variables
Variables:
is a label attached to the memory location where the variable value is
stored.
automatically assigned to the next available location or locations (many
variable types need more than 1 byte of memory).
must be declared at the start of the program block, so that the compiler
can allocate a corresponding set of locations.
Only alphanumeric characters (az, AZ, 09) can be used for variable
names
Variable values
in decimal by default
in hexadecimal with the prefix 0x, for example, 0xFF
By default, the CCS compiler is not case sensitive,
9
B mn K Thut in T - HBK
Listing 2.2 Variables
/* Source code file: VARI.C
Author, date, version: MPB 11-7-07 V1.0
Program function: Outputs an 8-bit variable
Simulation circuit: OUTBYTE.DSN
*******************************************************/
#include "16F877A.h"
void main()
{
int x; // Declare variable and type
x=99; // Assign variable value
output_D(x); // Display the value in binary
}
10
3/12/2012
6
B mn K Thut in T - HBK
Looping
Most real-time applications need to execute continuously until the
processor is turned off or reset.
In C this can be implemented as a while loop, as in Listing 2.3 .
/* Source code file: ENDLESS.C
Author, date, version: MPB 11-7-07 V1.0
Program function: Outputs variable count
Simulation circuit: OUTBYTE.DSN
*******************************************************/
#include "16F877A.h
void main()
{
int x; // Declare variable
while(1) // Loop endlessly
{ output_D(x); // Display value
x++; // Increment value
}
}
11
B mn K Thut in T - HBK
Decision Making
The effect of the program
is to switch on the output if
the input is high.
The switch needs to be
closed before running to
see this effect.
The LED cannot be
switched off again until the
program is restarted.
The simplest way to illustrate basic decision making is to change an output
depending on the state of an input.
Figure 2.4 show test circuit with input switch
12
3/12/2012
7
B mn K Thut in T - HBK
Listing 2.4 IF statement
/* Source code file: IFIN.C
Author, date, version: MPB 11-7-07 V1.0
Program function: Tests an input
Simulation circuit: INBIT.DSN
*******************************************************/
#include "16F877A.h"
void main()
{
int x; // Declare test var.
output_D(0); // Clear all outputs
while(1) // Loop always
{
x = input(PIN_C0); // Get input
if(x==1)output_high(PIN_D0); // Change out
}
}
13
B mn K Thut in T - HBK
Loop Control
The program can be simplified by combining the input function
with the condition statement as follows:
if (input(PIN_C0)) output_high(PIN_D0);
The conditional sequence can also be selected by a while
condition.
In Program WHILOOP.C ( Listing 2.5 )
the input is tested in the loop condition statement and the output flashed on
and off while the switch is open (input high).
If the switch is closed, the flash loop is not executed and the LED is switched off.
14
3/12/2012
8
B mn K Thut in T - HBK
Listing 2.5 Conditional loop
/* Source code file: WHILOOP.C
Author, date, version: MPB 11-7-07 V1.0
Program function: Input controls output loop
Simulation circuit: INBIT.DSN
*******************************************************/
#include "16F877A.h"
#use delay (clock=1000000) // MCU clock = 1MHz
void main(){
while(1)
{
while(input(PIN_C0)); // Repeat while switch open
{ output_high(PIN_D0);
delay_ms(300); // Delay 0.3s
output_low(PIN_D0);
delay_ms(500); // Delay 0.5s
}
output_low(PIN_D0); // Switch off LED
}
}
15
B mn K Thut in T - HBK
FOR Loop
The WHILE loop repeats until some external event or internally
modified value satisfies the test condition.
In other cases, we need a loop to repeat a fixed number of
times.
The FOR loop uses a loop control variable, which is set to an
initial value and modified for each iteration while a defined
condition is true.
In the demo program FORLOOP.C ( Listing 2.6 ), the loop control
parameters are given within the parentheses that follow the for
keyword.
16
3/12/2012
9
B mn K Thut in T - HBK
FOR Loop
17
B mn K Thut in T - HBK
SIREN Program
A program combining some of these basic features is shown in
SIREN.C ( Listing 2.7 ).
This program outputs to a sounder rather than an LED,
operating at a higher frequency.
The output is generated when the switch is closed (input C0
low).
The delay picks up the incrementing value of step giving a
longer pulse each time the for loop is executed.
This causes a burst of 255 pulses of increasing length (reducing
frequency), repeating while the input is on.
Note that 255 is the maximum value allowed for step, as it is
an 8-bit variable.
18
3/12/2012
10
B mn K Thut in T - HBK
Listing 2.7 Siren Program
/* Source code file: SIREN.C
Author, date, version: MPB 11-7-07 V1.0
Program function: Outputs a siren sound
Simulation circuit: INBIT.DSN
*******************************************************/
#include "16F877A.h"
#use delay (clock=1000000)
void main()
{
int step;
while(1)
{
while(!input(PIN_C0)) // loop while switch ON
{
for(step=0;step<255;step++) // Loop control
{
output_high(PIN_D0); // Sound sequence
delay_us(step);
output_low(PIN_D0);
delay_us(step);
}
}
}
}
19
B mn K Thut in T - HBK
Listing 2.8 Program Blank
/* Source Code Filename:
Author/Date/Version:
Program Description:
Hardware/simulation:
************************************************************/
#include "16F877A.h" // Specify PIC MCU
#use // Include library routines
void main() // Start main block
{
int // Declare global variables
while(1) // Start control loop
{
// Program statements
}
} // End main block
20
3/12/2012
11
B mn K Thut in T - HBK
Blank Program
A blank program is shown in Listing 2.8 , which could be used
as a general template.
We should try to be consistent in the header comment
information, so a standard comment block is suggested.
Compiler directives are preceded by hash marks and placed
before the main block.
Other initialization statements should precede the start of the
main control loop. Inclusion of the unconditional loop option
while(1) assumes that the system will run continuously until
reset.
21
B mn K Thut in T - HBK
Table 2.1 A basic set of CCS C components
Compiler Directives
#include source files Include another source code or header file
#use functions(parameters) Include library functions
C Blocks
main(condition) {statements } Main program block
while(condition) {statements } Conditional loop
if(condition) {statements } Conditional sequence
for(condition) {statements } Preset loop
C Functions
delay_ms(nnn) Delay in milliseconds
delay_us(nnn) Delay in microseconds
output_x(n) Output 8-bit code at Port X
output_high(PIN_nn) Set output bit high
output_low(PIN_nn) Set output bit low
input(PIN_nn) Get input
22
3/12/2012
12
B mn K Thut in T - HBK
Variable types
Floating point numbers
Characters
Assignment operators
A main function of any computer program is to carry out calculations
and other forms of data processing. Data structures are made up of
different types of numerical and character variables, and a range of
arithmetical and logical operations are needed.
Microcontroller programs do not generally need to process large
volumes of data, but processing speed is often important.
2.3 PIC16 C Data Operations
23
B mn K Thut in T - HBK
Table 2.1 Integer Variables
Name Type Min Max
int1 1 bit 0 1
unsigned int8 8 bits 0 255
signed int8 8 bits -127 +127
unsigned int16 16 bits 0 65525
signed int16 16 bits -32767 +32767
unsigned int32 32 bits 0 4294967295
signed int32 32 bits -2147483647 +2147483647
24
3/12/2012
13
B mn K Thut in T - HBK
Table 2.2 Microchip/CCS Floating Point Number Format
Exponent Sign Mantissa
xxxx xxxx x xxx xxxx xxxx xxxx xxxx xxxx
8 bits 1 23 bits
Table 2.4 Example of 32-bit floating point number conversion
Mantissa: 101 0010 0000 0000 0000
0000
Exponent: 1000 0011
Sign: 1 = negative number
FP number: 1000 0011 1101 0010 0000 0000 0000
0000
25
B mn K Thut in T - HBK
Figure 2.5 Variable Types
26
3/12/2012
14
B mn K Thut in T - HBK
Table 2.5 ASCII Codes
Low
Bits
High Bits
0010 0011 0100 0101 0110 0111
0000 Spac
e
0 @ P ` p
0001 ! 1 A Q a q
0010 " 2 B R b r
0011 # 3 C S c s
0100 $ 4 D T d t
0101 % 5 E U e u
0110 & 6 F V f v
0111 ' 7 G W g w
1000 ( 8 H X h x
1001 ) 9 I Y i y
1010 * : J Z j z
1011 + ; K [ k {
1100 , < L \ l |
1101 - = M ] m }
1110 . > N ^ n ~
1111 / ? O _ o Del
27
B mn K Thut in T - HBK
Table 2.6 Arithmetic and Logical Operations
OPERATION OPERATOR DESCRIPTION SOURCE CODE EXAMPLE RESULT
Single operand
Increment ++ Add one
to integer
result = num1++; 0000 0000 0000
0001
Decrement -- Subtract one
from integer
result = num1--; 1111 1111 1111
1110
Complement ~ Invert all bits
of integer
result = ~num1; 0000 0000 1111
1111
Arithmetic Operation
Add + Integer or
Float
result =
num1 + num2;
0000 1010
+ 0000 0011
0000
1101
Subtract - Integer or
Float
result =
num1 - num2;
0000 1010
- 0000 0011
0000
0111
Multiply * Integer or
Float
result =
num1 * num2;
0000 1010
* 0000 0011
0001
1110
Divide / Integer or
Float
result =
num1 / num2;
0000 1100
/ 0000 0011
0000
0100
Logical Operation
Logical AND & Integer
Bitwise
result =
num1 & num2;
1001 0011
& 0111 0001
0001
0001
Logical OR | Integer
Bitwise
result =
num1 | num2;
1001 0011
| 0111 0001
1111
0011
Exclusive OR ^ Integer
Bitwise
result =
num1 ^ num2;
1001 0011
^ 0111 0001
1110
0010
28
3/12/2012
15
B mn K Thut in T - HBK
Figure 2.6 Variable Operations
29
B mn K Thut in T - HBK
Table 2.7 Conditional Operators
Operation
Symbol
EXAMPLE
Equal to == if(a == 0) b=b+5;
Not equal to != if(a != 1) b=b+4;
Greater than > if(a > 2) b=b+3;
Less than < if(a < 3) b=b+2;
Greater than or equal to >= if(a >= 4) b=b+1;
Less than or equal to <= if(a <= 5) b=b+0;
30
3/12/2012
16
B mn K Thut in T - HBK
2.4 PIC16 C Sequence Control
While loops
Break, continue, goto
If, else, switch
Conditional branching operations are a basic feature of any
program.
These must be properly organized so that the program
structure is maintained and confusion avoided.
The program then is easy to understand and more readily
modified and upgraded.
31
B mn K Thut in T - HBK
While Loops
The basic while(condition) provides a logical test at the start of
a loop, and the statement block is executed only if the
condition is true.
It may, however, be desirable that the loop block be executed
at least once, particularly if the test condition is affected
within the loop.
This option is provided by the do..while(condition) syntax. The
difference between these alternatives is illustrated in Figure
2.7 .
32
3/12/2012
17
B mn K Thut in T - HBK
Condition
True?
Statement
Block
Condition
True?
Statement
Block
(a) While loop
(b) Do..While loop
Figure 2.3.1 Comparison of While and Do..While Loop
33
B mn K Thut in T - HBK
Listing 2.9 DOWHILE.C contains both types of while loop
// DOWHILE.C
// Comparison of WHILE and DO WHILE loops
#include "16F877A.H
main()
{
int outbyte1=0;
int outbyte2=0;
int count;
count=0; // This loop is not
while (count!=0) // executed
{ output_C(outbyte1);
outbyte1++;
count--;
}
count=0; // This loop is
do // executed
{ output_C(outbyte2);
outbyte2++;
count--;
} while (count!=0);
while(1){};
}
34
3/12/2012
18
B mn K Thut in T - HBK
Break, Continue, and Goto
Break and continue
It may sometimes be necessary to break the execution of a loop or
block in the middle of its sequence.
The block must be exited in an orderly way, and it is useful to have the
option of restarting the block (continue) or proceeding to the next one
(break).
Goto
Occasionally, an unconditional jump may be needed, but this should
be regarded as a last resort, as it tends to threaten the program
stability.
It is achieved by assigning a label to the jump destination and
executing a goto..label.
35
B mn K Thut in T - HBK
label
Statement
Block
Continue
Goto
Break
Figure 2.8 Break, continue and goto
36
3/12/2012
19
B mn K Thut in T - HBK
Listing 2.10 Continue, Break & Goto
// CONTINUE.C
// Continue, break and goto jumps
#include "16F877A.H"
#use delay(clock=4000000)
main()
{
int outbyte;
again: outbyte=0; // Goto destination
while(1)
{
output_C(outbyte); // Loop operation
delay_ms(10);
outbyte++;
if (!input(PIN_D0)) continue; // Restart loop
if (!input(PIN_D1)) break; // Terminate loop
delay_ms(100);
if (outbyte==100) goto again; // Unconditional jump
}
}
37
B mn K Thut in T - HBK
Figure 2.9 Comparison of If and If..Else
If
block
Condition
True?
YES
NO
Condition
True?
If
block
Else
block
YES NO
If..Else and Switch..Case
If .. Else: allows a block to be executed or skipped conditionally.
Switch..case : When we need a multi-choice selection
38
3/12/2012
20
B mn K Thut in T - HBK
Test Variable
Value = 3?
Procedure 3 YES
NO
Value = n?
Procedure n YES
NO
Default
Procedure
Value = 2?
Procedure 2 YES
NO
Value = 1?
Procedure 1 YES
NO
Figure 2.10 Switch..case branching structure
39
B mn K Thut in T - HBK
Listing 2.11 Comparison of Switch and If..Else control
// SWITCH.C
// Switch and if..else sequence control
// Same result from both sequences
#include "16F877A.h
void main()
{
int8 inbits;
while(1) {
inbits = input_D(); // Read input byte
// Switch..case option........................
switch(inbits) // Test input byte
{
case 1: output_C(1); // Input = 0x01,output = 0x01
break; // Quit block
case 2: output_C(3); // Input = 0x02,output = 0x03
break; // Quit block
case 3: output_C(7); // Input = 0x03,output = 0x07
break; // Quit block
default:output_C(0); // If none of these,output= 0x00
}
40
3/12/2012
21
B mn K Thut in T - HBK
Listing 2.11 Comparison of Switch and If..Else control
// If..else
option................................................
if (input(PIN_D0)) output_C(1);// Input RD0 high
if (input(PIN_D1)) output_C(2);// Input RD1 high
if (input(PIN_D0) && input(PIN_D1)) output_C(7);
// Both high
else output_C(0); // If none of these,
// output = 0x00
}
}
41
B mn K Thut in T - HBK
Assignments
1. Write a C function to convert a BCD code to a
common-anode 7-segment LED code
2. Write a C program to read 8-bit value from Port B,
then add 5 to them and output the result to Port D.
3. Write a C statement to convert numbers 0 to 9 to
their ASCII hex code.
4. Write a function to detect a button press and
button release with de-bouncing ability
5. Write a C program to create a chasing LED effect
with 8 single LEDs at port D.
42
3/12/2012
22
B mn K Thut in T - HBK
2.5 PIC16 C Functions and Structures
Program structure
Functions, arguments
Global and local variables
The structure of a C program is created using functions. This is a block of code written
and executed as a self-contained process, receiving the required parameters (data
to be processed) from the calling function and returning results to it. Main() is the
primary function in all C programs, within which the rest of the program is
constructed.
When running on a PC, main() is called by the operating system, and control is
returned to the OS when the C program is terminated. In the microcontroller,
main() is simply used to indicate the start of the main control sequence, and more
care needs to be taken in terminating the program.
Normally, the program runs in a continuous loop, but if not, the final statement should
be while(1);, which causes the program to wait and prevents the program running
into undefined locations following the application code.
43
B mn K Thut in T - HBK
Figure 2.11 Hierarchical C program structure
Main()
{
statements
fun1()
statements
statements
....
....
....
....
statements
fun2(arg)
statements
}
void fun1()
{
statements
...
...
}
void fun2(arg)
{
statements
...
fun3
...
return(val)
}
void fun3
{
statements
...
...
}
LEVEL 0 LEVEL 1 LEVEL 2
44
3/12/2012
23
B mn K Thut in T - HBK
Basic Functions
A simple program using a function is shown in FUNC1.C, Listing 2.12 . The
main block is very short, consisting of the function call out() and a while
statement, which provides the wait state at the end of main(). In this case,
the variables are declared before the main block. This makes them global
in scope; that is, they are recognized throughout the whole program and
within all function blocks. The function out() is also defined before main() ,
so that, when it is called, the function name is recognized. The function
starts with the keyword void , which indicates that no value is returned by
the function. The significance of this is explained shortly.
The function itself simply increments Port C from 0 to 255. It contains a for
loop to provide a delay, so that the output count is visible. This is a simple
alternative to the built-in delay functions seen in previous examples and is
used here to avoid the inclusion of such functions while we study user-
defined functions. It simply counts up to a preset
value to waste time. The delay time is controlled by this set value.
45
B mn K Thut in T - HBK
Listing 2.12 Basic function call
// FUNC1.C
// Function call structure
#include "16F877A.H
int8 outbyte=1;
int16 n;
void out() // Start of function block
{
while (outbyte!=0) // Start loop, quit when output =0
{
output_C(outbyte); // Output code 1 0xFF
outbyte++; // Increment output
for(n=1;n<500;n++);// Delay so output is visible
}
}
main()
{
out(); // Function call
while(1); // Wait until reset
}
46
3/12/2012
24
B mn K Thut in T - HBK
Global and Local Variables
Now, assume that we wish to pass a value to the function for local use (that is,
within the function). The simplest way is to define it as a global variable, which
makes it available throughout the program. In program FUNC2.C, Listing 2.13 , the
variable count, holding the delay count, hence the delay time, is global.
If there is no significant restriction on program memory, global variables may be
used. However, microcontrollers, by definition, have limited memory, so it is
desirable to use local variables whenever possible within the user functions. This is
because local variables exist only during function execution, and the locations used
for them are freed up on completion of function call. This can be confirmed by
watching the values of C program variables when the program is executed in
simulation mode the local ones become undefined once the relevant function
block is terminated.
If only global variables are used and the functions do not return results to the
calling block, they become procedures. Program FUNC3.C, Listing 2.14 , shows how
local variables are used.
47
B mn K Thut in T - HBK
Listing 2.13 Passing a parameter to the function
// FUNC2.C
#include "16F877A.H
int8 outbyte=1; // Declare global variables
int16 n, count;
void out() // Function block
{
while (outbyte!=0)
{ output_C(outbyte);
outbyte++;
for(n=1;n<count;n++);
}
}
main()
{
count=2000;
out(); // Call function
while(1);
}
48
3/12/2012
25
B mn K Thut in T - HBK
Listing 2.14 Local variables
// FUNC3.C
// Use of local variables
#include "16F877A.H
int8 outbyte=1; // Declare global variables
int16 count;
int out(int16 t) // Declare argument types
{
int16 n; // Declare local variable
while (input(PIN_D0)) // Run output at speed t
{ outbyte++;
for(n=1;n<t;n++);
}
return outbyte; // Return output when loop stops
}
main()
{
count=50000;
out(count); // Pass count value to function
output_C(outbyte); // Display returned value
while(1);
}
49
B mn K Thut in T - HBK
2.6 PIC16 C Input and Output
RS232 serial data
Serial LCD
Calculator and keypad
If an electronic gadget has a small alphanumeric LCD, the chances are that it
is a microcontroller application. Smart card terminals, mobile phones,
audio systems, coffee machines, and many other small systems use this
display. The LCD we use here has a standard serial interface, and only one
signal connection is needed. The signal format is RS232, a simple low-
speed protocol that allows 1 byte or character code to be sent at a time.
The data sequence also includes start and stop bits, and simple error
checking can be applied if required. The PIC 16F877, in common with
many microcontrollers, has a hardware RS232 port built in.
50
3/12/2012
26
B mn K Thut in T - HBK
Serial LCD
CCS C provides an RS232 driver routine that works with any
I/O pin (that is, the hardware port need not be used).
This is possible because the process for generating the RS232
data frame is not too complex and can be completed fast
enough to generate the signal in real time.
At the standard rate of 9600 baud, each bit is about 100 s
long, giving an overall frame time of about 1 ms.
The data can be an 8-bit integer or, more often, a 7-bit ASCII
character code.
51
B mn K Thut in T - HBK
Serial LCD
52
3/12/2012
27
B mn K Thut in T - HBK
Serial LCD
Control Codes
53
B mn K Thut in T - HBK
Serial LCD
Format Codes
54
3/12/2012
28
B mn K Thut in T - HBK
Example
55
B mn K Thut in T - HBK
2.7 PIC16 C More Data Types
Arrays and strings
Pointers and indirect addressing
Enumeration
The data in a C program may be most conveniently handled as
sets of associated variables. These occur more frequently as
the program data becomes more complex, but only the basics
are mentioned here.
56
3/12/2012
29
57
B mn K Thut in T - HBK
2.8 PIC16 C Compiler Directives
Include and use directives
Header file listing and directives
Compiler directives are typically used at the top of the program to set up
compiler options, control project components, define constant labels, and
so on before the main program is created. They are preceded by the hash
symbol to distinguish them from other types of statements and do not
have a semicolon to end the line.
58
3/12/2012
30
59
60
3/12/2012
31
61
62
3/12/2012
32
63
64
3/12/2012
33
65