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

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

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

286 9 PROGRAM DEVELOPMENT TECHNIQUES

The structure of DCMotor

class member functions must conform to the function declarations given in the dcmotor.h file.

Class definition

// class definition

#include “motor.h”

class DCMotor : public Motor

{

public:

DCMotor(int baseaddress=0x378); virtual void Forward();

virtual void Reverse(); virtual void Brake(); virtual void Off();

Header File (dcmotor.h)

Member function definitions

#include “dcmotor.h”

// member f’n 1 definition DCMotor::DCMotor(..

{

.

.

.

}

// member f’n 2 definition DCMotor::Forward()

{

.

.

.

}

// member f’n 3 definition DCMotor::Reverse()

{

.

.

.

}

.

.

.

.

.

.

Function File (dcmotor.cpp or *.obj or *.lib)

Figure 9-4 Include header file in the function file of its class.

Figure 9-4 shows the inclusion of the header file for the DCMotor class at the start of the function file for the DCMotor class. This will ensure all member function definitions of the DCMotor class (that were derived from the Motor class and overridden as required) will conform with the function declarations stipulated in the header file dcmotor.h.

9 PROGRAM DEVELOPMENT TECHNIQUES 287

Include directives

The files that are included from the ‘include’ directory of the C/C++ program development software are enclosed between angle brackets angle brackets (< >):

#include <stdlib.h> // For standard C library fn’s

Header files included from the same directory or any other directory in the path are enclosed between double quotation marks (“ “):

#include “motor.h” // For motor class objects used.

The proper use of angle brackets and double quotation marks is crucial as it allows the compiler to efficiently locate the included header files during compilation and linking.

Preventing Multiple Inclusions of Header Files

A particular header file is included only once in a program. Should a header file be included more than once, the compiler will interpret this as an error and issue an error message. The compiler can interpret multiple inclusion as, for example, the redefinition of a class that is already defined by the first instance of the include file

– hence the error!

The general rule “Include the header file of the object you use in the program” may lead to multiple inclusions. For example, if a program uses a DCMotor object and a StepperMotor object, we must include dcmotor.h as well as stepper.h files. They both have motor.h included in them. As a result motor.h will be included twice. There is a mechanism that enables us to practice the general rule above and at the same time avoid multiple inclusions of the same header file. The procedure uses a ‘status flag’, explained as follows:

Before the preprocessor begins to include header files, the flag will be inactive (file not included).

The first time a particular header file is presented for inclusion, the flag will be tested, and the result will indicate that the header file has not been included. The header file will be included this time and the flag will then be activated, indicating inclusion has now taken place.

When this header file is presented for inclusion on subsequent occasions, the flag will be tested and its status (this time; file included) will direct the preprocessor to ignore this file, preventing any multiple inclusions.

Sentries for header files

Sentries in header files are compiler directives for the preprocessor. They implement the function of the ‘status flag’ just described and prevent the compiler from including the same header file more than once.

The following example uses the AbstactMotor class to show how sentries are added to a header file.

288 9 PROGRAM DEVELOPMENT TECHNIQUES

Listing 9-6 AbsMotor.h header file.

#ifndef AbsmotorH #define AbsmotorH

class AbstractMotor

{

private:

int Speed;

public:

AbstractMotor();

void SetSpeed(int speed); int GetSpeed();

virtual void Off()=0; virtual void Forward()=0; virtual void Reverse()=0; virtual void Brake()=0; virtual ~AbstractMotor(){}

};

#endif

The first preprocessor directive #ifndef represents ‘if not defined’. It is similar to an if statement, with its body starting at #ifndef and ending at the line with the directive #endif. Therefore, the preprocessor interprets:

#ifndef AbsmotorH

as ‘if AbsmotorH is not defined’. The body of this #if statement will be executed only if AbsmotorH is not defined.

The identifier AbsmotorH will not be defined when proceeding to process a multiple file program for the first time. As such, when the pre-processor encounters the line #ifndef AbsmotorH, it will enter the body of the #if statement. The first line within the body is:

#define AbsmotorH

The #define directive is used to state that identifier AbsmotorH is to be defined. The identifier must be unique and not already used to name another header file from a different class. Improper naming of identifiers can lead to programming bugs that are difficult to find. Since the file system of your computer maintains unique names for each file, the best practice is to derive the sentry name based on the name of that header file. This approach has been used to form the name of the AbsmotorH sentry from the associated header file absmotor.h. When all remaining lines in the body are processed by the pre-processor, the AbstractMotor class will be interpreted by the compiler and the sentry AbsMotorH defined. Should the pre-processor encounter another absmotor.h

9 PROGRAM DEVELOPMENT TECHNIQUES 289

file included in another file of that program, execution of the #ifndef AbsmotorH directive will return false. In this case the body of the #if statement will be skipped, avoiding a repeated inclusion of its contents.

9.4 Case Study - Motor Driver Program

This section will demonstrate the process of generating a multiple file program as described previously using the motor driver program developed in Chapter 8. We will first create the software modules for each object class in our program. Each module will have its own header file and function file.

 

 

 

 

ParallelPort Class

 

 

 

ParallelPort Class Defn’s

 

 

 

 

AbstractMotor Class

 

 

 

 

 

AbstractMotor Class Defn’s

 

 

 

 

Motor Class

 

 

 

 

 

Motor Class Defn’s

 

 

 

 

 

StepperMotor Class

 

 

 

 

 

StepperMotor Class Defn’s

 

 

 

 

DCMotor Class

 

 

 

DCMotor Class Defn’s

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

dcmotor.h

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

ParallelPort Function File

 

 

 

 

 

 

 

 

 

 

 

 

AbstractMotor Function File

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

User Program

 

 

 

 

 

Motor Function File

 

 

 

 

 

 

 

 

 

 

 

 

 

StepperMotor Function File

 

 

 

 

 

 

 

 

 

 

 

 

 

 

DCMotor Function File

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

main.cpp

Single file program

dcmotor.cpp

Figure 9-5 Form a multiple file program.

Figure 9-5 shows the original single file program on the left with its main function and classes. The header file and function file associated with each class is shown on the right. The program from Chapter 8 (Listing 8-19) is shown following. Each code segment has been identified from the program, copied and labelled to its appropriate file type; being a header file or function file. These files are then saved with *.h and *.cpp extensions, preferably in the same directory to minimise file search time.

290 9 PROGRAM DEVELOPMENT TECHNIQUES

Listing 9-7 Motor driver program - segmented.

absmotor.h (header file)

#ifndef AbsmotorH #define AbsmotorH

class AbstractMotor

{

private:

int Speed;

public:

AbstractMotor();

void SetSpeed(int speed); int GetSpeed();

virtual void Off()=0; virtual void Forward()=0; virtual void Reverse()=0; virtual void Brake()=0; virtual ~AbstractMotor(){}

};

#endif

absmotor.cpp (function file)

#include "absmotor.h"

AbstractMotor::AbstractMotor()

{

Speed =0;

}

void AbstractMotor::SetSpeed(int speed)

{

Speed = speed;

if(Speed > 255) Speed = 255; // Limit upper value if(Speed < 0) Speed = 0; // Limit lower value

}

int AbstractMotor::GetSpeed()

{

return Speed;

}

pport.h (header file)

#ifndef PportH

9 PROGRAM DEVELOPMENT TECHNIQUES 291

#define PportH

class ParallelPort

{

private:

unsigned int BaseAddress; unsigned char InDataPort1;

public:

ParallelPort(); ParallelPort(int baseaddress);

void WritePort0(unsigned char data); void WritePort2(unsigned char data); unsigned char ReadPort1();

virtual ~ParallelPort(){}

};

#endif

pport.cpp (function file)

#include <dos.h>

#include "pport.h"

ParallelPort::ParallelPort()

{

BaseAddress = 0x378; InDataPort1 = 0;

}

ParallelPort::ParallelPort(int baseaddress)

{

BaseAddress = baseaddress; InDataPort1 = 0;

}

void ParallelPort::WritePort0(unsigned char data)

{

outportb(BaseAddress,data);

}

void ParallelPort::WritePort2(unsigned char data)

{

outportb(BaseAddress+2,data ^ 0x0B);

}

unsigned char ParallelPort::ReadPort1()

292 9 PROGRAM DEVELOPMENT TECHNIQUES

{

InDataPort1 = inportb(BaseAddress+1);

//Inverting Most significant bit to compensate

//for internal inversion by printer port hardware. InDataPort1 ^= 0x80;

//Filter to clear unused data bits D0, D1 and D2 to zero. InDataPort1 &= 0xF8;

return InDataPort1;

}

motor.h (header file)

#ifndef MotorH #define MotorH

#include "absmotor.h" #include "pport.h"

class Motor : public AbstractMotor, public ParallelPort

{

public:

Motor(int baseaddress=0x378); void Off();

virtual void Forward()=0; virtual void Reverse()=0; virtual void Brake()=0; virtual ~Motor(){}

};

#endif

motor.cpp (function file)

#include "motor.h"

Motor::Motor(int baseaddress):ParallelPort(baseaddress)

{

Off();

}

void Motor::Off()

{

WritePort0(0x00);

}

dcmotor.h (header file)

#ifndef DcmotorH #define DcmotorH

9 PROGRAM DEVELOPMENT TECHNIQUES 293

#include "motor.h"

class DCMotor : public Motor

{

public:

DCMotor(int baseaddress=0x378); virtual void Forward();

virtual void Reverse(); virtual void Brake();

};

#endif

dcmotor.cpp (function file)

#include "dcmotor.h"

DCMotor::DCMotor(int baseaddress):Motor(baseaddress)

{

}

void DCMotor::Forward()

{

int j;

for(j = 0; j < GetSpeed(); j++) WritePort0(0x09);

for(;j < 256; j++) WritePort0(0x00);

}

void DCMotor::Reverse()

{

int j;

for(j = 0; j < GetSpeed(); j++) WritePort0(0x06);

for(;j < 256; j++) WritePort0(0x00);

}

void DCMotor::Brake()

{

WritePort0(0x0C);

}

294 9 PROGRAM DEVELOPMENT TECHNIQUES

stepper.h (header file)

#ifndef StepperH #define StepperH

#include "motor.h"

enum MOTORTYPE {UPFS, UPHS, BPFS, BPHS};

class StepperMotor : public Motor

{

private:

MOTORTYPE MotorType; unsigned char Switching[8]; int CycleIndex;

int MaxIndex;

public:

StepperMotor(MOTORTYPE motortype = UPFS, int baseaddress=0x378);

virtual void Forward(); virtual void Reverse(); virtual void Brake();

};

#endif

stepper.cpp (function file)

#include <dos.h>

#include "stepper.h"

StepperMotor::StepperMotor(MOTORTYPE motortype,

int baseaddress): Motor(baseaddress)

{

MotorType = motortype; CycleIndex = 0;

switch(MotorType)

{

case UPFS: MaxIndex = 4; Switching[0] = 0x11; Switching[1] = 0x12; Switching[2] = 0x22; Switching[3] = 0x21; break;

case UPHS: MaxIndex = 8;

9 PROGRAM DEVELOPMENT TECHNIQUES 295

Switching[0] = 0x01;

Switching[1] = 0x11;

Switching[2] = 0x10;

Switching[3] = 0x12;

Switching[4] = 0x02;

Switching[5] = 0x22;

Switching[6] = 0x20;

Switching[7] = 0x21; break;

case BPFS: MaxIndex = 4; Switching[0] = 0x99; Switching[1] = 0x69; Switching[2] = 0x66; Switching[3] = 0x96; break;

case BPHS: MaxIndex = 8; Switching[0] = 0x99; Switching[1] = 0x09; Switching[2] = 0x69; Switching[3] = 0x60; Switching[4] = 0x66; Switching[5] = 0x06; Switching[6] = 0x96; Switching[7] = 0x90;

}

}

void StepperMotor::Forward()

{

if(++CycleIndex == MaxIndex) CycleIndex = 0; WritePort0(Switching[CycleIndex]); delay(259-GetSpeed());

}

void StepperMotor::Reverse()

{

if(--CycleIndex == -1) CycleIndex = MaxIndex -1; WritePort0(Switching[CycleIndex]); delay(259-GetSpeed());

}

void StepperMotor::Brake()

{

switch(MotorType)

{