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

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

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

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

Добавлен: 15.06.2025

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

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

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

422 The Quintessential PIC Microcontroller

Example 14.2

Using C coding show how a digitized reading from Channel 3 of a PIC16C74 can be acquired with the processor in its Sleep state.

Solution

The CCS compiler uses the sleep() function to put the MCU to sleep

– this simply translates to the sleep instruction. A Sleep conversion cannot be implemented using the read_adc() function of Program 14.5 as this continuously polls the GO/DONE flag until it drops low. Instead we need to set and clear individual interrupt related bits before going to sleep in the manner outlined in the assembly-level Program 14.4. On wakening the state of ADRES can then be read ‘manually’.

Program 14.7 Sleep conversion in C.

#include <16c74.h> #bit ADIF = 0x0C.6 #bit PEIE = 0x0B.6 #bit GO = 0x1F.2

/* The

A/D Interrupt Flag

in PIR1[6]

*/

/*

The

group interrupt

flag in INTCON[6]*/

/*

The

Go/NOT_DONE bit

in

ADCON0[2]

*/

#define ADRES *(unsigned int *)0x1e int main()

{

unsigned int i; set_tris_a(0x0E); setup_adc(ADC_CLOCK_INTERNAL);

setup_adc_ports(RA0_RA1_RA3_ANALOG); set_adc_channel(3);

disable_interrupts(GLOBAL);/* Disable all ints (GIE & PEIE=1)*/ ADIF = 0;

enable_interrupts(INT_ADC);

PEIE = 1;

/* Enable the auxiliary group interrupts*/

/*

Code

*/

GO = 1; sleep();

i = ADRES;

}

Coding for this specification is shown in Program 14.7. Here the GO/DONE, PEIE and ADIF bits are defined using the #bit directive. This time the script ADC_CLOCK_INTERNAL is used with the setup_adc() internal function to select the internal CR clock for the DAC module, as necessary for the Sleep conversion.

The internal function disable_interrupts(GLOBAL) clears both GIE and PEIE mask bits. The complementary enable_interrupts(GLOBAL)


14. Take the Rough with the Smooth 423

sets both bits but we need to enable the PEIE only and leave GIE cleared. This is implemented by the ‘bit-twiddling’ statement PEIE=1;. Similarly, clearing the ADIF flag is directly actioned by ADIF=0;. Before calling sleep() the statement GO=1;manually starts the conversion. After sleep() the ADRES register is read giving the required digitized equivalent.

Example 14.3

The analog input channel voltage range for the PIC16C7X/71X devices10

is limited to the positive range 0–Vref, where Vref can either be the internal VDD voltage or an external voltage at RA3 in the range 3–VDD. Many situa-

tions require a digitized mapping from bipolar analog signals. Design a simple resistive network to translate a bipolar voltage range of ±10 V to a unipolar range of 0–5 V, assuming Vref is +5 V.

Solution

+10V

Vref = 5V

-10V

R1

R3

+5V

0V

R2

Fig. 14.15 A level-shifting resistor network.

One possibility is shown in Fig. 14.15. In calculating the value of the three resistors, the following transfer relationships must be adhered to:

1.The value of Vref must appear at the summing node attenuated by 2 when Vin is zero; that is half scale. Thus a zero voltage 0 V 10000000b. To do this R1 paralleled with R2 must have the same resistance as R3; i.e.:

R3 = R1//R2

10The 16C77X devices can be configured to accept bipolar input analog voltages.


424 The Quintessential PIC Microcontroller

2.Vin must be attenuated by the gain of the system G, where the input range is ±G×Vref. In our case G = 2. Thus using the potential divider relationship:

