Sign in Join
Wiki copytemporary

AVR Embedded Tutorial - GPIO-Interrupt: what changed

Revision 1 to 2. 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-<table>
6463<thead>
65-<tr>
66-<th></th>
67-<th colspan="2">INT1</th>
68-<th></th>
69-<th colspan="2">INT0</th>
70-<th></th>
71-</tr>
64+
7265</thead>
7366<tbody>
74-<tr>
75-<td>Bit</td>
76-<td>3</td>
77-<td>2</td>
78-<td></td>
79-<td>1</td>
80-<td>0</td>
81-<td></td>
82-</tr>
83-<tr>
84-<td></td>
85-<td>0</td>
86-<td>0</td>
87-<td></td>
88-<td>0</td>
89-<td>0</td>
90-<td>Low Level on the pin</td>
91-</tr>
92-<tr>
93-<td></td>
94-<td>0</td>
95-<td>1</td>
96-<td></td>
97-<td>0</td>
98-<td>1</td>
99-<td>Every change</td>
100-</tr>
101-<tr>
102-<td></td>
103-<td>1</td>
104-<td>0</td>
105-<td></td>
106-<td>1</td>
107-<td>0</td>
108-<td>Pin goes LOW</td>
109-</tr>
110-<tr>
111-<td></td>
112-<td>1</td>
113-<td>1</td>
114-<td></td>
115-<td>1</td>
116-<td>1</td>
117-<td>Pin goes HIGH</td>
118-</tr>
67+
11968</tbody>
120-</table>
12169
12270### INT1 interrupt
12371
12472The INT1 interrupt must be set as follows:
12573
12674``` pascal
12775 EICRA := %1100; // INT1 is triggered when the pin goes HIGH.
12876 EIMSK := %10; // activate INT1.
12977```
13078
13179For the INT1 interrupt you have to use the ISR procedure for the INT1 (**INT1_ISR**).
13280
13381``` pascal
13482procedure Int1_Interrupt; public name 'INT1_ISR'; interrupt;
13583begin
13684 // do something
13785end;
13886```
13987
14088## Pin change interrupt
14189
14290This example is for an Arduino Nano (Atmega328p).
14391
14492### Terminal issue
14593
14694Output the pin status on a terminal.
14795
14896``` pascal
14997procedure WritePort(p : byte);
15098begin
15199 UARTSendString ('PB' + char(p + 48) + ':');
152100
153101 if PinB and (1 shl p) = (1 shl p) then
154102 begin
155103 UARTSendString('HIGH');
156104 end
157105 else
158106 begin
159107 UARTSendString('LOW');
160108 end;
161109end;
162110```
163111
164112### Interrupt routine
165113
166114The interrupt fires when a pin changes.
167115
168116``` pascal
169117procedure PC_Int0_Interrupt; public name 'PCINT0_ISR'; interrupt;
170118var
171119 i : byte;
172120begin
173121 UARTSendString(#27 '[0; 0H'); // Home the cursor
174122
175123 for i := 0 to 3 do
176124 begin
177125 WritePort(i);
178126 end;
179127end;
180128```
181129
182130### Declare pin change GPIO
183131
184132Activate pins PB0, PB1, PB2 and BP3 for interrupts.
185133
186134``` pascal
187135const
188136 inPortsB = %00001111; // PCINT0 + PCINT1 + PCINT2 + PCINT3
189137```
190138
191139### Activate pin change interrupt
192140
193141The parameters are described in the table below.
194142
195143``` pascal
196144procedure PC_Int0_Interrupt; public name 'PCINT0_ISR'; interrupt;
197145begin
198146 DDRB := 0;
199147 PORTB := inPortsB; // PullUp
200148
201149 // Initialize UART
202150 UARTInit;
203151
204152 // Activate PCINT0_ISR
205153 PCICR := %001; // Only on PORTB
206154 PCMSK0 := inPortsB;
207155
208156 // Activate interrupt
209157 asm
210158 Sei
211159 end;
212160
213161 // Main loop
214162 repeat
215163 // do something
216164 until 1 = 2;
217165end.
218166```
219167
220168### Registers for the Atmega328p
221169
222170The following registers are responsible for the activation of the ports/pins:
223171
224172- **PCICR** Ports that trigger an interrupt.
225173- **PCMSKx** The individual pins.
226174
227175Table for PCICR:
228176
229177| Bit | 2 | 1 | 0 |
230178|-------|-------|-------|-------|
231179| PCICR | PORTD | PORTC | PORTB |
232180
233181Table for the pins of PCMSKx :
234182
235183| Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
236184|--------|---------|---------|---------|---------|---------|---------|---------|--------|
237185| PCMSK0 | PCINT7 | PCINT6 | PCINT5 | PCINT4 | PCINT3 | PCINT2 | PCINT1 | PCINT0 |
238186| PCMSK1 | | PCINT14 | PCINT13 | PCINT12 | PCINT11 | PCINT10 | PCINT9 | PCINT8 |
239187| PCMSK2 | PCINT23 | PCINT22 | PCINT21 | PCINT20 | PCINT19 | PCINT18 | PCINT17 | PCINT6 |
240188
241189### Example for PORT B and PORT C
242190
243191``` pascal
244192// Activate PCINT0_ISR and PCINT1_ISR
245193PCICR := %011; // PORT B and PORT C
246194PCMSK0 := %11000000; // Pin 6 + 7 of PORT B
247195PCMSK1 := %00000011; // Pin 0 + 1 of PORT C
248196```
249197
250198A 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.
251199
252200``` pascal
253201procedure PC_Int1_Interrupt; public name 'PCINT1_ISR'; interrupt;
254202begin
255203 // do something
256204end;
257205```
258206
259207# See also
260208
261209- [[AVR Embedded Tutorial|AVR Embedded Tutorials]] - Overview
262210
263211---
264212*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).*
265213Category: AVR
266214Category: Arduino
267215Category: Embedded
268216Category: Tutorials

Back to history