Interrupts Library Unit

This library unit is intended to make working with PIC interrupts a bit easier, and additionally help make your code more readable.

The current version is 1.0. Right now it covers the most common interrupt sources, but more can be added if you'll leave a comment mentioning which you think would be handy.

Compilation Constants


In your program, you'll define compilation constants indicating which interrupts you intend to use. Here are the choices so far, with the first larger group considered to be peripheral interrupts, the remaining group of three not.

ADC:           analog to digital converter
RXD:           serial receive
TXD:           serial transmit
SSP:           synchronous serial port
CCP1:          capture/compare/PWM
T1_OVERFLOW:   Timer1 overflow
T2_MATCH:      Timer2 match
OSC_FAIL:      primary oscillator fail
COMPARATOR:    analog comparator
EEPROM_WRITE:  Eeeprom write done

T0_OVERFLOW:   Timer0 overflow
PIN_B0:        external pin B.0 interrupt
PORTB_CHANGE:  PortB has changed


You may define up to six interrupts in your programs. For example,

{$DEFINE INTERRUPT1 'TIMER0_OVERFLOW'}
{$DEFINE INTERRUPT2 'COMPARATOR'}
{$DEFINE INTERRUPT3 'ADC'}


Don't forget the single quote marks since these are compiler string constants.

Commands


Once you've done this, you can then use the following commands to enable or disable the various interrupts you've defined.

procedure IntOn(which);
procedure IntOff(which);

Note that the argument is a member of the t_int data type whose values correspond to the string constants mentioned above, i.e.,

type
 t_int  = (GLOBAL, PERIPHERALS, ADC, RXD, TXD, SSP, CCP1, T1_OVERFLOW, T2_MATCH, OSC_FAIL, COMPARATOR, EEPROM_WRITE, T0_OVERFLOW, PIN_B0, PORTB_CHANGE);


Further note that these two procedures are optimized to recognize only the interrupt types you've defined, and hence are quite compact.

For even greater convenience, observe that calling IntOn() not only sets the individual interrupt enable bit, but also the global enable bit, and the peripheral interrupt enable bit if applicable. On the other hand, IntOff() only clears the individual interrupt bit.

Additionally you can set/clear the peripheral interrupts (use an argument of
PERIPHERALS) or set/clear all interrupts (use an argument of GLOBAL).

Global Variables


Should you wish to work at a more elementary level, you can also access the various  interrupt bits directly with the more convenient MASK aliases declared in the global  variables section. These are:

  MASK_GLOBAL     
  MASK_PERIPHERALS 
  MASK_ADC         
  MASK_RXD        
  MASK_TXD         
  MASK_SSP       
  MASK_CCP1       
  MASK_T1_OVERFLOW 
  MASK_T2_MATCH   
  MASK_OSC_FAIL  
  MASK_COMPARATOR 
  MASK_EEPROM_WRITE
  MASK_T0_OVERFLOW 
  MASK_PIN_B0      
  MASK_PORTB_CHANGE

For example,

MASK_ADC := true;

will enable the analog-to-digital converter interrupt. Likewise, you can access the various interrupt flags with the similar FLAG  aliases. For example,

if (FLAG_T0_OVERFLOW) then
  LED := 1;


PMP Interrupts: An Overview


Don't forget that PMP already has a compiler directive for setting up interrupt service routines. As an overview,

{$INTERRUPTS ON, UNIQUE}

specifies that you intend to use one interrupt service routine only, and that the entry point should be generated in code. Use OFF, of course, if you don't wish an entry point to be generated.

{$INTERRUPTS ON, MULTIPLE}

on the other hand indicates that you have several interrupt service routines. The service routines will be called sequentially.

In the multiple case, then, you will need a selection structure in each service routine to determine if it applies to the current interrupt. For example, even  if you have several interrupt service routines, this one (below) will only be  executed if Timer0 has overflowed.

procedure update; interrupt;

begin
 if (FLAG_T0_OVERFLOW) then
   begin
     FLAG_T0_OVERFLOW := 0;
     inc(ticks)
   end
end;


Of course, you can simply use a unique service routine and have a multi-selection  structure within it which determines which interrupt to handle. Indeed, this may be  more efficient than employing several routines, since multiple procedure calls  from the main program are avoided.

In any case, study the PMP manual carefully.

Add It to Your Library Collection


You can get the Interupts library unit "Interrupts.pas" by clicking the following link:


Be sure to read over the source code for additional details on how to use it.

And, oh, one more thing: earlier version of PIC Micro Pascal sometimes hiccupped on the register bit names, so this unit is really only usable with Version 2.1.4 (the newest version currently).

Try It Out


I've put together a couple simple demos so you can see how the unit helps make things simpler. These use a circuit very similar to that in the four-digit, 7-segment exercise, so check out the schematic there. Note that both of these also use the Timers library unit.


As always, please be sure to leave a comment if you're finding this useful, or if you have a suggestion for improvements.

No comments:

Post a Comment