Файл: The quintessential PIC microcontroller (S. Katzen, 2000).pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 15.06.2025

Просмотров: 5286

Скачиваний: 0

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

11. One Byte at a Time 291

slope of the load line ∆∆VI is the resistance in kΩ (as current is in mA) and measures 280Ω.

Extending the load line onwards gives the maximum current as the X co-ordinate of the intersection with the Maximum locus, which is approximately 11.5 mA; not much di erent. If the current requirement had been larger, then the minimum/maximum currents diverge showing a significant temperature sensitivity. For example, a 20 mA minimum base current requires a base resistor of ≈ 120Ω (assuming a base voltage of 0.8 V) and the maximum base current would be 28 mA.

Example 11.2

An 18-pin mid-range PIC is to be used as a digital comparator where a parallel-input 8-bit word P is to be compared to a byte datum located in a file register named TRIP. Outputs are to indicate Lower-Than, Equivalent and Higher-Than. The comparator is to have an hysteresis of ±1 bit. That is, if previous comparisons showed N < TRIP then the trigger level is increased to TRIP +1 for equality. Similarly, on a downward trajectory the equality level is to be decreased to TRIP − 1.

Datum P is to be input via Port B set up as input and the lower three Port A pins give the active-high comparator outputs <, ==, > at RA2, RA1, RA0 respectively.

Solution

The task list for such a specification is:

1.Subtract P from LEVEL.

2.IF Equal (EQ when Z=1) THEN == output active.

3.ELSE IF P Higher than LEVEL (HI when C=0, Borrow) THEN > output active AND LEVEL = TRIP − 1.

4.ELSE IF P Lower than LEVEL (LO when C=1, No Borrow) THEN < output active AND LEVEL = TRIP + 1.

The subroutine given in Program 11.4 assumes that the main program has set up the port directions accordingly and the fixed value is in TRIP. Initially LEVEL would have been set to the same value as TRIP but would subsequently vary by ±1 as per the specification – the hysteresis band.

Software solutions to traditional hardware functions, such as comparison, have the advantage of greater flexibility, albeit at the price of a lower data throughput. Using low-cost ‘computing engines’, such as the PIC, means that relatively simple functions traditionally implemented by dedicated hardware can be replaced by embedded processors.

In this instance, flexibility could be replacing the fixed trip level by a variable datum input via, say, Port C – requiring a larger footprint device; eg. PIC16C74 (see SAQ 11.7). Example 12.1 on page 349 shows how an external datum can be serially acquired externally. Alternatively, an analog signal could represent one or both of the levels in devices with integral A/D converters – see Example 14.7 on page 428. In all these situations


292 The Quintessential PIC Microcontroller

Program 11.4 A digital comparator with hysteresis.

COMP

movf

PORTB,w

; Get input P

subwf

LEVEL,w

; LEVEL - P

btfss

STATUS,Z

; Skip if equality

goto

CONTINUE

; ELSE IF not THEN try alternative

; This code for equality

movlw

b’11111010’

; Make == output logic 1

movwf

PORTA

; Other outputs logic 0

goto

COMP_END

; and exit

CONTINUE

btfsc

STATUS,C

; Skip if borrow (P higher than)

goto

LO

; ELSE P < LEVEL

; This code if P

> LEVEL

HI

movlw

b’11111001’

; Set > output RA0 to logic 1

movwf

PORTA

; Rest to 0

decf

TRIP,w

; Copy TRIP-1 to w

movwf

LEVEL

; The new comparator level

goto

COMP_END

; and exit

; This code when P < LEVEL LO movlw b’11111100’

movwf PORTA incf TRIP,w movwf LEVEL

COMP_END return

;Set < output RA2 to low

;Rest to 0

;Copy TRIP+1 to w

;The new comparator level

the hysteresis may advantageously be made a fraction of the trip voltage, eg. ±321 , rather than a fixed ±1 bit.

Example 11.3

