Sign in Join
Wiki copytemporary

AVR Embedded Tutorial - GPIO-Interrupt: what changed

Revision 2 to 3. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11# GPIO interrupt
22
33## Introduction
44
55How to control the GPIO and UART can be found here:
66
77- [[AVR Embedded Tutorial - Simple GPIO on and off output/de|GPIO]]
88- [[AVR Embedded Tutorial - UART/de|UART]] *UARTInit* and *UARTSendString(...*
99
1010## External interrupt
1111
1212Interrupt pin assignment for the ATmega328:
1313
1414- INT0: PD2
1515- INT1: PD3
1616
1717### Interrupt routine
1818
1919This 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.
2020
2121``` pascal
2222procedure Int0_Interrupt; public name 'INT0_ISR'; interrupt;
2323begin
2424 UARTSendString('INT0'); // Identify interrupt
2525end;
2626```
2727
2828### Activate interrupt
2929
3030The parameters are described in the table below.
3131
3232``` pascal
3333begin
3434 PORTD := %00001100; // PullUp Pin 2 + 3
3535
3636 // Initialize UART
3737 UARTInit ;
3838
3939 // Activate INT0
4040 EICRA := %11; // INT0 is triggered when the pin goes HIGH.
4141 EIMSK := %01; // activate INT0.
4242
4343 // Activate interrupt
4444 asm
4545 Sei
4646 end;
4747
4848 // Main loop
4949 repeat
5050 until 1 = 2;
5151end.
5252```
5353
5454### Register for the Atmega328p
5555
5656The following registers are responsible for the activation of the ports/pins:
5757
5858- **EICRA** Function of the interrupt.
5959- **EIMSK** Activate INT0 and/or INT1.
6060
6161Table for **EICRA** which shows what kind of action on the pin triggers an interrupt.
6262
63-<thead>
64-
65-</thead>
66-<tbody>
67-
68-</tbody>
63+| | INT1 | | | INT0 | | |
64+|---|---|---|---|---|---|---|
65+| Bit | 3 | 2 | | 1 | 0 | |
66+| | 0 | 0 | | 0 | 0 | Low Level on the pin |
67+| | 0 | 1 | | 0 | 1 | Every change |
68+| | 1 | 0 | | 1 | 0 | Pin goes LOW |
69+| | 1 | 1 | | 1 | 1 | Pin goes HIGH |
6970
7071### INT1 interrupt
7172
7273The INT1 interrupt must be set as follows:
7374
7475``` pascal
7576 EICRA := %1100; // INT1 is triggered when the pin goes HIGH.
7677 EIMSK := %10; // activate INT1.
7778```
7879
7980For the INT1 interrupt you have to use the ISR procedure for the INT1 (**INT1_ISR**).
8081
8182``` pascal
8283procedure Int1_Interrupt; public name 'INT1_ISR'; interrupt;
8384begin
8485 // do something
8586end;
8687```
8788
8889## Pin change interrupt
8990
9091This example is for an Arduino Nano (Atmega328p).
9192
9293### Terminal issue
9394
9495Output the pin status on a terminal.
9596
9697``` pascal
9798procedure WritePort(p : byte);
9899begin
99100 UARTSendString ('PB' + char(p + 48) + ':');
100101
101102 if PinB and (1 shl p) = (1 shl p) then
102103 begin
103104 UARTSendString('HIGH');
104105 end
105106 else
106107 begin
107108 UARTSendString('LOW');
108109 end;
109110end;
110111```
111112
112113### Interrupt routine
113114
114115The interrupt fires when a pin changes.
115116
116117``` pascal
117118procedure PC_Int0_Interrupt; public name 'PCINT0_ISR'; interrupt;
118119var
119120 i : byte;
120121begin
121122 UARTSendString(#27 '[0; 0H'); // Home the cursor
122123
123124 for i := 0 to 3 do
124125 begin
125126 WritePort(i);
126127 end;
127128end;
128129```
129130
130131### Declare pin change GPIO
131132
132133Activate pins PB0, PB1, PB2 and BP3 for interrupts.
133134
134135``` pascal
135136const
136137 inPortsB = %00001111; // PCINT0 + PCINT1 + PCINT2 + PCINT3
137138```
138139
139140### Activate pin change interrupt
140141
141142The parameters are described in the table below.
142143
143144``` pascal
144145procedure PC_Int0_Interrupt; public name 'PCINT0_ISR'; interrupt;
145146begin
146147 DDRB := 0;
147148 PORTB := inPortsB; // PullUp
148149
149150 // Initialize UART
150151 UARTInit;
151152
152153 // Activate PCINT0_ISR
153154 PCICR := %001; // Only on PORTB
154155 PCMSK0 := inPortsB;
155156
156157 // Activate interrupt
157158 asm
158159 Sei
159160 end;
160161
161162 // Main loop
162163 repeat
163164 // do something
164165 until 1 = 2;
165166end.
166167```
167168
168169### Registers for the Atmega328p
169170
170171The following registers are responsible for the activation of the ports/pins:
171172
172173- **PCICR** Ports that trigger an interrupt.
173174- **PCMSKx** The individual pins.
174175
175176Table for PCICR:
176177
177178| Bit | 2 | 1 | 0 |
178179|-------|-------|-------|-------|
179180| PCICR | PORTD | PORTC | PORTB |
180181
181182Table for the pins of PCMSKx :
182183
183184| Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
184185|--------|---------|---------|---------|---------|---------|---------|---------|--------|
185186| PCMSK0 | PCINT7 | PCINT6 | PCINT5 | PCINT4 | PCINT3 | PCINT2 | PCINT1 | PCINT0 |
186187| PCMSK1 | | PCINT14 | PCINT13 | PCINT12 | PCINT11 | PCINT10 | PCINT9 | PCINT8 |
187188| PCMSK2 | PCINT23 | PCINT22 | PCINT21 | PCINT20 | PCINT19 | PCINT18 | PCINT17 | PCINT6 |
188189
189190### Example for PORT B and PORT C
190191
191192``` pascal
192193// Activate PCINT0_ISR and PCINT1_ISR
193194PCICR := %011; // PORT B and PORT C
194195PCMSK0 := %11000000; // Pin 6 + 7 of PORT B
195196PCMSK1 := %00000011; // Pin 0 + 1 of PORT C
196197```
197198
198199A 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.
199200
200201``` pascal
201202procedure PC_Int1_Interrupt; public name 'PCINT1_ISR'; interrupt;
202203begin
203204 // do something
204205end;
205206```
206207
207208# See also
208209
209210- [[AVR Embedded Tutorial|AVR Embedded Tutorials]] - Overview
210211
211212---
212213*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](/wiki-contact).*
213214Category: AVR
214215Category: Arduino
215216Category: Embedded
216217Category: Tutorials

Back to history