2G = R1 + (R2//R3)/(R2//R3)

After some manipulation we have:

R1

=

(G − 1) × R2

R2

=

G × R3

Of course we have three unknowns and only two equations so we have to start o by choosing a value for one of them below 10 kΩ, which is the maximum recommended value for input resistance. Picking 5 kΩ for R3

gives R2 as 2 × 5 = 10 kΩ and R2 as R1/(G − 1) = 10 kΩ. For the situation ±5 V 5 V then R1 = ∞ and R2 = R3.

Example 14.4

As part of a smart biomedical monitor, the peak analog value of an electro-cardiogram (ECG) signal is to be determined anew for each cycle. This R-point (see Fig. 7.1 on page 172) maximum value is to be output from Port B and RA5 is to be pulsed high whenever this value is being updated. Assuming that a PIC16C73/4 is used to implement the intelligence, the the ECG signal (conditioned as shown in Fig. 14.15) connected to Channel 1 RA1, devise a possible strategy. Timer 0 is being used to interrupt the processor at nominally 100 times per second (see Program 13.2 on page 370) design a suitable ISR to implement your strategy.

Solution

As in any biomedical parameter the ECG signal will vary from cycle to cycle in gain, shape and period. Even if this were not so, imperfections in the data acquisition system, notably the skin electrodes, can cause slow baseline (dc) drift. Thus the threshold at which the signal is to be tracked to its peak R-value must be reset at some sensible fraction of its previous peak during the period following the last update.

One possibility is shown in Fig. 14.16. Here the threshold is slowly decremented after the peak to ensure that a following peak of lower amplitude is not missed. On the basis of a lowest ECG rate of 40 beats per minute (period 1.5 s) if we reduce the threshold by one bit each two samples then the maximum reduction would be a count of 75 at a sample rate of 100 per second. To do this the threshold value THRESHOLD in Program 14.8 is stored as a double-byte number of form integer:fraction and half an integer (i.e. fraction = 10000000b) subtracted in each sample where the peak value MAXIMUM is not updated.

The task list implemented by this listing is:

1. DO a conversion to get ANALOG.


14. Take the Rough with the Smooth 425

Program 14.8 ECG peak picking.

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

; *

FUNCTION:

ISR to

update the ECG

parameters

*

;

*

ENTRY

:

On a Timer0 interrupt

*

;

*

EXIT

:

Update

MAXIMUM and THRESHOLD:THRESHOLD+1

*

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

;First save context

ECG_ISR movwf

_work

;

Put

away W

swapf

STATUS,w

;

and

the Status register

movwf

_status

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

btfss

INTCON,T0IF

;

Was this a Timer0 interrupt?

goto

ECG_EXIT

;

IF not THEN exit

bcf

INTCON,T0IF

; ELSE clear flag

movlw

1

;

Initiate a conversion of

call

GET_ANALOG

;

Channel 1

movwf

TEMP

;

Save digitized value

subwf

THRESHOLD,w

;

THRESHOLD - ANALOG

btfsc

STATUS,C

;

IF no Borrow THEN

goto

BELOW

;

don’t update MAXIMUM

movf

TEMP,w

;

ELSE get digitized value

movwf

MAXIMUM

;

which is the new MAXIMUM

movwf

PORTB

;

made visible to outside

bsf

PORTA,5

;

which is signalled

movwf

THRESHOLD

;

Now update double-byte

clrf

THRESHOLD+1

;

threshold

goto

ECG_EXIT

;

and finish

; Land here if the input is below the threshold

BELOW

bcf

PORTA,5

;

Signal no update

; Now reduce the threshold by 0.5 unless it is zero

movf

THRESHOLD,f

;

Is integer threshold zero?

btfsc

STATUS,Z

;

Skip if not

goto

ECG_EXIT

;

IF it is THEN leave alone

movlw

80h

;

0.5 = 10000000b

subwf

THRESHOLD+1,f ;

Take away from fraction byte

btfss

STATUS,C

;

Skip if no borrow

decf

THRESHOLD,f

;

ELSE decrement integer thres

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

ECG_EXIT 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


426 The Quintessential PIC Microcontroller

Vref

THRESHOLD

0V

Fig. 14.16 ECG detection strategy.

2.IF (ANALOG > THRESHOLD)

MAXIMUM = ANALOG.

THRESHOLD = ANALOG.

PORTB = ANALOG.

RA5 = 1.

3.ELSE

Reduce THRESHOLD by 0.5.

RA5 = 0.

In updating THRESHOLD where ANALOG > THRESHOLD the integer byte takes the new value of MAXIMUM whilst the fractional byte is zeroed. Treating this byte pair as a 16-bit word, this e ectively equates the threshold as MAXIMUM × 256 or THRESHOLD = MAXIMUM << 8, where MAXIMUM has been shifted left eight places. We are assuming that THRESHOLD has been zeroed in the background program during the initialization phase.

If the digitized analog sample is less than the threshold trip value then 80h = 10000000b is subtracted from the lower byte at THRESHOLD+1 and if this produces a borrow, then the upper byte at THRESHOLD is decremented. This subtract 12 routine is skipped if the threshold has reached zero thus preventing underflow.

Although not shown, Program 14.8 uses the subroutine GET_ANALOG of Program 14.1 and its associated 12 µs delay subroutine.

Program 14.9 gives the C coded version implementing our task list. The #int_rtcc directive tells the compiler to treat the following function as a Real-Time Counter Clock (Timer 0) ISR. In function ecg_isr(), the variables threshold and maximum are declared static. This means that their value will be retained after the function has exited and will be available next time on entry. The default way of treating C function variables is to hold their value only for the duration of the function. An alternative way of dealing with this problem is to declare such variables outside any function, in which case they will be global and retain their value indefinitely.

threshold is defined as a long int and the CCS compiler will then treat this datum as a 16-bit variable as required. The definition in equating threshold to zero will only initialize it once when the program begins

14. Take the Rough with the Smooth 427

Program 14.9 An implementation of the ECG peak picker in C.

#int_rtcc ecg_isr()

{

unsigned int analog;

static unsigned long int threshold = 0; static unsigned int maximum;

analog = read_adc();

if(analog > threshold>>8)

{

maximum

= analog;

/* New maximum value

*/

PORT_B

= analog;

/* Show the outside world

*/

threshold = maximum << 8;

/* New 2-byte threshold

*/

output_bit(PIN_A5,1);

/* Tell outside world

*/

}

else

{

threshold = threshold - 0x0080; /* Reduce by 0.5

*/

output_bit(PIN_A5,0);

/* Signal no update

*/

}

}

its run, as the variable is static. Again this is not the normal behavior of the default auto variable.

In equating threshold to the new maximum value, the latter is multiplied by 256 by shifting left eight times – a good compiler will automatically change a N*256 to N<<8. This double-byte form allows for the reduction by half a bit 0080h to give the specified falling trip level.

Both implementations assume that the analog module, ports and interrupt mask bits have been set up at the beginning of the background program as described earlier in the chapter.

Self-assessment questions

14.1 In Example 14.4 the decay of the threshold level was linear. Although this is fairly e ective for situations where the nominal period is known a priori and does not vary greatly, an exponential decay would be better suited where this is not the case. To generate this type of relationship a fixed percentage of the value at each sample point should be subtracted to give the new outcome rather than a constant. Show how you could modify Programs 14.8 and 14.9 to decrement at a rate of approximately 0.4% (≈ 2561 ) on each sample and determine the time constant in terms of the number of samples.