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

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

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

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

Добавлен: 15.06.2025

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

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

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

446 The Quintessential PIC Microcontroller

Although the table has here been placed at an even 256-byte boundary for convenience, in practice it can be located anywhere in memory. In the general case the table o set nn will need to be added to the 14-bit address TABLE. SAQ 15.2 discusses how this address arithmetic could be done.

Examples

Example 15.1

The CCS compiler has the following built-in functions dealing with the EEPROM Data module:

read_eeprom(address)

Reads a byte from the specified EEPROM address.

write_eeprom(address, value)

Write the value to the specified address and returns only when the Write cycle has finished.

Write a C function to duplicate the odometer update implemented at assembler level in Program 15.3.

Solution

Like its assembly-level counterpart of Program 15.3, the function of Program 15.7 is divided into three phases.

1.This phase creates an array of three bytes named odometer[] which will act as a temporary store for the odometer count located in EEPROM. As the EEPROM Data module handles data in discrete byte

Program 15.7 C-based coding for the odometer.

void odometer(void)

{

unsigned int odometer[3];

/* Define the 3-byte count

*/

odometer[0] = read_eeprom(0x10); /* Get the existing count

*/

odometer[1] = read_eeprom(0x11);

odometer[2] = read_eeprom(0x12);

/* Increment array

*/

if(++odometer[0] != 0) break;

else if(++odometer[1] != 0) break;

else odometer[2]++;

/* Now return incremented count to the EEPROM

*/

write_eeprom(0x10, odometer[0]);

write_eeprom(0x11, odometer[1]); write_eeprom(0x12, odometer[2]);

}


15. To Have and to Hold 447

packages, it is best to model the object in C in the same manner. The array is given the current reading by extracting the data one byte at a time from EEPROM locations 10:11:12h using the read_eeprom() function.

2.Once the 3-byte data is in the Data store it is incremented using an if-else tree:

(a)Increment low byte and check for zero. IF not zero THEN the overall addition is complete ELSE pass on carry to next byte.

(b)Increment the middle byte and check for zero. IF not zero THEN the overall addition is complete ELSE pass on carry to next byte.

(c)Increment most significant byte.

3.Finally each byte is written back into the EEPROM Data module using the write_eeprom() function.

Comparing the hand-coded assembly of Program 15.3 against the code generated from Program 15.7 gives 52 instructions against 91.

Example 15.2

A feasibility study is being undertaken in using a PIC-based Sauna controller. This is to monitor temperature and control heating and cooling units. There is also to be an over-temperature emergency alarm and shut- o .

One possibility is to use an 8-pin PIC with integral A/D conversion, such as the PIC12C672, together with an external temperature transducer. Someone has suggested that an e cient approach to this problem would be to use the variation in the internal Watchdog timer’s period with temperature as a cost e ective, albeit crude, sensor.

Experimental data was collected using a sample of eight production devices from the same manufacturing lot, with a soak time of 30 minutes at each tested temperature and 500 uncalibrated periods averaged to produce the graph of Fig. 15.8.

The data presented in Fig. 15.8 is based on Microchip’s application note AN720 Measuring Temperature Using the Watch Dog Timer (WDT). The two loci give the maximum and minimum across the range of tested devices. The Watchdog period was measured in Timer 0 overflows counting an internal 4 MHz clock. The Watchdog timer used a 1:8 prescale ratio.

From this data it can be seen that there is a correlation between period and rising temperature. However, although the overall trend is predictable, di erent devices will have varying o sets and slopes. For example, within the eight devices tested here the scale factor (scalar) varies from 2.28–2.42 counts per degree Celsius. This will necessitate a calibration phase before the system is used. If the count at one temperature T0 and the scalar are known for any device, then for the specific case where a count COUNTn − COUNT0 is recorded:

∆T = (COUNTn − COUNT0) × Scalar

448 The Quintessential PIC Microcontroller

Fig. 15.8 Watchdog timer period versus temperature.

In order to calibrate these devices it has been decided to soak batches in a refrigerator at 0◦C and save the 2-byte count in the EEPROM data module of a PIC16F83. The soak test is to be repeated in an oven at 30◦C with the di erence between this second count and the original value to be stored in a single EEPROM byte. Once this has been done, the device can be reprogrammed with the final running program overwriting the original calibrate program. This running program can then calculate temperature using the actual Watchdog period COUNTn:

T = (COUNT0 − COUNTn) × (Di erence/30)

where COUNT0 is the 2-byte EEPROM datum showing the count at 0◦C and Di erence is the 1-byte EEPROM datum showing the change in count over 30◦C.

Show how you could code the calibrate program to implement this specification.

Solution

Five tasks can be identified which must be undertaken at the end of a Watchdog period.

Average the current Timer 0 roll-over count with the existing low-temp- erature (i.e. 0◦C) count.

