210 lines
3.7 KiB
Markdown
210 lines
3.7 KiB
Markdown
# External Interrupt Configuration (ATmega328P)
|
||
|
||
## SREG (Status Register)
|
||
|
||
SREG is AVR status register with 8-bit status:
|
||
|
||
- Bit 0 → Carry Flag (C) – for ALU operations
|
||
- Bit 1 → Zero Flag (Z) – result is zero
|
||
- Bit 2 → Negative Flag (N) – result is negative
|
||
- Bit 3 → Two’s Complement Overflow Flag (V) – arithmetic overflow
|
||
- Bit 4 → Sign Bit (S) – N ⊕ V
|
||
- Bit 5 → Half Carry Flag (H) – carry from bit 3 to 4
|
||
- Bit 6 → Bit Copy Storage (T) – used in bit operations
|
||
- Bit 7 → Global Interrupt Enable (I) – Important for interrupt
|
||
|
||
### Enable Global Interrupt
|
||
SREG |= (1 << 7);
|
||
// or
|
||
sei();
|
||
|
||
### Disable Global Interrupt
|
||
SREG &= ~(1 << 7);
|
||
// or
|
||
cli();
|
||
|
||
---
|
||
|
||
## External Interrupt Pins
|
||
|
||
- PD2 → INT0
|
||
- PD3 → INT1
|
||
|
||
---
|
||
|
||
## EICRA (External Interrupt Control Register A)
|
||
|
||
Controls how external interrupts trigger.
|
||
|
||
### ISC (Interrupt Sense Control)
|
||
|
||
| ISCx1 | ISCx0 | Mode |
|
||
|------|------|--------------------|
|
||
| 0 | 0 | Low Level |
|
||
| 0 | 1 | Any Logical Change |
|
||
| 1 | 0 | Falling Edge |
|
||
| 1 | 1 | Rising Edge |
|
||
|
||
### Bit Positions
|
||
|
||
- INT0 → ISC01 (bit1), ISC00 (bit0)
|
||
- INT1 → ISC11 (bit3), ISC10 (bit2)
|
||
|
||
---
|
||
|
||
# Interrupt Trigger Modes (INT0)
|
||
|
||
## 1. Low Level (00) //holding button
|
||
|
||
EICRA &= ~((1 << ISC01) | (1 << ISC00));
|
||
|
||
Bit calculation:
|
||
- (1 << ISC01) = 00000010
|
||
- (1 << ISC00) = 00000001
|
||
- OR = 00000011
|
||
- NOT = 11111100
|
||
- Result → ISC01=0, ISC00=0
|
||
|
||
---
|
||
|
||
## 2. Any Logical Change (01)
|
||
|
||
EICRA &= ~(1 << ISC01);
|
||
EICRA |= (1 << ISC00);
|
||
|
||
Bit calculation:
|
||
- Clear ISC01 → 0
|
||
- Set ISC00 → 1
|
||
- Result → 01
|
||
|
||
---
|
||
|
||
## 3. Falling Edge (10)
|
||
|
||
EICRA |= (1 << ISC01);
|
||
EICRA &= ~(1 << ISC00);
|
||
|
||
Bit calculation:
|
||
- Set ISC01 → 1
|
||
- Clear ISC00 → 0
|
||
- Result → 10
|
||
|
||
---
|
||
|
||
## 4. Rising Edge (11)
|
||
|
||
EICRA |= (1 << ISC01) | (1 << ISC00);
|
||
|
||
Bit calculation:
|
||
- (1 << ISC01) = 00000010
|
||
- (1 << ISC00) = 00000001
|
||
- OR = 00000011
|
||
- Result → ISC01=1, ISC00=1
|
||
|
||
---
|
||
|
||
## INT1 (Same Logic)
|
||
|
||
Replace:
|
||
- ISC01 → ISC11
|
||
- ISC00 → ISC10
|
||
|
||
Example (Rising Edge INT1):
|
||
|
||
EICRA |= (1 << ISC11) | (1 << ISC10);
|
||
|
||
---
|
||
|
||
# Practical Note (Real Hardware Behavior)
|
||
|
||
- Button press is not 100% stable
|
||
- Causes:
|
||
- Mechanical bounce
|
||
- Loose wiring / plug-in noise
|
||
- Floating inputs
|
||
|
||
### Recommendation
|
||
|
||
- Avoid: Any Logical Change (too sensitive)
|
||
- Prefer:
|
||
- Falling Edge (more stable detection)
|
||
- Or implement HOLD logic in software
|
||
|
||
---
|
||
|
||
## EIMSK (External Interrupt Mask Register)
|
||
|
||
Controls enabling/disabling of interrupts.
|
||
|
||
### Bit Positions
|
||
|
||
- Bit 0 → INT0 enable
|
||
- Bit 1 → INT1 enable
|
||
|
||
---
|
||
|
||
## Enable / Disable Interrupt Lines
|
||
|
||
### Enable INT0
|
||
EIMSK |= (1 << INT0);
|
||
|
||
### Disable INT1
|
||
EIMSK &= ~(1 << INT1);
|
||
|
||
---
|
||
|
||
## Why Disable Unused Interrupts
|
||
|
||
- Prevent false triggering from floating pins
|
||
- Reduce noise impact
|
||
- Ensure controlled initialization
|
||
- Avoid unintended behaviour
|
||
|
||
---
|
||
|
||
## Interrupt Execution Flow
|
||
|
||
1. Configure trigger in EICRA
|
||
2. Enable interrupt in EIMSK
|
||
3. Enable global interrupt (sei)
|
||
4. Event occurs → CPU jumps to ISR
|
||
|
||
---
|
||
|
||
## ISR (Interrupt Service Routine)
|
||
|
||
ISR is executed automatically when interrupt occurs.
|
||
|
||
---
|
||
|
||
## Flag-Based Handling
|
||
|
||
### Global Flag
|
||
volatile uint8_t flag = 0;
|
||
|
||
- `volatile` required (value changes outside normal flow)
|
||
|
||
---
|
||
|
||
## ISR Definitions
|
||
|
||
### INT0 Interrupt
|
||
ISR(INT0_vect)
|
||
{
|
||
flag = 1;
|
||
}
|
||
|
||
### INT1 Interrupt
|
||
ISR(INT1_vect)
|
||
{
|
||
flag = 1;
|
||
}
|
||
|
||
---
|
||
|
||
## Important Notes
|
||
|
||
- Keep ISR short
|
||
- No delay or heavy processing inside ISR
|
||
- Use flag and handle logic in main loop
|
||
- Always use `volatile` for shared variables |