The principle of a stepper motor is shown in Fig. 11.12. In essence there are four coils, labelled A, B, C, D, which may be selectively energized either singly or in pairs, to generate a magnetic field in one of eight directions in divisions of 45◦.8 Thus Coil A alone gives a northerly field, A & B together give a north-easterly direction, B alone is east, etc. The rotor follows the field as it changes direction provided that inertial considerations allow it to keep up during acceleration and de-acceleration.

Solution

Our first step is to devise a table showing energization patterns for the eight possible field directions, as shown in Table 11.2.

8A real stepper motor repeats the coil set several times around the peripheral motor stator giving a finer mechanical step resolution. Thus, if there are four sets of stator coils the 45◦ electrical step translates to 11.25◦ mechanical.


11. One Byte at a Time 293

Program 11.5 Driving a stepper motor.

#define

FREQ

d’40’ ;

Programmer gives value in 100k steps

org

050h

;

Code begins at 050h

; *************************************************************

; *

FUNCTION:

Advances stepper motor 1 -- 256 steps

*

; *

ENTRY

:

Step number in STEP

*

; *

ENTRY

:

Current field position in POSITION

*

;

*

EXIT

:

POSITION updated, STEP = -1, W destroyed

*

;

*

RESOURCE:

Subroutine PATTERN, DELAY_10MS

*

; *************************************************************

MOTOR incf

POSITION,w

; Advance field direction

andlw

b’0111’

; Module-8

movwf

POSITION

; updated

call

PATTERN

; Get the energization pattern

movwf

PORTA

; Send to stepper motor

call

DELAY_10MS

; Hold off 10ms

decfsz

STEP,f

; Decrement step count

goto

MOTOR

; until zero

return

; *************************************************************

; *

FUNCTION:

Maps an integer 0 -- 7 to field pattern

*

;

*

ENTRY

:

Modulo-8 integer in W

*

;

*

EXIT

:

Stepper energization pattern in W

*

; *************************************************************

PATTERN addwf

PCL,f

; Increment Program Counter

retlw

b’1000’

; North

retlw

b’1100’

; North east

retlw

b’0100’

; East

retlw

b’0110’

; South east

retlw

b’0010’

; South

retlw

b’0011’

; South west

retlw

b’0001’

; West

retlw

b’1001’

; North west

; *************************************************************

; * FUNCTION:

Delays 10 ms

delay independent of clock freq

*

;

*

ENTRY

:

FREQ

is xtal

frequency in

multiples

of 100kHz

*

;

*

EXIT

:

10ms

delay; DELAY zero, W

destroyed

*

; *************************************************************

DELAY_10MS

movlw

FREQ

; The programmer’s statement

movwf

TEMP

; Gives the PIC frequency

; Delay loop 10ms at f = 100kHz xtal (1 cycle = 40us)

DLOOP1 movlw

d’62’

; Loop count

movwf

DELAY

DLOOP2 decf

DELAY,f

; 62

* 40us

btfss

STATUS,Z

; 62

* 40us

goto

DLOOP2

; 62

* 80us

decfsz

TEMP,f

; Decrement frequency parameter

goto

DLOOP1

; and repeat until zero

return


294 The Quintessential PIC Microcontroller

Table 11.2: Energization pattern for the eight field directions.

Position

A

B

C

D

Bearing

0

1

0

0

0

1

1

1

0

0

2

0

1

0

0

3

0

1

1

0

4

0

0

1

0

5

0

0

1

1

6

0

0

0

1

7

1

0

0

1

The coding shown in Program 11.5 comprises three subroutines.

MOTOR

The main subroutine simply modulo-8 increments the position vector by post-ANDing with 00000111b to give a wrap around from 7 to 0. This vector is then converted to the appropriate energizing pattern and sent out to the motor after a nominal 10 ms delay. The process is repeated until the decrementing STEP datum reaches zero – if initially zero then 256 steps will be actioned.

PATTERN

Returns one of eight energization patterns corresponding to the field vector as listed in Table 11.2. The mechanism of this look-up table coding has been described in Program 6.4 on page 149. As this suite of subroutines originates at 050h, the 8-bit addition to the Program Counter will not result in roll over across boundaries.

DELAY_10MS

This subroutine gives a nominal 10 ms delay independent of the processor crystal frequency, as defined by the programmer in the program