Average the current Timer 0 roll-over count with the existing hightemperature (i.e. 30◦C) count.

Store the low-temperature count in EEPROM.

Calculate the di erence between lowand high-temperature count and store in EEPROM.

Do nothing.


15. To Have and to Hold 449

Port lines can be used to signal which of the first four active actions are to be actioned. For example; if RA0 is high then add the current Timer 0 rollover count to the existing 2-byte low-temperature count. Unless this is the first reading, divide by two to give an average. The complete batch of devices could have their RA0 pin held high for a few minutes 30 minutes after the refrigerator stabilizes at 0◦C.

Bringing RA0 low and then RA2 high for a short time signals an EEPROM storage action. With all port lines low, no action is taken representing both time before temperature stabilization and after EEPROM programming.

The Timer 0 and Watchdog timers are initialized together with the count values on a once-only basis on Power-up reset. This will typically only occur when the devices are powered up when in the temperature bath. Subsequent resets will normally be due to Watchdog time-outs. The state of the Status register’s TO flag can be used to ascertain the source of reset – see page 363.

Program 15.8 shows the routine used to initialize the timers and variables entered if TO is 1 on reset; that is on Power-up. Once this is done, the system enters an endless loop goto $ (the assembler replaces the label $ by the instruction’s address) which simply keeps going to itself!

Also shown is the ISR servicing a Timer 0 interrupt. This increments the double-byte variable ROLL_OVER:ROLL_OVER+1 and this is the count value read by the system on a Watchdog reset giving a numerical value for period.

Eventually the Watchdog timer will time-out and reset the processor. This time TO will be 0 and the routine labelled READING in Program 15.9 will be entered. This checks the state of each of the four RA3:0 pins in turn, executing one of the four listed tasks. If no pin is high, the program simply clears ROLL_OVER:ROLL_OVER+1 and Timer 0, the Watchdog timer is restarted and an endless loop entered. This READING_EXIT routine is also entered at the end of the four tasks.

The first two tasks are shown in Program 15.9. Here the 2-byte Timer 0 roll-over count is either added to the existing value LO_TEMP:LO_TEMP+1 or HI_TEMP:HI_TEMP+1 as appropriate and the outcome shifted once right to divide by two to give the average. As the count total is modest, 2-byte arithmetic is su cient to avoid overflow. If this is repeated over a duration of several minutes an averaged value will result.

If this is the very first time a reading has been made then the divide by two operation is skipped and the flag variable FIRST_LO or FIRST_HI as appropriate is made non zero.

The core routine with respect to this chapter is given in Program 15.10. If RA2 is 1 the 2-byte low-temperature count LO_TEMP:LO_TEMP+1 is copied into the bottom two bytes of the EEPROM Data module using the EE_PUT subroutine of Program 15.2.

450 The Quintessential PIC Microcontroller

Program 15.8 The Sauna Power-up reset sequence and ISR.

__config _WDT_ON & _CP_OFF & _RC_OSC

cblock

20h

_work:1, _status:1

FIRST_HI:1, FIRST_LO:1

ROLL_OVER:2, LO_TEMP:2, HI_TEMP:2

DELTA_TEMP:1

endc

org

0

START

goto

MAIN

org

4

goto

ISR

MAIN

btfss

STATUS,NOT_TO

;

IF Watchdog timeout

goto

READING

;

THEN must have a reading

clrwdt

movlw

b’11011010’

;

Wdt enabled with a 1:8 prescale

bsf

STATUS,RP0

;

Change to Bank1

movwf

OPTION_REG

;

and TMR0 internal clock

bcf

STATUS,RP0

;

and back to Bank0

clrf

FIRST_HI

clrf

FIRST_LO

bsf

INTCON,T0IE

;

Enable Timer0 interrupt

clrf

TMR0

;

Zero the Timer

clrf

ROLL_OVER+1

;

Zero the 2-byte Timer roll-over

clrf

ROLL_OVER

bsf

INTCON,GIE

;

Enable all interrupts

goto

$

;

Endless loop

;

**************************************************************

;

* The ISR to increment the 2-byte COUNT IF TMR0 interrupt

*

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

;First save context in usual way

ISR

movwf

_work

; Put

away W

swapf

STATUS,w

; and

the Status register

movwf

_status

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

;The core code

incf

ROLL_OVER+1,f;

Record one more roll-over

btfsc

STATUS,C

;

Skip if no carry

incf

ROLL_OVER,f

;

Increment upper

byte

bcf

INTCON,T0IF

;

Clear interrupt

flag

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

swapf

_status,w

; Untwist

the original Status reg

movwf

STATUS

swapf

_work,f

; Get

the

original W reg back

swapf

_work,w

;

leaving

STATUS unchanged

retfie

;

and

return from interrupt


15. To Have and to Hold 451

