Sign in Join
Wiki copytemporary

AVR Embedded Tutorial - GPIO-Interrupt

Deutsch · English

GPIO interrupt

Introduction

How to control the GPIO and UART can be found here:

External interrupt

Interrupt pin assignment for the ATmega328:

Interrupt routine

This example shows how this works with INT0. You use EICRA to specify which interrupt is triggered. See table below. You can also activate INT0 and INT1 at the same time.

pascal
procedure Int0_Interrupt; public name 'INT0_ISR'; interrupt;
begin
  UARTSendString('INT0');  // Identify interrupt
end;

Activate interrupt

The parameters are described in the table below.

pascal
begin
  PORTD := %00001100;  // PullUp Pin 2 + 3

  // Initialize UART
  UARTInit ;

  // Activate INT0
  EICRA := %11;  // INT0 is triggered when the pin goes HIGH.
  EIMSK := %01;  // activate INT0.

  // Activate interrupt
  asm 
    Sei
  END;

  // Main loop
  repeat
  until 1 = 2;
end.

Register for the Atmega328p

The following registers are responsible for the activation of the ports/pins:

Table for EICRA which shows what kind of action on the pin triggers an interrupt.

<thead>

</thead> <tbody>

</tbody>

INT1 interrupt

The INT1 interrupt must be set as follows:

pascal
  EICRA := %1100;  // INT1 is triggered when the pin goes HIGH.
  EIMSK := %10;    // activate INT1.

For the INT1 interrupt you have to use the ISR procedure for the INT1 (INT1_ISR).

pascal
procedure Int1_Interrupt; public name 'INT1_ISR'; interrupt;
begin
  // do something
end;

Pin change interrupt

This example is for an Arduino Nano (Atmega328p).

Terminal issue

Output the pin status on a terminal.

pascal
procedure WritePort(p : byte);
begin
  UARTSendString ('PB' + char(p + 48) + ':');

  if PinB and (1 shl p) = (1 shl p) then 
    begin
      UARTSendString('HIGH');
    end 
  else 
    begin
      UARTSendString('LOW');
    end;
end;

Interrupt routine

The interrupt fires when a pin changes.

pascal
procedure PC_Int0_Interrupt; public name 'PCINT0_ISR'; interrupt;
var
  i : byte;
begin
  UARTSendString(#27 '[0; 0H');  // Home the cursor

  for i := 0 to 3 do 
    begin
      WritePort(i);
    end;
end;

Declare pin change GPIO

Activate pins PB0, PB1, PB2 and BP3 for interrupts.

pascal
const
  inPortsB = %00001111;  // PCINT0 + PCINT1 + PCINT2 + PCINT3

Activate pin change interrupt

The parameters are described in the table below.

pascal
procedure PC_Int0_Interrupt; public name 'PCINT0_ISR'; interrupt;
begin
  DDRB  := 0;
  PORTB := inPortsB;  // PullUp

  // Initialize UART
  UARTInit;

  // Activate PCINT0_ISR
  PCICR  := %001;     // Only on PORTB
  PCMSK0 := inPortsB;

  // Activate interrupt
  asm 
    Sei
  END;

  // Main loop
  repeat
    // do something
  until 1 = 2;
end.

Registers for the Atmega328p

The following registers are responsible for the activation of the ports/pins:

Table for PCICR:

Bit 2 1 0
PCICR PORTD PORTC PORTB

Table for the pins of PCMSKx :

Bit 7 6 5 4 3 2 1 0
PCMSK0 PCINT7 PCINT6 PCINT5 PCINT4 PCINT3 PCINT2 PCINT1 PCINT0
PCMSK1 PCINT14 PCINT13 PCINT12 PCINT11 PCINT10 PCINT9 PCINT8
PCMSK2 PCINT23 PCINT22 PCINT21 PCINT20 PCINT19 PCINT18 PCINT17 PCINT6

Example for PORT B and PORT C

pascal
// Activate PCINT0_ISR and PCINT1_ISR
PCICR  := %011;      // PORT B and PORT C
PCMSK0 := %11000000; // Pin 6 + 7 of PORT B
PCMSK1 := %00000011; // Pin 0 + 1 of PORT C

A second ISR procedure is added for the PCINT1_ISR. If you would like to use PORT D, then a procedure for the PCINT2_ISR would need to be added.

pascal
procedure PC_Int1_Interrupt; public name 'PCINT1_ISR'; interrupt;
begin
  // do something
end;

See also


From the Free Pascal wiki, page "AVR Embedded Tutorial - GPIO-Interrupt", as it stood on 2020-01-24 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.

Revision 2, last changed by WikiArchive .

Talk about this page

Nobody has opened a bench for this page yet. Sign in to open one.