Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Interfacing with C plus plus-programing communication with microcontrolers (K. Bentley, 2006)

.pdf
Скачиваний:
192
Добавлен:
12.08.2013
Размер:
3.18 Mб
Скачать

296 9 PROGRAM DEVELOPMENT TECHNIQUES

case UPFS: case UPHS: WritePort0(0x11); break;

case BPFS: case BPHS: WritePort0(0x99);

}

}

main.cpp (user program)

//*********************************************************** // Motor driver program using Virtual Functions (chapter 8). //*********************************************************** #include <dos.h>

#include <conio.h> #include <stdio.h> #include <stdlib.h> #include <iostream.h>

#include “motor.h” #include "dcmotor.h" #include "stepper.h"

void main()

{

Motor *MotorPtr; int Selection;

clrscr();

 

 

 

cout << endl << "

MOTOR MENU";

cout << endl << "

~~~~~~~~~~" << endl;

cout << "

1

DC Motor" << endl;

cout << "

2

UPFS" << endl;

cout << "

3

UPHS" << endl;

cout << "

4

BPFS" << endl;

cout << "

5

BPHS" << endl;

cout << "

6

QUIT" << endl;

cout << endl;

 

 

cout << "

Select the MOTOR Number: ";

cin >> Selection;

switch(Selection)

{

case 1: MotorPtr = new DCMotor;

9 PROGRAM DEVELOPMENT TECHNIQUES 297

break;

case 2: MotorPtr = new StepperMotor(UPFS); break;

case 3: MotorPtr = new StepperMotor(UPHS); break;

case 4: MotorPtr = new StepperMotor(BPFS); break;

case 5: MotorPtr = new StepperMotor(BPHS); break;

case 6: return;

default: cout << endl;

cout << " Unspecified Motor type...."; cout << " PRESS a key to END Program!"; getch();

exit(1); // Exits the program

}

if(MotorPtr == NULL)

{

cout << "Memory allocation failed " << endl; getch();

exit(1);

}

cout << "**********************************" << endl; cout << "* CONNECT BOARD POWER SUPPLY NOW *" << endl;

cout << "**********************************" << endl; cout << endl;

cout << " After connecting power,”;

cout << “ press a key to continue " << endl; getch();

cout << endl;

cout << " Keypress changes Speed/Rotation (& Braking)." << endl;

//..... Motor control part starts here .....

MotorPtr->SetSpeed(150); while(!kbhit()) MotorPtr->Forward(); getch(); // clear keyboard buffer

MotorPtr->SetSpeed(255); while(!kbhit()) MotorPtr->Forward(); getch();

MotorPtr->SetSpeed(150);

298 9 PROGRAM DEVELOPMENT TECHNIQUES

while(!kbhit()) MotorPtr->Reverse(); getch();

MotorPtr->SetSpeed(255); while(!kbhit()) MotorPtr->Reverse(); getch();

cout << endl << " Braking Applied!" << endl; while(!kbhit()) MotorPtr->Brake();

getch();

MotorPtr->Off();

//..... Motor control part ends here .....

// Free the memory occupied by the 'Motor' object delete MotorPtr;

}

Main Function File

The programmer uses the objects from the class hierarchy in the development of the main() function. A programmer only needs to know how to apply the user interface of the object classes i.e. the public members of the classes. This information allows the member functions to be used in the main function file according to their specification in the class definition. The programmer using the classes does not need to know the full internal details of the member functions being used. The compiler however, needs to know the exact construct of each class used, and their base classes if any. We fulfil this requirement by including the appropriate header files.

Note that the file motor.h is the only file included in the files dcmotor.h and stepper.h. The file motor.h, in turn, has the files absmotor.h and pport.h included. Therefore, when the compiler reaches the dcmotor.h file, it has already seen the files absmotor.h, pport.h, and motor.h. These files provide all the base class definitions needed for the definition of the DCMotor and

StepperMotor classes.

