fix input logic (pull-up) + add GPIO notes
This commit is contained in:
88
LED Blink Input Output/GPIO-notes-pins.md
Normal file
88
LED Blink Input Output/GPIO-notes-pins.md
Normal file
@@ -0,0 +1,88 @@
|
||||
# Digital INPUT OUTPUT
|
||||
|
||||
There are three registers which initialize Digital INPUT and DIGITAL OUTPUT port:
|
||||
|
||||
1. DDRB
|
||||
2. DDRC
|
||||
3. DDRD
|
||||
|
||||
Each pin is 1 bit of DDRx.
|
||||
|
||||
Here P means Port
|
||||
Example: PC → Port C
|
||||
|
||||
Microcontroller pins are grouped as:
|
||||
|
||||
1. PORTB → PB0–PB7
|
||||
2. PORTC → PC0–PC6
|
||||
3. PORTD → PD0–PD7
|
||||
|
||||
---
|
||||
|
||||
## Important
|
||||
|
||||
- In Arduino Uno, PC7 does not exist
|
||||
→ PORTC is only PC0–PC6
|
||||
|
||||
- PB6 and PB7 are used by 16MHz crystal
|
||||
→ DO NOT USE
|
||||
|
||||
- PC6 is RESET pin
|
||||
→ DO NOT USE as GPIO
|
||||
→ can reset system
|
||||
|
||||
- PD0 and PD1 are Serial pins (RX TX)
|
||||
→ used for USB upload and debugging
|
||||
→ DO NOT USE during development
|
||||
|
||||
---
|
||||
|
||||
## SPI (just remember)
|
||||
|
||||
- PB3 → MOSI
|
||||
- PB4 → MISO
|
||||
- PB5 → SCK
|
||||
|
||||
→ used for SPI and programming
|
||||
→ can be used as GPIO but avoid if SPI used
|
||||
→ PB5 has onboard LED
|
||||
|
||||
---
|
||||
|
||||
## I2C (just remember)
|
||||
|
||||
- PC4 → SDA
|
||||
- PC5 → SCL
|
||||
|
||||
→ used for I2C communication
|
||||
|
||||
---
|
||||
|
||||
## Safe pins for Digital I/O
|
||||
|
||||
- PORTD → PD2–PD7
|
||||
- PORTB → PB0–PB2 (PB3–PB5 usable but SPI)
|
||||
- PORTC → PC0–PC5 (PC4 PC5 shared with I2C)
|
||||
|
||||
---
|
||||
|
||||
## Use with care
|
||||
|
||||
- PB3 PB4 PB5 → SPI pins
|
||||
- PC4 PC5 → I2C pins
|
||||
|
||||
---
|
||||
|
||||
## Final
|
||||
|
||||
Best pins to use:
|
||||
|
||||
PD2–PD7
|
||||
PB0–PB2
|
||||
PC0–PC5
|
||||
|
||||
Avoid:
|
||||
|
||||
PB6 PB7 → crystal
|
||||
PC6 → reset
|
||||
PD0 PD1 → serial
|
||||
184
LED Blink Input Output/How-to-write-GPIO-notes.md
Normal file
184
LED Blink Input Output/How-to-write-GPIO-notes.md
Normal file
@@ -0,0 +1,184 @@
|
||||
# INPUT OUTPUT (DDRx Register)
|
||||
|
||||
To configure a pin as INPUT or OUTPUT, we use DDRx register.
|
||||
|
||||
- DDRx bit = 1 → OUTPUT
|
||||
- DDRx bit = 0 → INPUT
|
||||
|
||||
---
|
||||
|
||||
## Problem
|
||||
|
||||
Using direct assignment:
|
||||
|
||||
DDRB = 0b00000001;
|
||||
|
||||
→ PB0 = OUTPUT
|
||||
→ PB1–PB7 = INPUT
|
||||
|
||||
This is not good because:
|
||||
- it overwrites all bits
|
||||
- existing configuration is lost
|
||||
|
||||
---
|
||||
|
||||
## Correct approach (safe and professional)
|
||||
|
||||
### Set PB0 as OUTPUT
|
||||
|
||||
DDRB |= (1 << PB0);
|
||||
|
||||
Explanation:
|
||||
|
||||
Assume DDRB = 11111110
|
||||
|
||||
(1 << PB0) = 00000001
|
||||
|
||||
11111110
|
||||
00000001 (OR)
|
||||
--------
|
||||
11111111
|
||||
|
||||
→ Only PB0 becomes OUTPUT
|
||||
→ other pins unchanged
|
||||
|
||||
---
|
||||
|
||||
### Set PB0 as INPUT
|
||||
|
||||
DDRB &= ~(1 << PB0);
|
||||
|
||||
Explanation:
|
||||
|
||||
Assume DDRB = 11111111
|
||||
|
||||
(1 << PB0) = 00000001
|
||||
~(1 << PB0) = 11111110
|
||||
|
||||
11111111
|
||||
11111110 (AND)
|
||||
--------
|
||||
11111110
|
||||
|
||||
→ PB0 becomes INPUT
|
||||
→ other pins unchanged
|
||||
|
||||
---
|
||||
|
||||
## Final
|
||||
|
||||
- OUTPUT → DDRx |= (1 << Px)
|
||||
- INPUT → DDRx &= ~(1 << Px)
|
||||
|
||||
This method:
|
||||
- does not disturb other pins
|
||||
- is scalable
|
||||
- is standard embedded practice
|
||||
|
||||
# PORTx and PINx (Output and Input Control)
|
||||
|
||||
0xFF can be used in hex for 8-bit and 0b11111111 in binary.
|
||||
Both represent all bits = 1.
|
||||
|
||||
---
|
||||
|
||||
## OUTPUT (Using PORTx)
|
||||
|
||||
After setting direction using DDRx, we use PORTx to control output.
|
||||
|
||||
Set pin HIGH:
|
||||
|
||||
PORTB |= (1<<PB0);
|
||||
|
||||
→ PB0 = HIGH (5V)
|
||||
|
||||
Set pin LOW:
|
||||
|
||||
PORTB &= ~(1<<PB0);
|
||||
|
||||
→ PB0 = LOW (0V)
|
||||
|
||||
This follows same bit logic (OR to set, AND with NOT to clear).
|
||||
|
||||
---
|
||||
|
||||
## INPUT (Important concept)
|
||||
|
||||
To use pin as INPUT:
|
||||
|
||||
DDRB &= ~(1<<PB0);
|
||||
|
||||
Now PB0 is INPUT.
|
||||
|
||||
---
|
||||
|
||||
## Pull-up requirement
|
||||
|
||||
If input is left floating:
|
||||
- Noise (EMF, static) can cause false HIGH/LOW
|
||||
|
||||
So we enable internal pull-up:
|
||||
|
||||
PORTB |= (1<<PB0);
|
||||
|
||||
Now:
|
||||
- Default = HIGH
|
||||
- Pressed (connected to GND) = LOW
|
||||
|
||||
---
|
||||
|
||||
## Reading input (PINx)
|
||||
|
||||
PINx register reads actual pin state.
|
||||
|
||||
Example:
|
||||
|
||||
if (!(PINB & (1<<PB0))) {
|
||||
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
## Logic explanation
|
||||
|
||||
Case 1: Button NOT pressed
|
||||
|
||||
PINB bit = 1
|
||||
|
||||
PINB & (1<<PB0) = 1
|
||||
|
||||
!1 = 0 → FALSE
|
||||
|
||||
→ goes to else
|
||||
|
||||
---
|
||||
|
||||
Case 2: Button pressed
|
||||
|
||||
PINB bit = 0
|
||||
|
||||
PINB & (1<<PB0) = 0
|
||||
|
||||
!0 = 1 → TRUE
|
||||
|
||||
→ enters if
|
||||
|
||||
---
|
||||
|
||||
## Final understanding
|
||||
|
||||
- DDRx → direction
|
||||
- PORTx → output / pull-up
|
||||
- PINx → input reading
|
||||
|
||||
---
|
||||
|
||||
## Key point
|
||||
|
||||
Pull-up makes:
|
||||
- Not pressed → HIGH
|
||||
- Pressed → LOW
|
||||
|
||||
So logic is inverted:
|
||||
- LOW = pressed
|
||||
- HIGH = not pressed
|
||||
@@ -14,7 +14,7 @@ int main(void) {
|
||||
|
||||
while(1) {
|
||||
// Button pressed -> pin reads LOW because of pull-up
|
||||
if (PINB & (1<<PB3)) {
|
||||
if (!(PINB & (1<<PB3))) {
|
||||
for (int i=0;i<=20;i++){
|
||||
PORTB |= (1<<PB2); // LED ON
|
||||
delay_ms(200);
|
||||
|
||||
Reference in New Issue
Block a user