If RA3 is 1 the di erence between the 2-byte high and low temperatures is then calculated. With the data shown in Fig. 15.8 it can be seen that a 30◦C di erence will not exceed a byte’s worth of storage so only the

Program 15.9 Reading a new period count.

READING

btfsc

PORTA,0

;

Check; new low temp desired?

goto

NEW_LO

;

IF yes THEN go to it!

btfsc

PORTA,1

;

Check; new high temp desired?

goto

NEW_HI

;

IF yes THEN go to it!

btfsc

PORTA,2

;

Check; update low temp desired?

goto

UPDATE_LO

;

IF yes THEN go to it!

btfsc

PORTA,3

;

Check; update high temp desired?

goto

UPDATE_HI

;

IF yes THEN go to it!

goto

READING_EXIT ;

ELSE nothing doing

NEW_LO

movf

ROLL_OVER+1,w;

ELSE get low byte TMR0 roll-over

addwf

LO_TEMP+1,f

;

and add it to low byte low temp

btfsc

STATUS,C

;

Check for Carry

incf

LO_TEMP,f

;

IF so THEN record it

movf

ROLL_OVER,w

;

Now get high byte of roll-over

addwf

LO_TEMP,f

;

and add it to high byte low temp

movf

FIRST_LO,f

;

Is this the 1st low reading?

btfsc

STATUS,Z

goto

FIRST_TIME_LO;

IF so THEN go to it!

rrf

LO_TEMP,f

;

ELSE divide sum by two

rrf

LO_TEMP+1,f

goto

READING_EXIT ;

and finished

FIRST_TIME_LO

;

IF first reading simply transfer

incf

FIRST_LO,f

;

No longer the first reading

goto

READING_EXIT

NEW_HI

movf

ROLL_OVER+1,w;

ELSE get low byte TMR0 roll-over

addwf

HI_TEMP+1,f

;

and add it to low byte high temp

btfsc

STATUS,C

;

Check for Carry

incf

HI_TEMP,f

;

IF so THEN record it

movf

ROLL_OVER,w

;

Now get high byte of roll-over

addwf

HI_TEMP,f

;

and add it to high byte high temp

movf

FIRST_HI,f

;

Is this the 1st high reading?

btfsc

STATUS,Z

goto

FIRST_TIME_HI;

IF so THEN go to it!

rrf

HI_TEMP,f

;

ELSE Divide sum by two

rrf

HI_TEMP+1,f

goto

READING_EXIT ;

and finished

FIRST_TIME_HI

;

IF first reading simply transfer

incf

FIRST_HI,f

;

No longer the first reading

READING_EXIT

clrf

TMR0

;

Zero the timer

clrwdt

;

Reset the Watchdog timer

clrf

ROLL_OVER+1

;

Zero the roll-over count

clrf

ROLL_OVER

goto

$

;

Wait for another Watchdog reset


452 The Quintessential PIC Microcontroller

Program 15.10 Updating the Sauna EEPROM.

UPDATE_LO

movf

LO_TEMP,w

; Get high byte of low temperature

bsf

STATUS,RP0

; To Bank1

movwf

EEDATA

; In EEPROM Data register

clrf

EEADR

; EEPROM address 00h

call

EE_PUT

; Write datum in

movf

LO_TEMP+1,w

; Get low byte of low temperature

bsf

STATUS,RP0

; To Bank1

movwf

EEDATA

; Is new datum

incf

EEADR,f

; EEPROM address 01h

call

EE_PUT

; Write Datum in

goto

READING_EXIT

UPDATE_HI ;

Work out HI_TEMP-LO_TEMP & store at 02 in EEPROM

; Only need

to subtract the lower bytes as diff fits in one byte

movf

HI_TEMP+1,w

; Get low byte high temperature

subwf

LO_TEMP+1,w

; Subtract low byte low temperature

movwf

DELTA_TEMP

; giving the difference

bsf

STATUS,RP0

; To Bank1

movwf

EEDATA

; Delta temperature in 02h

movlw

2

movwf

EEADR

call

EE_PUT

goto

READING_EXIT

lower byte of the subtraction is implemented. This single byte di erence is then written into EEPROM in the normal way.

Self-assessment questions

15.1Good program practice dictates that the datum written into Data EEPROM should be verified as the value that was intended to be written. Show how you could modify the EE_PUT subroutine of Program 15.2 to return a value −1 in a file register if the action is not successful, otherwise zero.

15.2In Program 15.6 we placed the look-up table at a 256-byte boundary in the Program store (specifically 300h) to simplify the computation of the 1-byte table index. Thus to look up table entry nn we simply place the address 3nnh in the EEADRH:EEADR register pair.

Placing program segments at user-defined addresses is never a good idea, as subsequential program alterations can cause code to overlap unless care is taken. Letting the assembler sort out loca-