We have used the objects of the classes Motor, DCMotor, and StepperMotor in the main() function. Therefore, the main() function must include these three header files. These header files are quoted within double quotes which directs the compiler to search for them in the current directory or directories in the search path. Header files that are included within angle brackets (< >) have not been created by us. They reside in the ‘include’ directory of the C/C++ programming software.

This main() function is an ideal place to examine the effect of the sentries we included in the header files. The header files dcmotor.h and stepper.h both include motor.h. Therefore, the header file motor.h is shown included in three

9 PROGRAM DEVELOPMENT TECHNIQUES 299

parts of the complete program listing; once explicitly in the main function file (main.cpp) and twice indirectly via the inclusion of dcmotor.h and stepper.h. However, this does not result in the Motor class actually being defined and included three times. The first inclusion of the file motor.h will provide the class definition and define the sentry MotorH. The pre-processor will ignore any subsequent attempts to include motor.h since MotorH has already been defined. Thererefore, the two cases of indirect inclusion of motor.h in the files dcmotor.h and stepper.h will not be processed. This does not mean that the files dcmotor.h and stepper.h cannot function. They will use the Motor class definition that the compiler has already interpreted (from the first inclusion of motor.h) and so can provide the definitions of the classes DCMotor and

StepperMotor.

Creating Library Files

The linking process uses library files to produce the executable file. Library files are made by combining a number of object files together, and are normally given the file name extension .lib. C/C++ program development software provides utilities to generate library files. The library file will contain the compiled definitions of all the functions that were in each object file. The library file is generated as a binary file and so cannot be read by a programmer.

Project Files and Make Files

Compilation and linking is more complicated for multiple file programs than for our previous programs that used single source files. Nevertheless, this process can easily be automated using one of two methods. The first method creates a project file containing a list of the files used to form the final executable file. This project file includes all source files, library files and object files for the program. Note that project files do not contain header files. The preprocessor will include the header files when the source files are compiled.

The second method creates what is known as a make file. The make file is processed by a utility application known as a make utility program which operates the compiler and linker in accordance with commands contained in the make file.

Project files

We must create a project file, for example, named drive.* before being able to compile the motor drive program. The name of the file extension given to the project file is peculiar to the particular compiler being used. For example, Inprise™ Borland C++ for DOS will use .prj, and Microsoft™ Visual C++ will use .dsp as the extension for the project filename. Three different versions of managing and processing of project files are now given to work with our example program:

Version 1:

main.cpp

absmotor.cpp

pport.cpp

300 9 PROGRAM DEVELOPMENT TECHNIQUES

motor.cpp

dcmotor.cpp

stepper.cpp

When the project file has been processed, all .cpp files will be compiled individually to form .obj files. Then all .obj files will be linked with any other system related .obj or .lib files to form the final executable file.

If all files associated with the classes are available as object files (.obj), the project file would contain the following:

Version 2:

main.cpp

absmotor.obj

pport.obj

motor.obj

dcmotor.obj

stepper.obj

The main.cpp file will be compiled to form an .obj file. Then all .obj files will be linked with any other system related .obj or .lib files to form the .exe file.

It is also possible to form one .lib file combining all the files related to all classes of the hierarchy. Suppose we had a library file created named motors.lib. Then the project file would be as follows:

Version 3:

main.cpp

motors.lib

In this case, the file main.cpp will be compiled and linked with motors.lib and any other related .obj or .lib system files to form the .exe file.

Make files

The other option for automating compilation and linking is to generate a make file containing a sequence of commands used to compile and link all files needed to form an executable file. Commands can be placed in the make file to provide the required variety of options, such as compile only, link only, compile and link, etc.

A make file for the motor drive program that will generate the executable file drive.exe is given below in Listing 9-8. Replace the “CC” characters with the actual command line of the C++ compiler you are using to generate an operational make file. The file names used must be the exact file names. For example, if your compiler generates pport.o as the object file instead of pport.obj, then change all .obj file extensions to .o.