D

A I

Field

B

I

C

Fig. 11.12 The stepper motor.


11. One Byte at a Time 295

header as a number FREQ in steps of multiples of 100 kHz. Thus for a 8 MHz crystal, giving a 2 MHz machine cycle, FREQ should be defined as 80 using the #define directive, before the program is assembled.

The core of the subroutine is a loop needing a nominal 10 ms execution time at a crystal frequency of 100 kHz – 40 µs machine cycle. This loop is transversed FREQ times. Thus our 8 MHz example will have a loop execution of 1080 ms but will be executed 80 times to give our required 10 ms delay.

Example 11.4

Redo the keypad driver of Program 11.1 but coded in C.

Solution

Software structures of this nature, that is interacting with peripheral devices, are classified as device drivers. Device drivers or handlers have to be able to get at individual register bits in an e cient and sometimes real-time manner. Thus, even in a software system coded in a high-level language, the device drivers are traditionally written at assembly level. However, it is possible to code most device drivers in C, especially where response time is not critical.

The essence of the use of C in interacting with the various peripheral interface devices lies in its ability to operate at the colloquially called bit twiddling (or bit banging) level. To do this the programmer must be able to access fixed addresses in the Data store and to monitor or change individual bits within a datum. We have already seen on page 242 how to directly access a known memory location. For example, the definition:

Contents of

Pointer to byte datum

In File 06

#define PORT_B *(unsigned int *)0x06

defines the name PORT_B as synonymous with the contents of File 6, that is Port B.

Any bit or bits in, say, Port B can be monitored by using the & AND operation ; for example,

if((PORT_B & 0x80) == 0) {do this;} /* Check bit7 for 0 */ if((PORT_B & 0x02) != 0) {do that;} /* Check bit1 for 1 */

executes the statement {do this;} if bit 7 is zero and {do that;} if bit 1 of Port B is a one.

Most microcontrollers have native instructions to bit twiddle single bits directly in memory in a single execution cycle. Where only one bit

296 The Quintessential PIC Microcontroller

is involved this is more e cient than the use of AND and OR operations, and because of this C compilers designed to be used for such hardware targets usually have (non standard) operators designed to make use of this feature.

On page 244 the CCS compiler #bit declaration was used to define individual bits that could subsequently be tested by code. Using this technique our example becomes:

#bit

B7

=

06.7

/*

PortB, bit

7

*/

#bit

B1

=

06.1

/*

PortB, bit

1

*/

......................

if(!B7)

{do this;} /*

Do

this

if

Bit7 is false

(i.e.

0)

*/

if(B1)

{do that;} /*

Do

that

is

Bit1 is true

(i.e.

1)

*/

The CCS compiler comes with a header file for each processor which includes a bit description of all that device’s Special-Purpose Register set and I/O pins. Our examples assume that we have included the file

16f84.h. Thus:

if(!input(PIN_B7)) {do this;} /* Do this if bit RB7 == 0 */ if(input(PIN_B1)) {do that;} /* Do that if bit RB1 == 1 */

There is also a complementary output function; for instance:

output_pin(PIN_B1,0);

/* Make

RB1 low

*/

output_pin(PIN_B2,1);

/*

Make

RB2

high

*/

output_pin(PIN_B3,1);

/*

Make

RB3

high

*/

The CCS compiler adopts the policy that the inner workings of the various peripheral devices should be as invisible to the programmer as possible. To this end the compiler comes with a rich set of internal functions to set up and use the interface features appropriate to the target device specified by the header file.

As an example of this philosophy, set_tris_b(0xF0); is an alternative to the approach adopted on page 274. Similarly the internal function port_b_pullups(TRUE); is an alternative to setting the RBPU bit in the Option register.

The CCS compiler handles parallel I/O in several di erent ways. The #use fast_io(b) statement below leaves it up to the programmer to explicitly set up the appropriate TRIS registers. Other alternatives allow the programmer to ignore such minutia, but then the compiler will set up the port configuration each time it is used, even if that configuration remains unchanged from the last usage.

Program 11.6 assumes the following code as part of the main routine: