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) {
|
while(1) {
|
||||||
// Button pressed -> pin reads LOW because of pull-up
|
// Button pressed -> pin reads LOW because of pull-up
|
||||||
if (PINB & (1<<PB3)) {
|
if (!(PINB & (1<<PB3))) {
|
||||||
for (int i=0;i<=20;i++){
|
for (int i=0;i<=20;i++){
|
||||||
PORTB |= (1<<PB2); // LED ON
|
PORTB |= (1<<PB2); // LED ON
|
||||||
delay_ms(200);
|
delay_ms(200);
|
||||||
|
|||||||
Reference in New Issue
Block a user