9 PROGRAM DEVELOPMENT TECHNIQUES 301

In a make file we include dependencies and command-line compiler commands. The dependencies must start at the left-most column of a line in a make file as shown in the following statement from the make file of Listing 9-8:

drive: drive1.obj pport.obj dcmotor.obj stepper.obj motor.obj absmotor.obj

This statement informs the make utility that if any of the files listed after the colon have been changed, then the executable file drive.exe will be re-generated.

Listing 9-8 Make file example for drive.exe.

Makefile

#makefile for drive program

drive: drive1.obj pport.obj dcmotor.obj stepper.obj

motor.obj absmotor.obj

CC –edrive drive1.obj pport.obj dcmotor.obj stepper.obj motor.obj absmotor.obj

drive1.obj : drive1.cpp motor.h stepper.h dcmotor.h

motor.h : pport.h absmotor.h

stepper.h : motor.h

dcmotor.h : motor.h

CC -c drive1.cpp pport.obj : pport.cpp pport.h

CC -c pport.cpp

dcmotor.obj : dcmotor.cpp dcmotor.h

CC -c dcmotor.cpp

stepper.obj : stepper.cpp stepper.h

CC -c stepper.cpp

motor.obj : motor.cpp motor.h

CC -c motor.cpp

absmotor.obj : absmotor.cpp absmotor.h CC -c absmotor.cpp

Command-line compiler commands must not start at the left-most column of a line; instead they start after a tab character as shown below:

CC -edrive drive1.obj pport.obj dcmotor.obj stepper.obj motor.obj absmotor.obj

These commands provide information to the make utility for generating the drive.exe file. Note that the ‘switch’ –e informs the compiler that the executable file is to be given the name drive.exe. All other lines in the make file follow the rules just described. The switch –c represents compile only.

The make utility processes a file whose default name is makefile. By giving the file shown in Listing 9-8 the name makefile, the make utility can be invoked by entering the command make at the command prompt to generate drive.exe.

302 9 PROGRAM DEVELOPMENT TECHNIQUES

9.5 Summary

In the first planning stages of a program, the program’s operation should be described using pseudo-code. This description can be refined when working towards a realisable C++ program which has the objects that are needed in the program identified and then defined. These objects can then be organised into a suitable hierarchy; this is extremely beneficial for determining if the efficient use of virtual functions can be employed.

Many typographical errors can be produced when writing a program. When this occurs the compiler will detect the errors and notify the programmer accordingly. Some of these problems can be avoided by using the copy and paste facilities available in modern editors. Copy and paste operations are readily facilitated by using good layout practices when developing a program’s classes. This simplifies the process of defining functions and reduces the possibility of errors. Improper use of nested parenthesis and brackets is also a common cause of compilation and runtime errors. Several good habits have been demonstrated to help avoid these problems. Indentation also plays an important role in identifying levels of nesting, improving readability, and thereby reducing the likelihood of errors in the source file.

The modular approach to program development requires the generation of header files and functions files for each class. When distributing object classes to programmers or using object classes in a program, only the required modules need to be distributed or used. Because modular programs have multiple files, generating their executable files is more involved than for programs that use only one source file. The executable files for modular files are generated using either a project file or a make file to simplify and automate this process.

9.6 Bibliography

Meyer, B., Object Oriented Software Construction, Prentice Hall, 1988

Staugaard A. C. (Jr), Structured and Object Oriented Techniques, Prentice Hall, 1997.

Lafore, R. Object Oriented Programming in MICROSOFT C++, Waite Group Press, 1992

Wang, P.S., C++ with Object Oriented Programming, PWS Publishing, 1994. Winston, P.H., On to C++, Addison Wesley, 1994.

10

Voltage and

Temperature

Measurement

Inside this Chapter

ξ

ξ

ξ

ξ

ξ

ξ

Voltage-to-Frequency Conversion (VFC) using a Voltage-Controlled Oscillator (VCO).

Temperature sensing using thermistors.

Object class for the VCO.

Pulse counting.

Graphics programming.

Programs for voltage and temperature measurement.

10.1 Introduction

This chapter describes a means of converting an analog voltage to a digital pulse-train, the frequency of which is proportional to the applied voltage. This provides an excellent means of measuring analog voltages using a single digital input. We will be using a device known as a Voltage-Controlled Oscillator (VCO) to carry out this ‘analog-to-digital conversion’.

Software will be developed that measures the period of the pulse-train to quantify the applied voltage. The operation of a temperature sensitive resistor will also be described and this device will be used to measure actual temperature. This chapter also introduces graphics programming, where a graphics program is developed to display the digital pulse-train on-screen.

10.2Converting a Voltage to a Digital Pulse-train

One of the simplest forms of analog-to-digital converter is the voltage-to-frequency converter (VFC). The voltage-to-frequency converter produces a digital pulse-train whose frequency is proportional to the voltage applied to the converter input. A specialised type of VFC is the voltage-controlled oscillator (VCO) which produces either a sinusoidal or a square waveform.

Input

Voltage-controlled

Vcap

Voltage

 

Voltage

Current Source

I

Output

 

 

C

Comparator

Frequency

 

 

 

Ccomparator

 

 

 

 

+V

 

 

 

R1

R2

 

Figure 10-1 Typical voltage-to-frequency converter (VFC).

As shown in Figure 10-1, a typical VFC operates using a current source to charge a capacitor C with current that is proportional to the voltage applied to its input.

The output of the voltage comparator (initially a positive voltage) changes state when the voltage across the capacitor C, connected to its –ve input, rises to exceed the positive voltage at its +ve pin. When this happens, the output of the comparator will change polarity to a negative voltage and activate the switch closure across capacitor C. This action discharges capacitor C and also brings the comparator’s

10 VOLTAGE AND TEMPERATURE MEASUREMENT 305

resistor-capacitor circuit, connected to the comparator +ve pin, to a negative voltage.

Following these events, the voltage generated at the +ve pin by the comparator’s resistor-capacitor circuit will increase, eventually exceeding the ‘zero’ volts across the discharged capacitor C. When this happens, the comparator output will revert to a positive voltage level. The switch across capacitor C will open, allowing current to flow into capacitor C and charge the voltage at the –ve pin until it again exceeds the positive voltage at the +ve pin. This marks the completion of one VFC cycle. This process repeats continuously, producing a digital pulse-train at the VFC output. As the input voltage increases, the level of current charging the capacitor C increases and the time to reach the voltage at the comparator +ve pin falls, leading to an increase in the frequency of the output signal.

The interface board uses a VCO housed within part of a CMOS 4046 phase-lock loop integrated circuit. The phase-lock loop device can be used for a range of purposes, however, we have configured it to use just its VCO. Note: the VCO input voltage range that generates a linear output is approximately 1.5V to 3.5V. Its output frequency range is set by two resistors and a capacitor connected to its pins.

10.3 Temperature Measurement

There are many types of electrical sensors that are sensitive to changes in temperature. These include thermistors, thermocouples, thermally sensitive capacitors, semiconductor diodes, and quartz crystals.

Thermistors are one of the more popular temperature sensors in use and the only sensor described in this text. They are simply resistors with very high temperature coefficients, usually having a negative temperature coefficient (NTC). A negative temperature coefficient is one in which the resistance decreases as the temperature of the thermistor increases. Thermistors have an exponential change in their resistance with temperature, making them a little difficult to work with. However, they are low in cost, have high sensitivity, and are small in size.

The simplest means of implementing temperature measurement with a thermistor is by connecting the thermistor in a voltage divider circuit as shown in Figure 10-2.

+V

Bias

Resistor

Output

Voltage

Thermistor

Figure 10-2 Thermistor voltage divider circuit.