C Embededed 01
C Embededed 01
C Embededed 01
Pont, 2002-2003
Embedded This document may be freely distributed and copied, provided that copyright notice at
the foot of each OHP page is clearly visible in all copies.
Systems I
A 10-week course, using C
Michael J. Pont
University of Leicester
17
16
15
14
13
12
11
20
19
18
10
2
1
7
6
5
3
9
8
VSS
XTL1
XTL2
P3.7
P3.6
P3.5
P3.4
P3.3
P3.2
P3.1
P3.0
RST
P1.7
P1.6
P1.5
P1.4
P1.3
P1.2
P1.1
P1.0
‘8051’
/ PSEN
P0.0
VCC
P2.0
P2.1
P2.2
P2.3
P2.4
P2.5
P2.6
P2.7
P0.7
P0.6
P0.5
P0.4
P0.3
P0.2
P0.1
ALE
/ EA
34
37
38
39
24
25
28
30
35
36
40
26
27
29
31
32
33
21
22
23
[v1.2]
I II
Seminar 1: “Hello, Embedded World” 1 Seminar 2: Basic hardware foundations (resets, oscillators and port I/O) 21
Overview of this seminar 2 Review: The 8051 microcontroller 22
Overview of this course 3 Review: Central-heating controller 23
By the end of the course … 4 Overview of this seminar 24
Main course textbook 5 Oscillator Hardware 25
Why use C? 6 How to connect a crystal to a microcontroller 27
Pre-requisites! 7 Oscillator frequency and machine cycle period 28
The 8051 microcontroller 8 Keep the clock frequency as low as possible 29
The “super loop” software architecture 9 Stability issues 30
Strengths and weaknesseses of “super loops” 10 Improving the stability of a crystal oscillator 31
Example: Central-heating controller 11 Overall strengths and weaknesses 32
Reading from (and writing to) port pins 12 Reset Hardware 34
SFRs and ports 13 More robust reset circuits 35
SFRs and ports 14 Driving DC Loads 36
Creating and using sbit variables 15 Use of pull-up resistors 38
Example: Reading and writing bytes 16 Driving a low-power load without using a buffer 39
Creating “software delays” 17 Using an IC Buffer 40
Using the performance analyzer to test software delays 18 Example: Buffering three LEDs with a 74HC04 41
Strengths and weaknesses of software-only delays 19 What is a multi-segment LED? 42
Preparation for the next seminar 20 Driving a single digit 43
Preparation for the next seminar 44
III IV
Seminar 3: Reading Switches 45 Seminar 4: Adding Structure to Your Code 77
Introduction 46 Introduction 78
Review: Basic techniques for reading from port pins 47 Object-Oriented Programming with C 79
Example: Reading and writing bytes (review) 48 Example of “O-O C” 82
Example: Reading and writing bits (simple version) 49 The Project Header (Main.H) 85
Example: Reading and writing bits (generic version) 51 The Port Header (Port.H) 92
The need for pull-up resistors 56 Re-structuring a “Hello World” example 96
The need for pull-up resistors 57 Example: Re-structuring the Goat-Counting Example 104
The need for pull-up resistors 58 Preparation for the next seminar 114
Dealing with switch bounce 59
Example: Reading switch inputs (basic code) 61
Example: Counting goats 68
Conclusions 74
Preparation for the next seminar 75
V VI
Seminar 5: Meeting Real-Time Constraints 115 Seminar 6: Creating an Embedded Operating System 139
Introduction 116 Introduction 140
Creating “hardware delays” 118 Timer-based interrupts (the core of an embedded OS) 144
The TCON SFR 119 The interrupt service routine (ISR) 145
The TMOD SFR 120 Automatic timer reloads 146
Two further registers 121 Introducing sEOS 147
Example: Generating a precise 50 ms delay 122 Introducing sEOS 148
Example: Creating a portable hardware delay 126 Tasks, functions and scheduling 153
The need for ‘timeout’ mechanisms - example 129 Setting the tick interval 154
Creating loop timeouts 130 Saving power 157
Example: Testing loop timeouts 132 Using sEOS in your own projects 158
Example: A more reliable switch interface 134 Is this approach portable? 159
Creating hardware timeouts 135 Example: Milk pasteurization 160
Conclusions 137 Conclusions 174
Preparation for the next seminar 138 Preparation for the next seminar 175
VII VIII
Seminar 7: Multi-State Systems and Function Sequences 177 Seminar 8: Using the Serial Interface 211
Introduction 178 Overview of this seminar 212
Implementing a Multi-State (Timed) system 180 What is ‘RS-232’? 213
Example: Traffic light sequencing 181 Basic RS-232 Protocol 214
Example: Animatronic dinosaur 189 Asynchronous data transmission and baud rates 215
Implementing a Multi-State (Input/Timed) system 195 RS-232 voltage levels 216
Example: Controller for a washing machine 197 The software architecture 217
Conclusions 208 Overview 218
Preparation for the next seminar 209 Using the on-chip U(S)ART for RS-232 communications 219
Serial port registers 220
Baud rate generation 221
Why use 11.0592 MHz crystals? 222
PC Software 223
What about printf()? 224
RS-232 and 8051: Overall strengths and weaknesses 225
Example: Displaying elapsed time on a PC 226
Example: Data acquisition 235
Conclusions 239
Preparation for the next seminar 240
IX X
Seminar 9: Case Study: Intruder Alarm System 241 Seminar 10: Case Study: Controlling a Mobile Robot 263
Introduction 242 Overview 264
System Operation 243 What can the robot do? 265
Key software components used in this example 244 The robot brain 266
Running the program 245 How does the robot move? 267
The software 246 Pulse-width modulation 268
Extending and modifying the system 260 Software PWM 269
Conclusions 261 The resulting code 270
More about the robot 271
Conclusions 272
XI XII
Overview of this seminar
4V - 6V (battery)
10 µF
1 RST VCC 20
10 K 2 P3.0 P1.7 19
4 XTL2 P1.5 17
Atmel 2051
E
4 MHz
5 XTL1 P1.4 16
B
6 P3.2 P1.3 15 ZTX751
7 P3.3 P1.2 14 C
8 P3.4 P1.1 13
9 P3.5 P1.0 12
10 GND P3.7 11
17
16
15
14
13
12
11
20
19
18
10
5
4
3
2
1
6
8
9
VSS
XTL1
XTL2
P3.7
P3.6
P3.5
P3.4
P3.3
P3.2
P3.1
P3.0
RST
P1.7
P1.6
P1.5
P1.4
P1.3
P1.2
P1.1
P1.0
‘8051’
/ PSEN
P0.0
VCC
P2.0
P2.1
P2.2
P2.3
P2.4
P2.5
P2.6
P2.7
P0.7
P0.6
P0.5
P0.4
P0.3
P0.2
P0.1
ALE
/ EA
24
25
26
27
28
29
30
32
33
34
35
36
37
38
39
40
31
21
22
23
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 1 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 2
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Overview of this course By the end of the course …
This course is concerned with the implementation of software (and By the end of the course, you will be able to:
a small amount of hardware) for embedded systems constructed
1. Design software for single-processor embedded applications
using a single microcontroller.
based on small, industry standard, microcontrollers;
The processors examined in detail are from the 8051 family 2. Implement the above designs using a modern, high-level
(including both ‘Standard’ and ‘Small’ devices). programming language (‘C’), and
All programming is in the ‘C’ language. 3. Begin to understand issues of reliability and safety and how
software design and programming decisions may have a
positive or negative impact in this area.
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 3 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 4
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Main course textbook Why use C?
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 5 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 6
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Pre-requisites! The 8051 microcontroller
17
16
15
14
13
12
11
20
19
18
10
2
1
7
6
5
3
9
8
example - Java or C++.
VSS
XTL1
XTL2
P3.7
P3.6
P3.5
P3.4
P3.3
P3.2
P3.1
P3.0
RST
P1.7
P1.6
P1.5
P1.4
P1.3
P1.2
P1.1
P1.0
‘8051’
For most people with such a background, “getting to grips”
/ PSEN
P0.0
VCC
P2.0
P2.1
P2.2
P2.3
P2.4
P2.5
P2.6
P2.7
P0.7
P0.6
P0.5
P0.4
P0.3
P0.2
P0.1
ALE
/ EA
with C is straightforward.
34
35
36
37
38
39
40
24
25
26
27
28
29
30
32
33
21
23
31
22
Typical features of a modern 8051:
Thirty-two input / output lines.
Internal data (RAM) memory - 256 bytes.
Up to 64 kbytes of ROM memory (usually flash)
Three 16-bit timers / counters
Nine interrupts (two external) with two priority levels.
Low-power Idle and Power-down modes.
The different members of this family are suitable for everything from
automotive and aerospace systems to TV “remotes”.
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 7 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 8
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
The “super loop” software architecture Strengths and weaknesseses of “super loops”
The main strength of Super Loop systems is their simplicity. This
Problem makes them (comparatively) easy to build, debug, test and maintain.
What is the minimum software environment you need to create an Super Loops are highly efficient: they have minimal hardware
resource implications.
embedded C program?
Super Loops are highly portable.
Solution
BUT:
void main(void)
{ If your application requires accurate timing (for example, you need to
/* Prepare for task X */
X_Init(); acquire data precisely every 2 ms), then this framework will not
provide the accuracy or flexibility you require.
while(1) /* 'for ever' (Super Loop) */
The basic Super Loop operates at ‘full power’ (normal operating
{
X(); /* Perform the task */ mode) at all times. This may not be necessary in all applications, and
} can have a dramatic impact on system power consumption.
}
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 9 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 10
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Example: Central-heating controller Reading from (and writing to) port pins
Problem
Temperature
sensor
Central
heating Boiler
How do you write software to read from and /or write to the ports
Temperature
controller
on an (8051) microcontroller?
dial
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 11 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 12
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
SFRs and ports SFRs and ports
Control of the 8051 ports through software is carried out using what A typical SFR header file for an 8051 family device will contain the
are known as ‘special function registers’ (SFRs). lines:
sfr P0 = 0x80;
Physically, the SFR is a area of memory in internal RAM: sfr P1 = 0x90;
sfr P2 = 0xA0;
P0 is at address 0x80 sfr P3 = 0xB0;
P1 at address 0x90
Having declared the SFR variables, we can write to the ports in a
P2 at address 0xA0 straightforward manner. For example, we can send some data to
Port 1 as follows:
P3 at address 0xB0
unsigned char Port_data;
Port_data = 0x0F;
Note that, in order to read from a pin, we need to ensure that the last
thing written to the pin was a ‘1’.
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 13 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 14
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Creating and using sbit variables Example: Reading and writing bytes
sbit Warning_led = LED_PORT^0; /* LED is connected to pin 3.0 */ /* Must set up P1 for reading */
P1 = 0xFF;
...
while(1)
Warning_led = LED_ON; {
... /* delay */ /* Read the value of P1 */
Warning_led = LED_OFF; Port1_value = P1;
... /* delay */
Warning_led = LED_ON; /* Copy the value to P2 */
... /* etc */ P2 = Port1_value;
}
}
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 15 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 16
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Creating “software delays” Using the performance analyzer to test software delays
Problem
Loop_Delay()
{
unsigned int x,y;
Longer_Loop_Delay()
{
unsigned int x, y, z;
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 17 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 18
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Strengths and weaknesses of software-only delays Preparation for the next seminar
SOFTWARE DELAY can be used to produce very short delays. In the lab session associated with this seminar, you will use a
SOFTWARE DELAY requires no hardware timers. hardware simulator to try out the techniques discussed here. This
SOFTWARE DELAY will work on any microcontroller. will give you a chance to focus on the software aspects of
embedded systems, without dealing with hardware problems.
BUT:
In the next seminar, we will prepare to create your first test systems
It is very difficult to produce precisely timed delays. on “real hardware”.
The loops must be re-tuned if you decide to use a different processor,
change the clock frequency, or even change the compiler optimisation
settings. Please read Chapters 1, 2 and 3
before the next seminar
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 19 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 20
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Review: The 8051 microcontroller
17
16
15
14
13
12
11
20
19
18
10
2
1
7
6
5
3
9
8
Seminar 2:
VSS
XTL1
XTL2
P3.7
P3.6
P3.5
P3.4
P3.3
P3.2
P3.1
P3.0
RST
P1.7
P1.6
P1.5
P1.4
P1.3
P1.2
P1.1
P1.0
‘8051’
Basic hardware
/ PSEN
P0.0
VCC
P2.0
P2.1
P2.2
P2.3
P2.4
P2.5
P2.6
P2.7
P0.7
P0.6
P0.5
P0.4
P0.3
P0.2
P0.1
ALE
/ EA
34
35
36
37
38
39
40
24
25
26
27
28
29
30
32
33
21
23
31
22
foundations (resets, Typical features of a modern 8051:
oscillators and port Thirty-two input / output lines.
EA
The different members of this family are suitable for everything from
Vcc
Atmel
89C52 automotive and aerospace systems to TV “remotes”.
12 MHz
DS1812 RESET XTAL 1
30 pF ±10
GND XTAL 2
30 pF ±10
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 21 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 22
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Review: Central-heating controller Overview of this seminar
void main(void)
Specifically, we’ll look at:
{
/* Init the system */ Oscillator circuits
C_HEAT_Init();
Reset circuits
while(1) /* 'for ever' (Super Loop) */
{
/* Find out what temperature the user requires Controlling LEDs
(via the user interface) */
C_HEAT_Get_Required_Temperature();
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 23 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 24
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Oscillator Hardware
CRYSTAL OSCILLATOR
All digital computer systems are driven by some form of
oscillator circuit. Crystals may be used to generate a popular form of oscillator circuit
This circuit is the ‘heartbeat’ of the system and is crucial to known as a Pierce oscillator.
correct operation. Vcc
For example: C
L
Oscillator output
(to microcontroller)
If the oscillator fails, the system will not function at all. Crystal
JFET
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 25 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 26
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
How to connect a crystal to a microcontroller Oscillator frequency and machine cycle period
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 27 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 28
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Keep the clock frequency as low as possible Stability issues
Many developers select an oscillator / resonator frequency that is at A key factor in selecting an oscillator for your system is the
or near the maximum value supported by a particular device. issue of oscillator stability. In most cases, oscillator stability
is expressed in figures such as ‘±20 ppm’: ‘20 parts per
million’.
This can be a mistake:
Many application do not require the levels of performance
To see what this means in practice, consider that there are
that a modern 8051 device can provide.
approximately 32 million seconds in a year. In every million
The electromagnetic interference (EMI) generated by a seconds, your crystal may gain (or lose) 20 seconds. Over
circuit increases with clock frequency. the year, a clock based on a 20 ppm crystal may therefore
gain (or lose) about 32 x 20 seconds, or around 10 minutes.
In most modern (CMOS-based) 8051s, there is an almost
linear relationship between the oscillator frequency and the
power-supply current. As a result, by using the lowest Standard quartz crystals are typically rated from ±10 to ±100 ppm, and
frequency necessary it is possible to reduce the power so may gain (or lose) from around 5 to 50 minutes per year.
requirement: this can be useful in many applications.
When accessing low-speed peripherals (such as slow
memory, or LCD displays), programming and hardware
design can be greatly simplified - and the cost of peripheral
components, such as memory latches, can be reduced - if the
chip is operating more slowly.
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 29 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 30
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Improving the stability of a crystal oscillator Overall strengths and weaknesses
If you want a general crystal-controlled embedded system to Crystal oscillators are stable. Typically ±20-100 ppm = ±50 mins per
year (up to ~1 minute / week).
keep accurate time, you can choose to keep the device in an
oven (or fridge) at a fixed temperature, and fine-tune the The great majority of 8051-based designs use a variant of the simple
crystal-based oscillator circuit presented here: developers are
software to keep accurate time. This is, however, rarely therefore familiar with crystal-based designs.
practical. Quartz crystals are available at reasonable cost for most common
frequencies. The only additional components required are usually two
‘Temperature Compensated Crystal Oscillators’ (TCXOs) small capacitors. Overall, crystal oscillators are more expensive than
are available that provide - in an easy-to-use package - a ceramic resonators.
crystal oscillator, and circuitry that compensates for changes
in temperature. Such devices provide stability levels of up to BUT:
±0.1 ppm (or more): in a clock circuit, this should gain or
lose no more than around 1 minute every 20 years. Crystal oscillators are susceptible to vibration.
The stability falls with age.
TCXOs can cost in excess of $100.00 per unit...
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 31 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 32
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Reset Hardware
CERAMIC RESONATOR
The process of starting any microcontroller is a non-trivial
one.
Overall strengths and weaknesses
The underlying hardware is complex and a small,
Cheaper than crystal oscillators.
manufacturer-defined, ‘reset routine’ must be run to place
Physically robust: less easily damage by physical vibration (or
dropped equipment, etc) than crystal oscillator.
this hardware into an appropriate state before it can begin
executing the user program. Running this reset routine takes
Many resonators contain in-built capacitors, and can be used without
any external components. time, and requires that the microcontroller’s oscillator is
Small size. About half the size of crystal oscillator. operating.
An RC reset circuit is usually the simplest way of controlling
BUT: the reset behaviour.
10 uF Vcc
AT89C2051
RESET XTAL 1
30 pF ±10
10 K
GND XTAL 2
30 pF ±10
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 33 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 34
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
More robust reset circuits Driving DC Loads
30 pF ±10
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 35 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 36
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Use of pull-up resistors
NAKED LED
To adapt circuits for use on pins without internal pull-up resistors is
straightforward: you simply need to add an external pull-up resistor:
Vcc
Vcc
Rpull-up
PX.Y
8051 Device Logic 0 (0v)
to light LED
PX.Y
8051 Device Logic 0
usually possible.
Supply voltage, Vcc = 5V, The value of the pull-up resistor should be between 1K and 10K.
This requirement applies to all of the examples on this course.
LED forward voltage, Vdiode = 2V,
Required diode current, Idiode = 15 mA (note that the data NOTE:
sheet for your chosen LED will provide this information). This is usually only necessary on Port 0
(see Seminar 3 for further details).
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 37 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 38
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Driving a low-power load without using a buffer Using an IC Buffer
5V
Vcc
“Low” output = 0V LED is (fully) ON
R
“High” output = 5V LED is OFF
R
Pin X.Y
(CMOS)
Load
Buffer
8051 Device
PX.Y
Logic 0 (0v)
Vcc − Vload
8051 Device
to drive load
R=
I load Using a CMOS buffer.
5V
Piezo-electric
Pin X.Y
buzzer
Buffer
(TTL)
8051 Device
PX.Y
Logic 0 (0v) to sound buzzer
8051 Device Using a TTL buffer.
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 39 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 40
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Example: Buffering three LEDs with a 74HC04 What is a multi-segment LED?
This example shows a 74HC04 buffering three LEDs. As discussed Multiple LEDs are often arranged as multi-segment displays:
in Solution, we do not require pull-up resistors with the HC combinations of eight segments and similar seven-segment displays
(CMOS) buffers. (without a decimal point) are particularly common.
8
In this case, we assume that the LEDs are to be driven at 15 mA a
Vcc − Vdiode 5V − 2V e
Rled = = = 200Ω c
I diode 0.015 A
d
5V
PX.c)
Port X
Logic 1 (PX.a) (PX.b) (PX.c)
8051 Device to light
LED
Cathode (-)
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 41 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 42
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Driving a single digit Preparation for the next seminar
Vcc
PX.0 9 a
8
b
c
UDN
2585A
dp
10
10 R
PX.7
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 43 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 44
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Introduction
Port 3.
0 Enter < > Up and Around
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 45 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 46
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Review: Basic techniques for reading from port pins Example: Reading and writing bytes (review)
while(1)
{
/* Read the value of P1 */
Port1_value = P1;
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 47 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 48
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Example: Reading and writing bits (simple version) Experienced ‘C’ programmers please note these lines:
/*-------------------------------------------------------------*- sbit Switch_pin = P1^0;
sbit LED_pin = P1^1;
Bits1.C (v1.00)
-*-------------------------------------------------------------*/ Here we gain access to two port pins through the use of an
variable declaration. The symbol ‘^’ is used, but the XOR bitwise
#include <Reg52.H>
operator is NOT involved.
sbit Switch_pin = P1^0;
sbit LED_pin = P1^1;
/* ............................................................... */
while(1)
{
x = Switch_pin; /* Read Pin 1.0 */
LED_pin = x; /* Write to Pin 1.1 */
}
}
/*-------------------------------------------------------------*-
---- END OF FILE ---------------------------------------
-*-------------------------------------------------------------*/
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 49 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 50
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Example: Reading and writing bits (generic version) /* Desktop program - illustrating the use of bitwise operators */
#include <stdio.h>
The six bitwise operators:
void Display_Byte(const unsigned char);
printf("\n\n");
return 0;
}
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 51 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 52
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/* --------------------------------------------------------------- */ /*-------------------------------------------------------------*-
void Display_Byte(const unsigned char CH) Reading and writing individual port pins.
{
unsigned char i, c = CH; NOTE: Both pins on the same port
unsigned char Mask = 1 << 7;
-*-------------------------------------------------------------*/
for (i = 1; i <= 8; i++)
{ #include <reg52.H>
putchar(c & Mask ? '1' : '0');
c <<= 1; void Write_Bit_P1(const unsigned char, const bit);
} bit Read_Bit_P1(const unsigned char);
putchar('\n'); /* ............................................................... */
}
void main (void)
{
bit x;
while(1)
x 11111110 {
1s complement [~x] 00000001 x = Read_Bit_P1(0); /* Read Port 1, Pin 0 */
Bitwise AND [x & 0x0f] 00001110 Write_Bit_P1(1,x); /* Write to Port 1, Pin 1 */
Bitwise OR [x | 0x0f] 11111111 }
Bitwise XOR [x ^ 0x0f] 11110001 }
Left shift, 1 place [x <<= 1] 11111100
Right shift, 4 places [x >>= 4] 00001111 /* --------------------------------------------------------------- */
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 53 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 54
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/* --------------------------------------------------------------- */
/*-------------------------------------------------------------*-
---- END OF FILE ---------------------------------------
-*-------------------------------------------------------------*/
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 55 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 56
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
The need for pull-up resistors The need for pull-up resistors
Without pull-ups:
Vcc Vcc
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 57 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 58
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Dealing with switch bounce
Creating some simple software to check for a valid switch input is
In practice, all mechanical switch contacts bounce (that is, turn on straightforward:
and off, repeatedly, for a short period of time) after the switch is
closed or opened. 1. We read the relevant port pin.
2. If we think we have detected a switch depression, we wait for
+5v
20 ms and then read the pin again.
3. If the second reading confirms the first reading, we assume
Voltage
the switch really has been depressed.
+5v
Note that the figure of ‘20 ms’ will, of course, depend on the switch
t1 t2 Time used.
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 59 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 60
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Example: Reading switch inputs (basic code) /*-------------------------------------------------------------*-
Switch_read.C (v1.00)
--------------------------------------------------------
This switch-reading code is adequate if we want to perform
operations such as: A simple 'switch input' program for the 8051.
- Reads (and debounces) switch input on Pin 1^0
- If switch is pressed, changes Port 3 output
Drive a motor while a switch is pressed.
-*-------------------------------------------------------------*/
Switch on a light while a switch is pressed.
#include <Reg52.h>
Activate a pump while a switch is pressed. /* Connect switch to this pin */
sbit Switch_pin = P1^0;
/* Function prototypes */
Drive a motor while a switch is pressed void SWITCH_Init(void);
Condition: If the safety guard is not in place, don’t turn the bit SWITCH_Get_Input(const unsigned char DEBOUNCE_PERIOD);
void DISPLAY_SWITCH_STATUS_Init(void);
motor. Instead sound a buzzer for 2 seconds. void DISPLAY_SWITCH_STATUS_Update(const bit);
void DELAY_LOOP_Wait(const unsigned int DELAY_MS);
Switch on a light while a switch is pressed
Condition: To save power, ignore requests to turn on the
light during daylight hours.
Activate a pump while a switch is pressed
Condition: If the main water reservoir is below 300 litres,
do not start the main pump: instead, start the reserve pump
and draw the water from the emergency tank.
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 61 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 62
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/* ---------------------------------------------------------------- */ /*-------------------------------------------------------------*-
void main(void)
{ SWITCH_Get_Input()
bit Sw_state;
Reads and debounces a mechanical switch as follows:
/* Init functions */
SWITCH_Init(); 1. If switch is not pressed, return SWITCH_NOT_PRESSED.
DISPLAY_SWITCH_STATUS_Init();
2. If switch is pressed, wait for the DEBOUNCE_PERIOD (in ms).
while(1) Then:
{ a. If switch is no longer pressed, return SWITCH_NOT_PRESSED.
Sw_state = SWITCH_Get_Input(30); b. If switch is still pressed, return SWITCH_PRESSED
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 63 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 64
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*- /*-------------------------------------------------------------*-
DISPLAY_SWITCH_STATUS_Init() DELAY_LOOP_Wait()
Initialization function for the DISPLAY_SWITCH_STATUS library. Delay duration varies with parameter.
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 65 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 66
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Example: Counting goats
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 67 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 68
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*-
Mechanical sensor A 'goat counting' program for the 8051...
at goat body
height
-*-------------------------------------------------------------*/
#include <Reg52.h>
/* Function prototypes */
void SWITCH_Init(void);
bit SWITCH_Get_Input(const unsigned char DEBOUNCE_PERIOD);
void DISPLAY_COUNT_Init(void);
If we try to use the code in the previous example, the goat sensor void DISPLAY_COUNT_Update(const unsigned char);
will not allow us to count the number of goats but will instead void DELAY_LOOP_Wait(const unsigned int DELAY_MS);
provide an indication of the time taken for the goats to pass the /* ---------------------------------------------------------------- */
sensor. void main(void)
{
unsigned char Switch_presses = 0;
/* Init functions */
SWITCH_Init();
DISPLAY_COUNT_Init();
while(1)
{
if (SWITCH_Get_Input(30) == SWITCH_PRESSED)
{
Switch_presses++;
}
DISPLAY_COUNT_Update(Switch_presses);
}
}
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 69 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 70
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*/ /*-------------------------------------------------------------*-
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 71 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 72
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Conclusions
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 73 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 74
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Preparation for the next seminar
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 75 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 76
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Introduction
Your Code 2. We will describe how to create and use a ‘Project Header’
file. This file encapsulates key aspects of the hardware
environment, such as the type of processor to be used, the
oscillator frequency and the number of oscillator cycles
required to execute each instruction. This helps to document
the system, and makes it easier to port the code to a different
Port Header (Port.H) processor.
// Pins 3.0 and 3.1 used // Switches
// for RS-232 interface sbit Sw_up = P1^2;
sbit Sw_down = P1^3;
3. We will describe how to create and use a ‘Port Header’ file.
This brings together all details of the port access from the
Up Down
whole system. Like the Project Header, this helps during
porting and also serves as a means of documenting important
system features.
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 77 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 78
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Object-Oriented Programming with C
1
Graham notes :
“[The phrase] ‘object-oriented’ has become almost
Language generation Example languages
synonymous with modernity, goodness and worth in
- Machine Code information technology circles.”
First-Generation Language Assembly 2
(1GL) Language. Jalote notes :
Second-Generation Languages COBOL, “One main claimed advantage of using object orientation
(2GLs) FORTRAN is that an OO model closely represents the problem
domain, which makes it easier to produce and understand
Third-Generation Languages C, Pascal, Ada 83
(3GLs)
designs.”
1
Graham, I. (1994) “Object-Oriented Methods,” (2nd Ed.) Addison-Wesley. Page
1.
2
Jalote, P. (1997) “An Integrated Approach to Software Engineering”, (2nd Ed.)
Springer-Verlag. Page 273.
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 79 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 80
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
It is possible to create ‘file-based-classes’ in C without imposing a Example of “O-O C”
significant memory or CPU load. /*-------------------------------------------------------------*-
PC_IO.H (v1.00)
Header file --------------------------------------------------------
Serial.C
Serial.C - see PC_IO.C for details.
All
All
program
program -*-------------------------------------------------------------*/
code
code Header file
in
in aa #ifndef _PC_IO_H
single Switch.C
Switch.C
single #define _PC_IO_H
source
source
file
file Header file /* ------ Public constants ------------------------------------ */
sEOS.C
sEOS.C /* Value returned by PC_LINK_Get_Char_From_Buffer if no char is
available in buffer */
#define PC_LINK_IO_NO_CHAR 127
char PC_LINK_IO_Get_Char_From_Buffer(void);
#endif
/*-------------------------------------------------------------*-
---- END OF FILE ---------------------------------------
-*-------------------------------------------------------------*/
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 81 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 82
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*- /*-------------------------------------------------------------*/
void PC_LINK_IO_Write_Char_To_Buffer(...)
PC_IO.C (v1.00) {
...
-------------------------------------------------------- }
/*-------------------------------------------------------------*/
void PC_LINK_IO_Update(...)
{
...
}
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 83 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 84
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*-
The Project Header (Main.H) Main.H (v1.00)
-*-------------------------------------------------------------*/
/* --------------------------------------------------------
SHOULD NOT NEED TO EDIT THE SECTIONS BELOW
-------------------------------------------------------- */
#endif
/*-------------------------------------------------------------*-
---- END OF FILE ---------------------------------------
-*-------------------------------------------------------------*/
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 85 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 86
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
The device header Oscillator frequency and oscillations per instruction
Header file for the Infineon C515C /* Number of oscillations per instruction (12, etc)
12 - Original 8051 / 8052 and numerous modern versions
Copyright (c) 1995-1999 Keil Elektronik GmbH All rights reserved. 6 - Various Infineon and Philips devices, etc.
----------------------------------------------------------------*/ 4 - Dallas 320, 520 etc.
1 - Dallas 420, etc. */
... #define OSC_PER_INST (12)
/* A/D Converter */
sfr ADCON0 = 0xD8;
...
We demonstrate how to use this information:
/* Interrupt System */
sfr IEN0 = 0xA8; For creating delays (Embedded C, Chapter 6),
...
/* Ports */
For controlling timing in an operating system (Chapter 7),
sfr P0 = 0x80; and,
sfr P1 = 0x90;
sfr
sfr
P2
P3
=
=
0xA0;
0xB0;
For controlling the baud rate in a serial interface (Chapter 9).
sfr P4 = 0xE8;
sfr P5 = 0xF8;
sfr P6 = 0xDB;
sfr P7 = 0xFA;
...
/* Serial Channel */
sfr SCON = 0x98;
...
/* Timer0 / Timer1 */
sfr TCON = 0x88;
...
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 87 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 88
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Common data types Interrupts
As we noted in “Embedded C” Chapter 2, interrupts are a key
typedef unsigned char tByte; component of most embedded systems.
typedef unsigned int tWord;
typedef unsigned long tLong;
The following lines in the Project Header are intended to make it
In C, the typedef keyword allows us to provide aliases for data easier for you to use (timer-based) interrupts in your projects:
types: we can then use these aliases in place of the original types. #define INTERRUPT_Timer_0_Overflow 1
Thus, in the projects you will see code like this: #define INTERRUPT_Timer_1_Overflow 3
#define INTERRUPT_Timer_2_Overflow 5
tWord Temperature;
We discuss how to make use of this facility in Embedded C, Ch. 7.
Rather than:
unsigned int Temperature;
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 89 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 90
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Summary: Why use the Project Header? The Port Header (Port.H)
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 91 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 92
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
The Port Header file is simple to understand and easy to apply. There are many advantages obtained by integrating all port access
in a single Port.H header file:
Consider, for example, that we have three C files in a project (A, B,
/* ----- Port.H ----- */
C), each of which require access to one or more port pins, or to a
complete port. /* Port access for File B */
#define Port_B = P0;
... ...
...
...
In this version of the code, all of the port access requirements are
spread over multiple files.
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 93 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 94
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*-
Port.H (v1.01)
Re-structuring a “Hello World” example
-------------------------------------------------------- /*-------------------------------------------------------------*-
'Port Header' (see Chap 5) for project DATA_ACQ (see Chap 9) Main.H (v1.00)
-*-------------------------------------------------------------*/ -*-------------------------------------------------------------*/
/* Pins 3.0 and 3.1 used for RS-232 interface */ /* Number of oscillations per instruction (12, etc)
12 - Original 8051 / 8052 and numerous modern versions
#endif 6 - Various Infineon and Philips devices, etc.
4 - Dallas 320, 520 etc.
/*-------------------------------------------------------------*- 1 - Dallas 420, etc. */
---- END OF FILE --------------------------------------- #define OSC_PER_INST (12)
-*-------------------------------------------------------------*/
/* --------------------------------------------------------
SHOULD NOT NEED TO EDIT THE SECTIONS BELOW
-------------------------------------------------------- */
#endif
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 95 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 96
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*- /*-------------------------------------------------------------*-
-------------------------------------------------------- --------------------------------------------------------
'Port Header' for project HELLO2 (see Chap 5) A "Hello Embedded World" test program for 8051.
/*-------------------------------------------------------------*-
---- END OF FILE ---------------------------------------
-*-------------------------------------------------------------*/
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 97 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 98
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*- /*-------------------------------------------------------------*-
-------------------------------------------------------- --------------------------------------------------------
-*-------------------------------------------------------------*/ -*-------------------------------------------------------------*/
-*-------------------------------------------------------------*/
void LED_FLASH_Init(void)
{
LED_state_G = 0;
}
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 99 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 100
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*- /*-------------------------------------------------------------*-
/*-------------------------------------------------------------*-
---- END OF FILE ---------------------------------------
-*-------------------------------------------------------------*/
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 101 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 102
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*-
Delay_Loop.C (v1.00)
Example: Re-structuring the Goat-Counting Example
-------------------------------------------------------- /*-------------------------------------------------------------*-
-*-------------------------------------------------------------*/ -*-------------------------------------------------------------*/
#endif
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 103 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 104
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*- /*-------------------------------------------------------------*-
-------------------------------------------------------- --------------------------------------------------------
'Port Header' for project GOATS2 (see Chap 5) A 'switch count' program for the 8051.
-*-------------------------------------------------------------*/ -*-------------------------------------------------------------*/
DISPLAY_COUNT_Update(Switch_presses);
}
}
/*-------------------------------------------------------------*-
---- END OF FILE ---------------------------------------
-*-------------------------------------------------------------*/
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 105 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 106
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*- /*-------------------------------------------------------------*-
-------------------------------------------------------- --------------------------------------------------------
- See Switch_wait.C for details. Simple library for debouncing a switch input.
/*-------------------------------------------------------------*- -*-------------------------------------------------------------*/
---- END OF FILE --------------------------------------- void SWITCH_Init(void)
-*-------------------------------------------------------------*/ {
Switch_pin = 1; /* Use this pin for input */
}
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 107 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 108
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*- /*-------------------------------------------------------------*-
See Switch_Wait.H for details of return values. /* ------ Public function prototypes -------------------------- */
void DISPLAY_COUNT_Init(void);
-*-------------------------------------------------------------*/ void DISPLAY_COUNT_Update(const tByte);
bit SWITCH_Get_Input(const tByte DEBOUNCE_PERIOD)
{ #endif
bit Return_value = SWITCH_NOT_PRESSED;
/*-------------------------------------------------------------*-
if (Switch_pin == 0) ---- END OF FILE ---------------------------------------
{ -*-------------------------------------------------------------*/
/* Switch is pressed */
/*-------------------------------------------------------------*-
---- END OF FILE ---------------------------------------
-*-------------------------------------------------------------*/
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 109 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 110
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*- /*-------------------------------------------------------------*-
-------------------------------------------------------- --------------------------------------------------------
-*-------------------------------------------------------------*/ -*-------------------------------------------------------------*/
/*-------------------------------------------------------------*-
DISPLAY_COUNT_Update()
-*-------------------------------------------------------------*/
void DISPLAY_COUNT_Update(const tByte COUNT)
{
Count_port = COUNT;
}
/*-------------------------------------------------------------*-
---- END OF FILE ---------------------------------------
-*-------------------------------------------------------------*/
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 111 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 112
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*-
Delay_Loop.C (v1.00)
Preparation for the next seminar
--------------------------------------------------------
#include "Delay_loop.h"
/*-------------------------------------------------------------*-
DELAY_LOOP_Wait()
-*-------------------------------------------------------------*/
void DELAY_LOOP_Wait(const tWord DELAY_MS)
{
tWord x, y;
/*-------------------------------------------------------------*-
---- END OF FILE ---------------------------------------
-*-------------------------------------------------------------*/
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 113 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 114
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Introduction
Constraints q
x, y, z = position coordinates
υ, β, ϖ = velocity cordinates
p = roll rate
q = pitch rate
y,β Rudder
r = yaw rate
δr
Elevator
δe
Aileron
x,υ δa
p
z,ϖ
Yaw (rate)
sensor
Pitch
(rate) Rudder
sensor
Roll
(rate) Elevator
sensor Aircraft
Autopilot
System
Main
pilot Aileron
controls
Velocity
sensors
(3 axes)
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 115 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 116
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
bit SWITCH_Get_Input(const tByte DEBOUNCE_PERIOD)
{
Creating “hardware delays”
tByte Return_value = SWITCH_NOT_PRESSED;
All members of the 8051 family have at least two 16-bit timer /
if (Switch_pin == 0)
{ counters, known as Timer 0 and Timer 1.
/* Switch is pressed */
We’ll see how to deal with both of these problems in this seminar
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 117 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 118
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
The TCON SFR The TMOD SFR
Bit 7 6 5 4 3 2 1 0
Bit 7 6 5 4 3 2 1 0 NAME Gate C/T M1 M0 Gate C/T M1 M0
(msb) (lsb)
TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0 Timer 1 Timer 0
NAME
Mode 1 (M1 = 0; M0 = 1)
TF1 Timer 1 overflow flag
16-bit timer/counter (with manual reload)
Set by hardware on Timer 1 overflow.
(Cleared by hardware if processor vectors to interrupt routine.) Mode 2 (M1 = 1; M0 = 0)
TR1 Timer 1 run control bit 8-bit timer/counter (with 8-bit auto-reload)
Set / cleared by software to turn Timer 1 either ‘ON’ or ‘OFF’.
TF0 Timer 0 overflow flag GATE Gating control
Set by hardware on Timer 0 overflow. When set, timer/counter “x” is enabled only while “INT x” pin is high and “TRx”
(Cleared by hardware if processor vectors to interrupt routine.) control bit is set. When cleared timer “x” is enabled whenever “TRx” control bit
is set.
TR0 Timer 0 run control bit
C/T Counter or timer select bit
Set / cleared by software to turn Timer 0 either ‘ON’ or ‘OFF’.
Set for counter operation (input from “Tx” input pin).
Cleared for timer operation (input from internal system clock).
Note that the overflow of the timers can be used to generate an
interrupt. We will not make use of this facility in the Hardware Delay
code.
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 119 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 120
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Two further registers Example: Generating a precise 50 ms delay
/*-------------------------------------------------------------*-
Before we can see how this hardware can be used to create delays,
you need to be aware that there are an additional two registers Hardware_Delay_50ms.C (v1.00)
associated with each timer: these are known as TL0 and TH0, and --------------------------------------------------------
TL1 and TH1.
A test program for hardware-based delays.
-*-------------------------------------------------------------*/
#include <reg52.h>
void LED_FLASH_Init(void);
void LED_FLASH_Change_State(void);
void DELAY_HARDWARE_One_Second(void);
void DELAY_HARDWARE_50ms(void);
/*..................................................................*/
void main(void)
{
LED_FLASH_Init();
while(1)
{
/* Change the LED state (OFF to ON, or vice versa) */
LED_FLASH_Change_State();
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 121 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 122
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*- /*-------------------------------------------------------------*-
LED_FLASH_Init() DELAY_HARDWARE_One_Second()
Prepare for LED_Change_State() function - see below. Hardware delay of 1000 ms.
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 123 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 124
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Example: Creating a portable hardware delay
/*-------------------------------------------------------------*-
Main.C (v1.00)
--------------------------------------------------------
-*-------------------------------------------------------------*/
#include "Main.H"
#include "Port.H"
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 125 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 126
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/* Timer preload values for use in simple (hardware) delays
- Timers are 16-bit, manual reload ('one shot').
/*-------------------------------------------------------------*/
ET0 = 0; /* No interrupts */
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 127 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 128
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
The need for ‘timeout’ mechanisms - example Creating loop timeouts
The Philips 8Xc552 is an Extended 8051 device with a number of Basis of loop timeout:
on-chip peripherals, including an 8-channel, 10-bit ADC. Philips tWord Timeout_loop = 0;
provide an application note (AN93017) that describes how to use
...
this feature of the microcontroller.
while (++Timeout_loop);
This application note includes the following code:
/* Wait until AD conversion finishes (checking ADCI) */ Original ADC code:
while ((ADCON & ADCI) == 0);
/* Wait until AD conversion finishes (checking ADCI) */
Such code is potentially unreliable, because there are circumstances while ((ADCON & ADCI) == 0);
under which our application may ‘hang’. This might occur for one
or more of the following reasons: Modified version, with a loop timeout:
If the ADC has been incorrectly initialised, we cannot be tWord Timeout_loop = 0;
sure that a data conversion will be carried out. /* Take sample from ADC
Wait until conversion finishes (checking ADCI)
If the ADC has been subjected to an excessive input voltage, - simple loop timeout */
while (((ADCON & ADCI) == 0) && (++Timeout_loop != 0));
then it may not operate at all.
If the variable ADCON or ADCI were not correctly Note that this alternative implementation is also useful:
initialised, they may not operate as required.
while (((ADCON & ADCI) == 0) && (Timeout_loop != 0))
{
Timeout_loop++; /* Disable for use in hardware simulator */
The Philips example is not intended to illustrate ‘production’ code. }
Unfortunately, however, code in this form is common in embedded
applications.
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 129 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 130
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*-
TimeoutL.H (v1.00)
Example: Testing loop timeouts
-------------------------------------------------------- /*-------------------------------------------------------------*-
Simple software (loop) timeout delays for the 8051 family. Main.C (v1.00)
* THESE VALUES ARE NOT PRECISE - YOU MUST ADAPT TO YOUR SYSTEM * -*-------------------------------------------------------------*/
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 131 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 132
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Example: A more reliable switch interface
bit SWITCH_Get_Input(const tByte DEBOUNCE_PERIOD)
{
tByte Return_value = SWITCH_NOT_PRESSED;
tLong Timeout_loop = LOOP_TIMEOUT_INIT_10000ms;
if (Switch_pin == 0)
{
/* Switch is pressed */
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 133 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 134
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*-
Creating hardware timeouts TimeoutH.H (v1.00)
/* Configure Timer 0 as a 16-bit timer */ -*-------------------------------------------------------------*/
TMOD &= 0xF0; /* Clear all T0 bits (T1 left unchanged) */
TMOD |= 0x01; /* Set required T0 bits (T1 left unchanged) */ #ifndef _TIMEOUTH_H
#define _TIMEOUTH_H
ET0 = 0; /* No interrupts */
/* ------ Public constants ------------------------------------ */
/* Simple timeout feature - approx 10 ms */
TH0 = PRELOAD_10ms_H; /* See Timeout.H for PRELOAD details */ /* Timer T_ values for use in simple (hardware) timeouts */
TL0 = PRELOAD_10ms_L; - Timers are 16-bit, manual reload ('one shot'). */
TF0 = 0; /* Clear flag */
TR0 = 1; /* Start timer */ NOTE: These macros are portable but timings are *approximate*
and *must* be checked by hand for accurate timing. */
while (((ADCON & ADCI) == 0) && !TF0);
/* Define initial Timer 0 / Timer 1 values for ~50 µs delay */
#define T_50micros (65536 - (tWord)((OSC_FREQ /
26000)/(OSC_PER_INST)))
#define T_50micros_H (T_50micros / 256)
#define T_50micros_L (T_50micros % 256)
...
#endif
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 135 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 136
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Conclusions Preparation for the next seminar
The delay and timeout considered in this seminar are widely used in
embedded applications.
Please read Chapter 7
In the next seminar we go on to consider another key software before the next seminar
component in many embedded applications: the operating system.
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 137 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 138
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Introduction
void main(void)
{
/* Prepare run function X */
Seminar 6: X_Init();
Creating an Embedded {
X(); /* Run function X */
}
Operating System }
Milk
Milkpasteurisation
pasteurisationsystem
system
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 139 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 140
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Consider a collection of requirements assembled from a range of
different embedded projects (in no particular order):
The current speed of the vehicle must be measured at 0.5
second intervals.
The display must be refreshed 40 times every second
The calculated new throttle setting must be applied every 0.5
“Item 345 was painted by Selvio Guaranteen early in the 16th century. At this time, seconds.
Guaranteen, who is generally known as a member of the Slafordic School, was …”
“Now turn to your left, and locate Item 346, a small painting which was until recently also
A time-frequency transform must be performed 20 times
thought to have been painted by Guarateen but which is now …”. every second.
The engine vibration data must be sampled 1000 times per
second.
Signal The frequency-domain data must be classified 20 times
every second.
level
(c
Tim
The keypad must be scanned every 200 ms.
e Signal
) level
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 141 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 142
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Timer-based interrupts (the core of an embedded OS)
void main(void)
{ #define INTERRUPT_Timer_2_Overflow 5
...
Init_System();
void main(void)
while(1) /* 'for ever' (Super Loop) */ {
{ Timer_2_Init(); /* Set up Timer 2 */
X(); /* Call the function (10 ms duration) */
Delay_50ms(); /* Delay for 50 ms */ EA = 1; /* Globally enable interrupts */
}
} while(1); /* An empty Super Loop */
}
void Timer_2_Init(void)
This will be fine, if: {
/* Timer 2 is configured as a 16-bit timer,
1. We know the precise duration of function X(), and, which is automatically reloaded when it overflows
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 143 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 144
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
The interrupt service routine (ISR) Automatic timer reloads
/* Preload values for 50 ms delay */
TH0 = 0x3C; /* Timer 0 initial value (High Byte) */
The interrupt generated by the overflow of Timer 2, invokes the TL0 = 0xB0; /* Timer 0 initial value (Low Byte) */
ISR: TF0 = 0; /* Clear overflow flag */
TR0 = 1; /* Start timer 0 */
/* --------------------------------------------------------------- */
void X(void) interrupt INTERRUPT_Timer_2_Overflow while (TF0 == 0); /* Loop until Timer 0 overflows (TF0 == 1) */
{
/* This ISR is called every 1 ms */ TR0 = 0; /* Stop Timer 0 */
/* Place required code here... */
} For our operating system, we have slightly different requirements:
The link between this function and the timer overflow is made using We require a long series of interrupts, at precisely-
the Keil keyword interrupt: determined intervals.
void X(void) interrupt INTERRUPT_Timer_2_Overflow We would like to generate these interrupts without imposing
a significant load on the CPU.
…plus the following #define directive:
In this case, the timer is reloaded using the contents of the ‘capture’
Interrupt source Address IE Index registers (note that the names of these registers vary slightly
Power On Reset 0x00 - between chip manufacturers):
External Interrupt 0 0x03 0 RCAP2H = 0xFC; /* Load T2 reload capt. reg. high byte */
Timer 0 Overflow 0x0B 1 RCAP2L = 0x18; /* Load T2 reload capt. reg. low byte */
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 145 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 146
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Introducing sEOS Introducing sEOS
See “Embedded C”, Chapter 7
void main(void)
{
Init_System(); /*--------------------------------------------------------*-
#include "Main.H"
#include "Port.H"
In this case: #include "Simple_EOS.H"
/* ----------------------------------------------------- */
We call X() every 60 ms - approximately.
void main(void)
{
/* Prepare for dummy task */
X_Init();
Now let’s look at a better way of doing this …
/* Set up simple EOS (60 ms tick interval) */
sEOS_Init_Timer2(60);
/*--------------------------------------------------------*-
---- END OF FILE ----------------------------------
-*--------------------------------------------------------*/
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 147 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 148
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*--------------------------------------------------------*- /*--------------------------------------------------------*-
--------------------------------------------------- -*--------------------------------------------------------*/
void sEOS_Init_Timer2(const tByte TICK_MS)
Main file for Simple Embedded Operating System (sEOS). {
tLong Inc;
Demonstration version with dummy task X(). tWord Reload_16;
tByte Reload_08H, Reload_08L;
-*--------------------------------------------------------*/
/* Timer 2 is configured as a 16-bit timer,
#include "Main.H" which is automatically reloaded when it overflows */
#include "Simple_EOS.H" T2CON = 0x04; /* Load T2 control register */
/* Header for dummy task */ /* Number of timer increments required (max 65536) */
#include "X.H" Inc = ((tLong)TICK_MS * (OSC_FREQ/1000)) /
(tLong)OSC_PER_INST;
/*--------------------------------------------------------*-
/* 16-bit reload value */
sEOS_ISR() Reload_16 = (tWord) (65536UL - Inc);
Invoked periodically by Timer 2 overflow: /* 8-bit reload values (High & Low) */
see sEOS_Init_Timer2() for timing details. Reload_08H = (tByte)(Reload_16 / 256);
Reload_08L = (tByte)(Reload_16 % 256);
-*--------------------------------------------------------*/
sEOS_ISR() interrupt INTERRUPT_Timer_2_Overflow /* Used for manually checking timing (in simulator) */
{ /*P2 = Reload_08H; */
/* Must manually reset the T2 flag */ /*P3 = Reload_08L; */
TF2 = 0;
TH2 = Reload_08H; /* Load T2 high byte */
/*===== USER CODE - Begin ============================= */ RCAP2H = Reload_08H; /* Load T2 reload capt. reg h byte */
TL2 = Reload_08L; /* Load T2 low byte */
/* Call dummy task here */ RCAP2L = Reload_08L; /* Load T2 reload capt. reg l byte */
X();
/* Timer 2 interrupt is enabled, and ISR will be called
/*===== USER CODE - End =============================== */ whenever the timer overflows. */
} ET2 = 1;
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 149 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 150
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*--------------------------------------------------------*-
/*--------------------------------------------------------*-
sEOS_Go_To_Sleep()
X.C (v1.00)
This operating system enters 'idle mode' between clock ticks
to save power. The next clock tick will return processor ---------------------------------------------------
to the normal operating state.
Dummy task to introduce sEOS.
-*--------------------------------------------------------*/
void sEOS_Go_To_Sleep(void) -*--------------------------------------------------------*/
{
PCON |= 0x01; /* Enter idle mode (generic 8051 version) */ #include "X.H"
}
/*--------------------------------------------------------*-
/*--------------------------------------------------------*-
---- END OF FILE ---------------------------------- X_Init()
-*--------------------------------------------------------*/
Dummy task init function.
-*--------------------------------------------------------*/
void X_Init(void)
{
/* Dummy task init... */
}
/*--------------------------------------------------------*-
X()
-*--------------------------------------------------------*/
void X(void)
{
/* Dummy task... */
}
/*--------------------------------------------------------*-
---- END OF FILE ----------------------------------
-*--------------------------------------------------------*/
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 151 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 152
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Tasks, functions and scheduling Setting the tick interval
In discussions about embedded systems, you will frequently In the function main(), we can see that the control of the tick
hear and read about ‘task design’, ‘task execution times’ and interval has been largely automated:
‘multi-tasking’ systems. /* Set up simple EOS (60 ms tick interval) */
sEOS_Init_Timer2(60);
In this context, the term ‘task’ is usually used to refer to a In this example, a tick interval of 60 ms is used: this means that the
function that is executed on a periodic basis. ISR (the ‘update’ function) at the heart of sEOS will be invoked
every 60 ms:
In the case of sEOS, the tasks will be implemented using /*--------------------------------------------------------*-
functions which are called from the timer-driven sEOS_ISR()
interrupt service routine.
Invoked periodically by Timer 2 overflow:
see sEOS_Init_Timer2() for timing details.
-*--------------------------------------------------------*/
sEOS_ISR() interrupt INTERRUPT_Timer_2_Overflow
{
…
}
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 153 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 154
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
The ‘automatic’ tick interval control is achieved using the C pre- If using a 12 MHz oscillator, then accurate timing can
processor, and the information included in the project header file usually be obtained over a range of tick intervals from 1 ms
(Main.H): to 60 ms (approximately).
/* Oscillator / resonator frequency (in Hz) e.g. (11059200UL) */
#define OSC_FREQ (12000000UL)
If using other clock frequencies (e.g. 11.0592 MHz), precise
timing can only be obtained at a much more limited range of
/* Number of oscillations per instruction (12, etc) */
...
tick intervals.
#define OSC_PER_INST (12)
If you are developing an application where precise timing is
This information is then used to calculate the required timer reload required, you must check the timing calculations by hand.
values in Simple_EOS.C as follows:
/* Used for manually checking timing (in simulator) */
/* Number of timer increments required (max 65536) */ P2 = Reload_08H;
Inc = ((tLong)TICK_MS * (OSC_FREQ/1000)) / (tLong)OSC_PER_INST; P3 = Reload_08L;
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 155 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 156
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Saving power Using sEOS in your own projects
Using sEOS, we can reduce the power consumption of the When using sEOS in your own applications, you will need to
application by having the processor enter idle mode when it finishes include a copy of the files Simple_EOS.C and Simple_EOS.H in your
executing the ISR. project: the .C file will then need to be edited - in the area indicated
below - in order to match your requirements:
This is achieved through the function sEOS_Go_To_Sleep(): sEOS_ISR() interrupt INTERRUPT_Timer_2_Overflow
{
/*--------------------------------------------------------*-
/* Must manually reset the T2 flag */
TF2 = 0;
sEOS_Go_To_Sleep()
/*===== USER CODE - Begin ============================= */
This operating system enters 'idle mode' between clock ticks
to save power. The next clock tick will return processor /* ADD YOUR FUNCTION (TASK) CALLS HERE... */
to the normal operating state.
/*===== USER CODE - End =============================== */
-*--------------------------------------------------------*/ }
void sEOS_Go_To_Sleep(void)
{
PCON |= 0x01; /* Enter idle mode (generic 8051 version) */
}
Atmel 89S53 11 mA 2 mA 60 A
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 157 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 158
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Is this approach portable? Example: Milk pasteurization
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 159 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 160
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*- /*-------------------------------------------------------------*-
-------------------------------------------------------- --------------------------------------------------------
Port Header file for the milk pasteurization example Milk pasteurization example.
(“Embedded C” Chapter 7)
-*-------------------------------------------------------------*/
-*-------------------------------------------------------------*/
#include "Main.H"
/* ------ Pulse_Count.C ---------------------------------- */ #include "Port.H"
#include "Simple_EOS.H"
/* Connect pulse input to this pin - debounced in software */ #include "Bargraph.H"
sbit Sw_pin = P3^0;
#include "Pulse_Count.H"
/* Connect alarm to this pin (set if pulse is below threshold) */
sbit Alarm_pin = P3^7; /* --------------------------------------------------------------- */
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 161 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 162
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*- /*-------------------------------------------------------------*-
-------------------------------------------------------- ...
Main file for Simple Embedded Operating System (sEOS) for 8051. -*-------------------------------------------------------------*/
void sEOS_Init_Timer2(const tByte TICK_MS)
-- This version for milk-flow-rate monitoring. {
tLong Inc;
-*-------------------------------------------------------------*/ tWord Reload_16;
tByte Reload_08H, Reload_08L;
#include "Main.H"
#include "Simple_EOS.H" /* Timer 2 is configured as a 16-bit timer,
which is automatically reloaded when it overflows */
#include "Pulse_count.H" T2CON = 0x04; /* Load T2 control register */
/*===== USER CODE - Begin ================================== */ TH2 = Reload_08H; /* Load T2 high byte */
RCAP2H = Reload_08H; /* Load T2 reload capt. reg. high byte */
/* Call 'Update' function here */ TL2 = Reload_08L; /* Load T2 low byte */
PULSE_COUNT_Update(); RCAP2L = Reload_08L; /* Load T2 reload capt. reg. low byte */
/*===== USER CODE - End ==================================== */ /* Timer 2 interrupt is enabled, and ISR will be called
} whenever the timer overflows. */
ET2 = 1;
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 163 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 164
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*- /*-------------------------------------------------------------*-
This operating system enters 'idle mode' between clock ticks --------------------------------------------------------
to save power. The next clock tick will return the processor
to the normal operating state. Count pulses from a mechanical switch or similar device.
___
-*-------------------------------------------------------------*/ Responds to falling edge of pulse: |___
void sEOS_Go_To_Sleep(void)
{ -*-------------------------------------------------------------*/
PCON |= 0x01; /* Enter idle mode (generic 8051 version) */
} #include "Main.H"
#include "Port.H"
/*-------------------------------------------------------------*-
---- END OF FILE --------------------------------------- #include "Bargraph.H"
-*-------------------------------------------------------------*/ #include "Pulse_Count.H"
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 165 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 166
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*-
/*-------------------------------------------------------------*-
PULSE_COUNT_Update()
PULSE_COUNT_Init()
This is the main switch function.
Initialisation function for the switch library.
It should be called every 30 ms
-*-------------------------------------------------------------*/ (to allow for typical 20ms debounce time).
void PULSE_COUNT_Init(void)
{ -*-------------------------------------------------------------*/
Sw_pin = 1; /* Use this pin for input */ void PULSE_COUNT_Update(void)
{
/* The tests (see text) */ /* Clear timer flag */
Test4 = LO_LEVEL; TF2 = 0;
Test3 = LO_LEVEL;
Test2 = LO_LEVEL; /* Shuffle the test results */
Test1 = LO_LEVEL; Test4 = Test3;
Test0 = LO_LEVEL; Test3 = Test2;
} Test2 = Test1;
Test1 = Test0;
/*-------------------------------------------------------------*-
/* Get latest test result */
PULSE_COUNT_Check_Below_Threshold() Test0 = Sw_pin;
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 167 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 168
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/* Calculate average every 45 calls to this task /*-------------------------------------------------------------*-
- maximum count over this period is 9 pulses
if (++Calls_G < 45) */ Bargraph.h (v1.00)
/*-------------------------------------------------------------*-
---- END OF FILE ---------------------------------------
-*-------------------------------------------------------------*/
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 169 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 170
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*- /*-------------------------------------------------------------*-
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 171 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 172
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*- Conclusions
BARGRAPH_Update()
The simple operating system (‘sEOS’) introduced in this
Update the bargraph display.
seminar imposes a very low processor load but is nonetheless
-*-------------------------------------------------------------*/ flexible and useful.
void BARGRAPH_Update(void)
{
tBargraph Data = Data_G - BARGRAPH_MIN;
The simple nature of sEOS also provides other benefits. For
Pin0 = ((Data >= M9_1_G) == BARGRAPH_ON);
Pin1 = ((Data >= M9_2_G) == BARGRAPH_ON); example, it means that developers themselves can, very
Pin2 = ((Data >= M9_3_G) == BARGRAPH_ON); rapidly, port the OS onto a new microcontroller
Pin3 = ((Data >= M9_4_G) == BARGRAPH_ON);
Pin4 = ((Data >= M9_5_G) == BARGRAPH_ON); environment. It also means that the architecture may be
Pin5
Pin6
=
=
((Data
((Data
>=
>=
M9_6_G)
M9_7_G)
==
==
BARGRAPH_ON);
BARGRAPH_ON);
readily adapted to meet the needs of a particular application.
Pin7 = ((Data >= M9_8_G) == BARGRAPH_ON);
}
/*-------------------------------------------------------------*- Perhaps the most important side-effect of this form of simple OS is that
---- END OF FILE ---------------------------------------
-*-------------------------------------------------------------*/
- unlike a traditional ‘real-time operating system’ - it becomes part of the
application itself, rather than forming a separate code layer.
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 173 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 174
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Preparation for the next seminar
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 175 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 176
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Introduction
Waking
Waking Attacking
Attacking
For example, the system might only move between State A
and State B if a particular input is received within X seconds
of a system output being generated.
Growling
Growling
The autopilot system discussed at the start of this seminar
might follow this pattern, as might a control system for a
washing machine, or an intruder alarm system.
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 177 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 178
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
For completeness, we will mention on further possibility:
Implementing a Multi-State (Timed) system
Multi-State (Input)
This is a comparatively rare form of system, in which the We can describe the time-driven, multi-state architecture as follows:
transition between states (and behaviour in each state)
The system will operate in two or more states.
depends only on the system inputs.
Each state may be associated with one or more function
For example, the system might only move between State A calls.
and State B if a particular input is received. It will remain
Transitions between states will be controlled by the passage
indefinitely in State A if this input is not received.
of time.
Such systems have no concept of time, and - therefore - no Transitions between states may also involve function calls.
way of implementing timeout or similar behaviours. We will
not consider such systems in this course.
Please note that, in order to ease subsequent maintenance tasks, the
system states should not be arbitrarily named, but should - where
In this seminar, we will consider how the Multi-State (Time) and possible - reflect a physical state observable by the user and / or
Multi-State (Input / Time) architectures can be implemented in C. developer.
Please also note that the system states will usually be represented
by means of a switch statement in the operating system ISR.
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 179 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 180
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Example: Traffic light sequencing
In this case, the various states are easily identified:
Time Red
Red-Amber
Red
Green
Amber
Amber
Green
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 181 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 182
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*-
In this simple case, we do not require function calls from (or Main.c (v1.00)
between) system states: the required behaviour will be implemented --------------------------------------------------------
directly through control of the (three) port pins which – in the final
Traffic light example.
system – would be connected to appropriate bulbs.
-*-------------------------------------------------------------*/
For example: #include "Main.H"
#include "Port.H"
case RED: #include "Simple_EOS.H"
{
Red_light = ON; #include "T_Lights.H"
Amber_light = OFF;
Green_light = OFF; /* --------------------------------------------------------------- */
... void main(void)
{
/* Prepare to run traffic sequence */
TRAFFIC_LIGHTS_Init(RED);
/*-------------------------------------------------------------*-
---- END OF FILE ---------------------------------------
-*-------------------------------------------------------------*/
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 183 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 184
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*- /*-------------------------------------------------------------*-
-------------------------------------------------------- -*-------------------------------------------------------------*/
/* ------ Public data type declarations ----------------------- */ /* Easy to change logic here */
#define ON 0
/* Possible system states */ #define OFF 1
typedef enum {RED, RED_AND_AMBER, GREEN, AMBER} eLight_State;
/* Times in each of the (four) possible light states
/* ------ Public function prototypes -------------------------- */ (Times are in seconds) */
#define RED_DURATION 20
void TRAFFIC_LIGHTS_Init(const eLight_State); #define RED_AND_AMBER_DURATION 5
void TRAFFIC_LIGHTS_Update(void); #define GREEN_DURATION 30
#define AMBER_DURATION 5
#endif
/* Used by sEOS */
static tByte Call_count_G = 0;
/*-------------------------------------------------------------*-
TRAFFIC_LIGHTS_Init()
-*-------------------------------------------------------------*/
void TRAFFIC_LIGHTS_Init(const eLight_State START_STATE)
{
Light_state_G = START_STATE; /* Decide on initial state */
}
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 185 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 186
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*-
case GREEN:
TRAFFIC_LIGHTS_Update() {
Red_light = OFF;
Must be called once per second. Amber_light = OFF;
Green_light = ON;
-*-------------------------------------------------------------*/
void TRAFFIC_LIGHTS_Update(void) if (++Time_in_state == GREEN_DURATION)
{ {
switch (Light_state_G) Light_state_G = AMBER;
{ Time_in_state = 0;
case RED: }
{
Red_light = ON; break;
Amber_light = OFF; }
Green_light = OFF;
case AMBER:
if (++Time_in_state == RED_DURATION) {
{ Red_light = OFF;
Light_state_G = RED_AND_AMBER; Amber_light = ON;
Time_in_state = 0; Green_light = OFF;
}
if (++Time_in_state == AMBER_DURATION)
break; {
} Light_state_G = RED;
Time_in_state = 0;
case RED_AND_AMBER: }
{
Red_light = ON; break;
Amber_light = ON; }
Green_light = OFF; }
}
if (++Time_in_state == RED_AND_AMBER_DURATION)
{ /*-------------------------------------------------------------*-
Light_state_G = GREEN; ---- END OF FILE ---------------------------------------
Time_in_state = 0; -*-------------------------------------------------------------*/
}
break;
}
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 187 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 188
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Example: Animatronic dinosaur The system states
Sleeping:
The dinosaur will be largely motionless, but will be
obviously ‘breathing’. Irregular snoring noises, or slight
movements during this time will add interest for the
audience.
Waking:
The dinosaur will begin to wake up. Eyelids will begin to
flicker. Breathing will become more rapid.
Growling:
Eyes will suddenly open, and the dinosaur will emit a very
loud growl. Some further movement and growling will
follow.
Attacking:
Rapid ‘random’ movements towards the audience. Lots of
noise (you should be able to hear this from the next floor in
Sleeping
Sleeping
the museum).
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 189 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 190
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*- /*-------------------------------------------------------------*-
DINOSAUR_Init()
Dinosaur.C (v1.00) -*-------------------------------------------------------------*/
void DINOSAUR_Init(void)
-------------------------------------------------------- {
/* Initial dinosaur state */
Demonstration of multi-state (timed) architecture: Dinosaur_state_G = SLEEPING;
Dinosaur control system. }
-*-------------------------------------------------------------*/ /*-------------------------------------------------------------*-
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 191 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 192
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
case GROWLING:
{ /*-------------------------------------------------------------*/
/* Call relevant function */ void DINOSAUR_Perform_Sleep_Movements(void)
DINOSAUR_Growl(); {
/* Demo only... */
if (++Time_in_state_G == GROWLING_DURATION) P1 = (tByte) Dinosaur_state_G;
{ P2 = Time_in_state_G;
Dinosaur_state_G = ATTACKING; }
Time_in_state_G = 0;
} /*-------------------------------------------------------------*/
void DINOSAUR_Perform_Waking_Movements(void)
break; {
} /* Demo only... */
P1 = (tByte) Dinosaur_state_G;
case ATTACKING: P2 = Time_in_state_G;
{ }
/* Call relevant function */
DINOSAUR_Perform_Attack_Movements(); /*-------------------------------------------------------------*/
void DINOSAUR_Growl(void)
if (++Time_in_state_G == ATTACKING_DURATION) {
{ /* Demo only... */
Dinosaur_state_G = SLEEPING; P1 = (tByte) Dinosaur_state_G;
Time_in_state_G = 0; P2 = Time_in_state_G;
} }
break; /*-------------------------------------------------------------*/
} void DINOSAUR_Perform_Attack_Movements(void)
} {
} /* Demo only... */
P1 = (tByte) Dinosaur_state_G;
P2 = Time_in_state_G;
}
/*-------------------------------------------------------------*-
---- END OF FILE ---------------------------------------
-*-------------------------------------------------------------*/
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 193 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 194
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Implementing a Multi-State (Input/Timed) system Implementing state timeouts
The system will operate in two or more states. Consider the following - informal - system requirements:
Each state may be associated with one or more function The pump should be run for 10 seconds. If, during this time,
calls. no liquid is detected in the outflow tank, then the pump
Transitions between states may be controlled by the passage should be switched off and ‘low water’ warning should be
of time, by system inputs or a combination of time and sounded. If liquid is detected, the pump should be run for a
inputs. further 45 seconds, or until the ‘high water’ sensor is
activated (whichever is first).
Transitions between states may also involve function calls.
After the front door is opened, the correct password must be
entered on the control panel within 30 seconds or the alarm
will sound.
The ‘down flap’ signal will be issued. If, after 50 ms, no
flap movement is detected, it should be concluded that the
flap hydraulics are damaged. The system should then alert
the user and enter manual mode.
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 195 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 196
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Example: Controller for a washing machine
Here is a brief description of the way in which we expect the system
Water
Valve to operate:
Water
Heater 1. The user selects a wash program (e.g. ‘Wool’, ‘Cotton’) on
the selector dial.
Start
Switch
Water
Pump
4. The water valve is opened to allow water into the wash drum.
Temperature
Sensor
Door
lock
Detergent
5. If the wash program involves detergent, the detergent hatch is
Hatch
opened. When the detergent has been released, the detergent
hatch is closed.
6. When the ‘full water level’ is sensed, the water valve is
closed.
7. If the wash program involves warm water, the water heater is
switched on. When the water reaches the correct
temperature, the water heater is switched off.
8. The washer motor is turned on to rotate the drum. The motor
then goes through a series of movements, both forward and
reverse (at various speeds) to wash the clothes. (The precise
set of movements carried out depends on the wash program
that the user has selected.) At the end of the wash cycle, the
motor is stopped.
9. The pump is switched on to drain the drum. When the drum
is empty, the pump is switched off.
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 197 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 198
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*-
Washer.C (v1.01)
The Input / Timed architecture discussed here is by no means unique to
‘white goods’ (such as washing machines). --------------------------------------------------------
then be used to ensure that each phase of the manoeuvre /* ------ Private function prototypes ------------------------- */
completes correctly. tByte WASHER_Read_Selector_Dial(void);
bit WASHER_Read_Start_Switch(void);
bit WASHER_Read_Water_Level(void);
bit WASHER_Read_Water_Temperature(void);
void WASHER_Control_Detergent_Hatch(bit);
void WASHER_Control_Door_Lock(bit);
void WASHER_Control_Motor(bit);
void WASHER_Control_Pump(bit);
void WASHER_Control_Water_Heater(bit);
void WASHER_Control_Water_Valve(bit);
#define OFF 0
#define ON 1
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 199 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 200
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/* --------------------------------------------------------------- */
/* ------ Private variables ----------------------------------- */ void WASHER_Update(void)
{
static eSystem_state System_state_G; /* Call once per second */
switch (System_state_G)
static tWord Time_in_state_G; {
case INIT:
static tByte Program_G; {
/* For demo purposes only */
/* Ten different programs are supported Debug_port = (tByte) System_state_G;
Each one may or may not use detergent */
static tByte Detergent_G[10] = {1,1,1,0,0,1,0,1,1,0}; /* Set up initial state */
/* Motor is off */
/* Each one may or may not use hot water */ WASHER_Control_Motor(OFF);
static tByte Hot_Water_G[10] = {1,1,1,0,0,1,0,1,1,0};
/* Pump is off */
/* --------------------------------------------------------------- */ WASHER_Control_Pump(OFF);
void WASHER_Init(void)
{ /* Heater is off */
System_state_G = INIT; WASHER_Control_Water_Heater(OFF);
}
/* Valve is closed */
WASHER_Control_Water_Valve(OFF);
/* Change state */
System_state_G = START;
break;
}
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 201 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 202
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
case START: case FILL_DRUM:
{ {
/* For demo purposes only */ /* For demo purposes only */
Debug_port = (tByte) System_state_G; Debug_port = (tByte) System_state_G;
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 203 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 204
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
case HEAT_WATER: case WASH_01:
{ {
/* For demo purposes only */ /* For demo purposes only */
Debug_port = (tByte) System_state_G; Debug_port = (tByte) System_state_G;
/* Remain in this state until water is hot /* All wash program involve WASH_01
NOTE: Timeout facility included here */ Drum is slowly rotated to ensure clothes are fully wet */
if (++Time_in_state_G >= MAX_WATER_HEAT_DURATION) WASHER_Control_Motor(ON);
{
/* Should have warmed the water by now... */ if (++Time_in_state_G >= WASH_01_DURATION)
System_state_G = ERROR; {
} System_state_G = WASH_02;
Time_in_state_G = 0;
/* Check the water temperature */ }
if (WASHER_Read_Water_Temperature() == 1)
{ break;
/* Water is at required temperature */ }
/* Ready to go to next state */
System_state_G = WASH_01; /* REMAINING WASH PHASES OMITTED HERE ... */
Time_in_state_G = 0;
} case WASH_02:
{
break; /* For demo purposes only */
} Debug_port = (tByte) System_state_G;
break;
}
case ERROR:
{
/* For demo purposes only */
Debug_port = (tByte) System_state_G;
break;
}
}
}
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 205 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 206
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/* --------------------------------------------------------------- */
tByte WASHER_Read_Selector_Dial(void)
{
Conclusions
/* User code here... */
This seminar has discussed the implementation of multi-state
return 0;
} (timed) and multi-state (input / timed) systems. Used in
conjunction with an operating system like that presented in
/* --------------------------------------------------------------- */
bit WASHER_Read_Start_Switch(void) “Embedded C” Chapter 7, this flexible system architecture is in
{
/* Simplified for demo ... */
widespread use in embedded applications.
if (Start_pin == 0)
{
/* Start switch pressed */
return 1;
}
else
{
return 0;
}
}
/* --------------------------------------------------------------- */
bit WASHER_Read_Water_Level(void)
{
/* User code here... */
return 1;
}
/* --------------------------------------------------------------- */
bit WASHER_Read_Water_Temperature(void)
{
/* User code here... */
return 1;
}
/* --------------------------------------------------------------- */
void WASHER_Control_Detergent_Hatch(bit State)
{
bit Tmp = State;
/* User code here... */
}
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 207 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 208
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Preparation for the next seminar
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 209 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 210
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Overview of this seminar
7
5
9
MAX 233
Rx 19
20
Tx 18
6
1
1
Connect together: 6, 9
Pins 12 & 17
Pins 11 & 15
Pins 16 & 10
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 211 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 212
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
What is ‘RS-232’? Basic RS-232 Protocol
In 1997 the Telecommunications Industry Association released RS-232 is a character-oriented protocol. That is, it is intended to be
what is formally known as TIA-232 Version F, a serial used to send single 8-bit blocks of data. To transmit a byte of data
communication protocol which has been universally referred to as over an RS-232 link, we generally encode the information as
‘RS-232’ since its first ‘Recommended Standard’ appeared in the follows:
1960s. Similar standards (V.28) are published by the International
We send a ‘Start’ bit.
Telecommunications Union (ITU) and by CCITT (The Consultative
Committee International Telegraph and Telephone). We send the data (8 bits).
The ‘RS-232’ standard includes details of: We send a ‘Stop’ bit (or bits).
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 213 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 214
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Asynchronous data transmission and baud rates RS-232 voltage levels
RS-232 uses an asynchronous protocol. The threshold levels used by the receiver are +3 V and -3 V
and the lines are inverted.
Both ends of the communication link have an internal clock,
running at the same rate. The data (in the case of RS-232, The maximum voltage allowed is +/- 15V.
the ‘Start’ bit) is then used to synchronise the clocks, if
necessary, to ensure successful data transfer.
Note that these voltages cannot be obtained directly from the
naked microcontroller port pins: some form of interface
RS-232 generally operates at one of a (restricted) range of hardware is required.
baud rates.
For example, the Maxim Max232 and Max233 are popular
Typically these are: 75, 110, 300, 1200, 2400, 4800, 9600, and widely-used line driver chips.
14400, 19200, 28800, 33600, 56000, 115000 and (rarely)
330000 baud. Vcc
1.0 µF
supported.
5
Max
9
19
Rx To Tx pin ( P3.1)
18
233 1
Tx
6
20
1
To Rx pin ( P3.0)
6,9
Connect together:
Pins 12 & 17
Pins 11 & 15
Pins 16 & 10
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 215 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 216
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
The software architecture Overview
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 217 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 218
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Using the on-chip U(S)ART for RS-232 communications Serial port registers
The UART is full duplex, meaning it can transmit and The serial port control and status register is the special function
receive simultaneously. register SCON. This register contains the mode selection bits (and
the serial port interrupt bits, TI and RI: not used here).
It is also receive-buffered, meaning it can commence
reception of a second byte before a previously received byte
SBUF is the receive and transmit buffer of serial interface.
has been read from the receive register.
Writing to SBUF loads the transmit register and initiates
The serial port can operate in 4 modes (one synchronous transmission.
mode, three asynchronous modes). SBUF = 0x0D; /* Output CR */
We are primarily interested in Mode 1. Reading out SBUF accesses a physically separate receive register.
/* Read the data from UART */
In this mode, 10 bits are transmitted (through TxD) or Data = SBUF;
received (through RxD): a start bit (0), 8 data bits (lsb first),
and a stop bit (1).
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 219 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 220
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Baud rate generation Why use 11.0592 MHz crystals?
We are primarily concerned here with the use of the serial It is very important to appreciate that it is not generally possible to
port in Mode 1. produce standard baud rates (e.g. 9600) using Timer 1 (or Timer 2),
In this mode the baud rate is determined by the overflow rate unless you use an 11.0592 MHz crystal oscillator.
of Timer 1 or Timer 2.
We focus on the use of Timer 1 for baud rate generation. Remember: this is an asynchronous protocol, and relies for correct
operation on the fact that both ends of the connection are working
at the same baud rate. In practice, you can generally work with a
The baud rate is determined by the Timer 1 overflow rate and the difference in baud rates at both ends of the connection by up to 5%,
value of SMOD follows: but no more.
2 × Frequency SMOD
Baud rate (Mode 1) = oscillator
32 × Instructionscycle × (256 − TH 1)
Despite the possible 5% margin, it is always good policy to get the baud
Where:
rate as close as possible to the standard value because, in the field,
SMOD …is the ‘double baud rate’ bit in the PCON register; there may be significant temperature variations between the oscillator in
Frequencyoscillator …is the oscillator / resonator frequency; the PC and that in the embedded system.
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 221 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 222
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
PC Software What about printf()?
If your desktop computer is running Windows (95, 98, NT, 2000), We do not generally recommend the use of standard library
then a simple but effective option is the ‘Hyperterminal’ application function “printf()”, because:
which is included with all of these operating systems.
this function sends data immediately to the UART. As a
result, the duration of the transmission is often too long to be
safely handled in a co-operatively scheduled application,
and,
most implementations of printf() do not incorporate
timeouts, making it possible that use of this functions can
‘hang’ the whole application if errors occur.
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 223 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 224
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
RS-232 and 8051: Overall strengths and weaknesses Example: Displaying elapsed time on a PC
RS-232 support is part of the 8051 core: applications based on RS-232
are very portable.
Vcc
At the PC end too, RS-232 is ubiquitous: every PC has one or more 1.0 µF
RS-232 ports.
Links can - with modern tranceiver chips - be up to 30 m (100 ft) in 7
length.
5
9
Because of the hardware support, RS-232 generally imposes a low
MAX 233
software load. Rx 19
20
Tx 18
BUT:
6
1
1
Connect together: 6, 9
RS-232 is a peer-to-peer protocol (unlike, for example, RS-485): you
Pins 12 & 17
can only connect one microcontroller directly (simultaneously) to each
Pins 11 & 15
PC.
Pins 16 & 10
RS-232 has little or no error checking at the hardware level (unlike, for
example, CAN): if you want to be sure that the data you received at the
PC is valid, you need to carry out checks in software.
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 225 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 226
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*-
Main.c (v1.00)
--------------------------------------------------------
-*-------------------------------------------------------------*/
#include "Main.H"
#include "Port.H"
#include "Simple_EOS.H"
#include "PC_O_T1.h"
#include "Elap_232.h"
/* --------------------------------------------------------------- */
void main(void)
{
/* Set baud rate to 9600 */
PC_LINK_O_Init_T1(9600);
/*-------------------------------------------------------------*-
---- END OF FILE ---------------------------------------
-*-------------------------------------------------------------*/
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 227 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 228
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*- /*-------------------------------------------------------------*/
Simple library function for keeping track of elapsed time if (++Sec_G == 60)
Demo version to display time on PC screen via RS232 link. {
Sec_G = 0;
-*-------------------------------------------------------------*/
if (++Min_G == 60)
#include "Main.h" {
#include "Elap_232.h" Min_G = 0;
#include "PC_O.h"
if (++Hou_G == 24)
/* ------ Public variable definitions ------------------------- */ {
Hou_G = 0;
tByte Hou_G; }
tByte Min_G; }
tByte Sec_G; }
Init function for simple library displaying elapsed time on PC /* We use the "seconds" data to turn on and off the colon
via RS-232 link. (between hours and minutes) */
if ((Sec_G % 2) == 0)
-*-------------------------------------------------------------*/ {
void Elapsed_Time_RS232_Init(void) Time_Str[17] = ':';
{ Time_Str[20] = ':';
Hou_G = 0; }
Min_G = 0; else
Sec_G = 0; {
} Time_Str[17] = ' ';
Time_Str[20] = ' ';
}
PC_LINK_O_Write_String_To_Buffer(Time_Str);
}
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 229 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 230
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*-
/*-------------------------------------------------------------*/
PC_LINK_O_Init_T1()
void PC_LINK_O_Update(void)
This version uses T1 for baud rate generation. {
/* Deal with transmit bytes here.
Uses 8051 (internal) UART hardware Are there any data ready to send? */
if (Out_written_index_G < Out_waiting_index_G)
-*-------------------------------------------------------------*/ {
void PC_LINK_O_Init_T1(const tWord BAUD_RATE) PC_LINK_O_Send_Char(Tran_buffer[Out_written_index_G]);
{
PCON &= 0x7F; /* Set SMOD bit to 0 (don't double baud rates) */ Out_written_index_G++;
}
/* Receiver disabled else
8-bit data, 1 start bit, 1 stop bit, variable baud */ {
SCON = 0x42; /* No data to send - just reset the buffer index */
Out_waiting_index_G = 0;
TMOD |= 0x20; /* T1 in mode 2, 8-bit auto reload */ Out_written_index_G = 0;
}
TH1 = (256 - (tByte)((((tLong)OSC_FREQ / 100) * 3125) }
/ ((tLong) BAUD_RATE * OSC_PER_INST * 1000)));
/*-------------------------------------------------------------*/
TL1 = TH1;
TR1 = 1; /* Run the timer */ void PC_LINK_O_Write_String_To_Buffer(const char* const STR_PTR)
TI = 1; /* Send first character (dummy) */ {
tByte i = 0;
/* Set up the buffers for reading and writing */
Out_written_index_G = 0; while (STR_PTR[i] != '\0')
Out_waiting_index_G = 0; {
PC_LINK_O_Write_Char_To_Buffer(STR_PTR[i]);
/* Interrupt *NOT* enabled */ i++;
ES = 0; }
} }
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 231 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 232
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*/
void PC_LINK_O_Write_Char_To_Buffer(const char CHARACTER) sEOS_ISR() interrupt INTERRUPT_Timer_2_Overflow
{ {
/* Write to the buffer *only* if there is space TF2 = 0; /* Must manually reset the T2 flag */
(No error reporting in this simple library...) */
if (Out_waiting_index_G < TRAN_BUFFER_LENGTH) /*===== USER CODE - Begin ================================== */
{ /* Call RS-232 update function every 5ms */
Tran_buffer[Out_waiting_index_G] = CHARACTER; PC_LINK_O_Update();
Out_waiting_index_G++;
} /* This ISR is called every 5 ms
} - only want to update time every second */
if (++Call_count_G == 200)
/*-------------------------------------------------------------*/ {
void PC_LINK_O_Send_Char(const char CHARACTER) /* Time to update time */
{ Call_count_G = 0;
tLong Timeout1 = 0;
/* Call time update function */
if (CHARACTER == '\n') Elapsed_Time_RS232_Update();
{ }
Timeout1 = 0; /*===== USER CODE - End ==================================== */
while ((++Timeout1) && (TI == 0)); }
if (Timeout1 == 0)
{
/* UART did not respond - error
No error reporting in this simple library... */
return;
}
TI = 0;
SBUF = 0x0d; /* Output CR */
}
Timeout1 = 0;
while ((++Timeout1) && (TI == 0));
if (Timeout1 == 0)
{
/* UART did not respond - error
No error reporting in this simple library... */
return;
}
TI = 0;
SBUF = CHARACTER;
}
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 233 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 234
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Example: Data acquisition void MENU_Command_Processor(void)
{
char Ch;
In this section, we give an example of a simple data acquisition
if (First_time_only_G == 0)
system with a serial-menu architecture. {
First_time_only_G = 1;
MENU_Show_Menu();
In this case, using the menu, the user can determine the state of the }
input pins on Port 1 or Port 2: /* Check for user inputs */
PC_LINK_IO_Update();
Ch = PC_LINK_IO_Get_Char_From_Buffer();
if (Ch != PC_LINK_IO_NO_CHAR)
{
MENU_Perform_Task(Ch);
MENU_Show_Menu();
}
}
void MENU_Show_Menu(void)
{
PC_LINK_IO_Write_String_To_Buffer("Menu:\n");
PC_LINK_IO_Write_String_To_Buffer("a - Read P1\n");
PC_LINK_IO_Write_String_To_Buffer("b - Read P2\n\n");
PC_LINK_IO_Write_String_To_Buffer("? : ");
}
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 235 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 236
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
void MENU_Perform_Task(char c)
{ sEOS_ISR() interrupt INTERRUPT_Timer_2_Overflow
PC_LINK_IO_Write_Char_To_Buffer(c); /* Echo the menu option */ {
PC_LINK_IO_Write_Char_To_Buffer('\n'); TF2 = 0; /* Must manually reset the T2 flag */
case 'b':
case 'B':
{
Get_Data_From_Port2();
break;
}
}
}
void Get_Data_From_Port1(void)
{
tByte Port1 = Data_Port1;
char String[11] = "\nP1 = XXX\n\n";
PC_LINK_IO_Write_String_To_Buffer(String);
}
void Get_Data_From_Port2(void)
{
tByte Port2 = Data_Port2;
char String[11] = "\nP2 = XXX\n\n";
PC_LINK_IO_Write_String_To_Buffer(String);
}
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 237 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 238
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Conclusions Preparation for the next seminar
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 239 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 240
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Introduction
Bell box
Door Window
Seminar 9: D
Control
panel
W
W W
Bell box
Door Window
1 2 3
D W
Control 4 5 6
panel W
7 8 9
* 0 #
Statue
W W
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 241 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 242
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
System Operation Key software components used in this example
When initially activated, the system is in ‘Disarmed’ state. This case study uses the following software components:
In Disarmed state, the sensors are ignored. The alarm does Software to control external port pins (to activate the
not sound. The system remains in this state until the user external bell), as introduced in “Embedded C” Chapter 3.
enters a valid password via the keypad (in our demonstration
Switch reading, as discussed in “Embedded C” Chapter 4, to
system, the password is “1234”). When a valid password is
process the inputs from the door and window sensors. Note
entered, the systems enters ‘Arming’ state.
that - in this simple example (intended for use in the
In Arming state, the system waits for 60 seconds, to allow simulator) - no switch debouncing is carried out. This
the user to leave the area before the monitoring process feature can be added, if required, without difficulty.
begins. After 60 seconds, the system enters ‘Armed’ state.
The embedded operating system, sEOS, introduced in
In Armed state, the status of the various system sensors is “Embedded C” Chapter 7.
monitored. If a window sensor is tripped, the system enters
A simple ‘keypad’ library, based on a bank of switches.
‘Intruder’ state. If the door sensor is tripped, the system
Note that - to simplify the use of the keypad library in the
enters ‘Disarming’ state. The keypad activity is also
simulator - we have assumed the presence of only eight keys
monitored: if a correct password is typed in, the system
in the example program (0 - 7). This final system would
enters ‘Disarmed’ state.
probably use at least 10 keys: support for additional keys can
In Disarming state, we assume that the door has been be easily added if required.
opened by someone who may be an authorised system user.
The RS-232 library (from “Embedded C” Chapter 9) is used
The system remains in this state for up to 60 seconds, after
to illustrate the operation of the program. This library would
which - by default - it enters Intruder state. If, during the 60-
not be necessary in the final system (but it might be useful to
second period, the user enters the correct password, the
retain it, to support system maintenance).
system enters ‘Disarmed’ state.
In Intruder state, an alarm will sound. The alarm will keep
sounding (indefinitely), until the correct password is entered.
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 243 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 244
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Running the program The software
/*-------------------------------------------------------------*-
Port.H (v1.00)
--------------------------------------------------------
'Port Header' (see Chap 5) for project INTRUDER (see Chap 10)
-*-------------------------------------------------------------*/
#define KEYPAD_PORT P2
sbit K0 = KEYPAD_PORT^0;
sbit K1 = KEYPAD_PORT^1;
sbit K2 = KEYPAD_PORT^2;
sbit K3 = KEYPAD_PORT^3;
sbit K4 = KEYPAD_PORT^4;
sbit K5 = KEYPAD_PORT^5;
sbit K6 = KEYPAD_PORT^6;
sbit K7 = KEYPAD_PORT^7;
/*-------------------------------------------------------------*-
---- END OF FILE ---------------------------------------
-*-------------------------------------------------------------*/
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 245 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 246
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/*-------------------------------------------------------------*- /*-------------------------------------------------------------*-
-------------------------------------------------------- -*-------------------------------------------------------------*/
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 247 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 248
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
void INTRUDER_Update(void) case ARMING:
{ {
/* Incremented every time */ if (New_state_G)
if (State_call_count_G < 65534) {
{ PC_LINK_O_Write_String_To_Buffer("\nArming...");
State_call_count_G++; New_state_G = 0;
} }
break;
}
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 249 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 250
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
case ARMED: case DISARMING:
{ {
if (New_state_G) if (New_state_G)
{ {
PC_LINK_O_Write_String_To_Buffer("\nArmed"); PC_LINK_O_Write_String_To_Buffer("\nDisarming...");
New_state_G = 0; New_state_G = 0;
} }
/* First, check the window sensors */ /* Remain here for 60 seconds (50 ms tick assumed)
if (INTRUDER_Check_Window_Sensors() == 1) to allow user to enter the password
{ - after time up, sound alarm. */
/* An intruder detected */ if (++State_call_count_G > 1200)
System_state_G = INTRUDER; {
New_state_G = 1; System_state_G = INTRUDER;
State_call_count_G = 0; New_state_G = 1;
break; State_call_count_G = 0;
} break;
}
/* Next, check the door sensors */
if (INTRUDER_Check_Door_Sensor() == 1) /* Still need to check the window sensors */
{ if (INTRUDER_Check_Window_Sensors() == 1)
/* May be authorised user - go to 'Disarming' state */ {
System_state_G = DISARMING; /* An intruder detected */
New_state_G = 1; System_state_G = INTRUDER;
State_call_count_G = 0; New_state_G = 1;
break; State_call_count_G = 0;
} break;
}
/* Finally, check for correct password */
if (INTRUDER_Get_Password_G() == 1) /* Finally, check for correct password */
{ if (INTRUDER_Get_Password_G() == 1)
System_state_G = DISARMED; {
New_state_G = 1; System_state_G = DISARMED;
State_call_count_G = 0; New_state_G = 1;
break; State_call_count_G = 0;
} break;
}
break;
} break;
}
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 251 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 252
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
case INTRUDER:
{ bit INTRUDER_Get_Password_G(void)
if (New_state_G) {
{ signed char Key;
PC_LINK_O_Write_String_To_Buffer("\n** INTRUDER! **"); tByte Password_G_count = 0;
New_state_G = 0; tByte i;
}
/* Update the keypad buffer */
/* Sound the alarm! */ KEYPAD_Update();
INTRUDER_Sound_Alarm();
/* Are there any new data in the keypad buffer? */
/* Keep sounding alarm until we get correct password */ if (KEYPAD_Get_Data_From_Buffer(&Key) == 0)
if (INTRUDER_Get_Password_G() == 1) {
{ /* No new data - password can't be correct */
System_state_G = DISARMED; return 0;
New_state_G = 1; }
State_call_count_G = 0;
} /* If we are here, a key has been pressed */
if (Position_G == 0)
{
PC_LINK_O_Write_Char_To_Buffer('\n');
}
PC_LINK_O_Write_Char_To_Buffer(Key);
Input_G[Position_G] = Key;
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 253 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 254
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
/* Have we got four numbers? */
if ((++Position_G) == 4) bit INTRUDER_Check_Window_Sensors(void)
{ {
Position_G = 0; /* Just a single window 'sensor' here
Password_G_count = 0; - easily extended. */
if (Window_sensor_pin == 0)
/* Check the password */ {
for (i = 0; i < 4; i++) /* Intruder detected... */
{ PC_LINK_O_Write_String_To_Buffer("\nWindow damaged");
if (Input_G[i] == Password_G[i]) return 1;
{ }
Password_G_count++;
} /* Default */
} return 0;
} }
if (Password_G_count == 4) /* --------------------------------------------------------------- */
{ bit INTRUDER_Check_Door_Sensor(void)
/* Password correct */ {
return 1; /* Single door sensor (access route) */
} if (Door_sensor_pin == 0)
else {
{ /* Someone has opened the door... */
/* Password NOT correct */ PC_LINK_O_Write_String_To_Buffer("\nDoor open");
return 0; return 1;
} }
}
/* Default */
return 0;
}
/* --------------------------------------------------------------- */
void INTRUDER_Sound_Alarm(void)
{
if (Alarm_bit)
{
/* Alarm connected to this pin */
Sounder_pin = 0;
Alarm_bit = 0;
}
else
{
Sounder_pin = 1;
Alarm_bit = 1;
}
}
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 255 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 256
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
void KEYPAD_Update(void)
{ bit KEYPAD_Scan(char* const pKey)
char Key; {
char Key = KEYPAD_NO_NEW_DATA;
/* Scan keypad here... */
if (KEYPAD_Scan(&Key) == 0) if (K0 == 0) { Key = '0'; }
{ if (K1 == 0) { Key = '1'; }
/* No new key data - just return */ if (K2 == 0) { Key = '2'; }
return; if (K3 == 0) { Key = '3'; }
} if (K4 == 0) { Key = '4'; }
if (K5 == 0) { Key = '5'; }
/* Want to read into index 0, if old data has been read if (K6 == 0) { Key = '6'; }
(simple ~circular buffer). */ if (K7 == 0) { Key = '7'; }
if (KEYPAD_in_waiting_index == KEYPAD_in_read_index)
{ if (Key == KEYPAD_NO_NEW_DATA)
KEYPAD_in_waiting_index = 0; {
KEYPAD_in_read_index = 0; /* No key pressed */
} Old_key_G = KEYPAD_NO_NEW_DATA;
Last_valid_key_G = KEYPAD_NO_NEW_DATA;
/* Load keypad data into buffer */
KEYPAD_recv_buffer[KEYPAD_in_waiting_index] = Key; return 0; /* No new data */
}
if (KEYPAD_in_waiting_index < KEYPAD_RECV_BUFFER_LENGTH)
{ /* A key has been pressed: debounce by checking twice */
/* Increment without overflowing buffer */ if (Key == Old_key_G)
KEYPAD_in_waiting_index++; {
} /* A valid (debounced) key press has been detected */
}
/* Must be a new key to be valid - no 'auto repeat' */
if (Key != Last_valid_key_G)
bit KEYPAD_Get_Data_From_Buffer(char* const pKey) {
{ /* New key! */
/* If there is new data in the buffer */ *pKey = Key;
if (KEYPAD_in_read_index < KEYPAD_in_waiting_index) Last_valid_key_G = Key;
{
*pKey = KEYPAD_recv_buffer[KEYPAD_in_read_index]; return 1;
}
KEYPAD_in_read_index++; }
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 257 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 258
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
sEOS_ISR() interrupt INTERRUPT_Timer_2_Overflow
{
Extending and modifying the system
TF2 = 0; /* Must manually reset the T2 flag */
/* Call intruder update function */ How would you add additional nodes?
INTRUDER_Update();
} (See “Patterns for Time-Triggered Embedded Systems, Part F)
/*===== USER CODE - End ==================================== */
}
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 259 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 260
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Conclusions
This case study has illustrated most of the key features of embedded
C, as discussed throughout the earlier sessions in this course.
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 261 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 262
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Overview
Seminar 10: In this session, we will discuss the design of software to control a
Case Study: small mobile robot.
Controlling a
Mobile Robot
http://www.microrobotna.com
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 263 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 264
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
What can the robot do? The robot brain
The robot has IR sensors and transmitters that allow him to detect a Mr Line is controlled by an 8051 microcontroller (an AT89C2051).
black line on a white surface - and follow it.
We’ll use a pin-compatible AT89C4051 in this study.
http://www.microrobotna.com
http://www.microrobotna.com
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 265 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 266
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
How does the robot move? Pulse-width modulation
Time
x
Duty cycle (%) = x+y
× 100
1
Frequency = x+y
, where x and y are in seconds.
The key point to note is that the average voltage seen by the load is
http://www.microrobotna.com given by the duty cycle multiplied by the load voltage.
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 267 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 268
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
Software PWM The resulting code
PWM_PERIOD_G
PWM_G
PWM_position_G
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 269 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 270
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.
More about the robot Conclusions
http://www.le.ac.uk/engineering/mjp9/robot.htm
COPYRIGHT © MICHAEL J. PONT, 2001-2003. Contains material from: PES I - 271 COPYRIGHT © M ICHAEL J. PONT, 2001-2003. Contains material from: PES I - 272
Pont, M.J. (2002) “Embedded C”, Addison-Wesley. Pont, M.J. (2002) “Embedded C”, Addison-Wesley.