पाठ 18 / 25
Bit Manipulation, Registers and volatile
DDRx, PORTx, PINx on the ATmega328P.
Talking to hardware directly
Peripherals are controlled through memory-mapped registers: special addresses where each bit controls or reports something. On the ATmega328P (Arduino Uno R3) each I/O port has three: DDRx sets direction (1 = output), PORTx sets output level or enables the pull-up on inputs, and PINx reads input levels. Uno digital pin 13 is bit 5 of port B (PB5), pins 0-7 are port D and pins 8-13 are PB0-PB5; check your board's pinout. Use bitwise operators: set with |= (1 << n), clear with &= ~(1 << n), toggle with ^= and test with &. Register access is much faster than digitalWrite but ties code to one chip. The volatile qualifier tells the compiler that a variable can change outside normal program flow (hardware registers, or variables shared with an interrupt), so every access must really read or write memory instead of using a cached copy.
Blink pin 13 with direct register access
Plain embedded C for the ATmega328P at 16 MHz (avr-libc).
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
int main(void) {
DDRB |= (1 << DDB5); /* PB5 (Uno pin 13) as output */
for (;;) {
PORTB ^= (1 << PORTB5); /* toggle the LED */
_delay_ms(500);
if (!(PINB & (1 << PINB0))) {
/* PB0 (Uno pin 8) reads LOW: e.g. a button to GND with pull-up */
}
}
}Common bit operations
Reusable C macros.
#define BIT_SET(reg, n) ((reg) |= (1u << (n)))
#define BIT_CLEAR(reg, n) ((reg) &= ~(1u << (n)))
#define BIT_TOGGLE(reg, n) ((reg) ^= (1u << (n)))
#define BIT_READ(reg, n) (((reg) >> (n)) & 1u)
/* configure PB0 as input with internal pull-up (ATmega328P) */
void button_init(void) {
BIT_CLEAR(DDRB, DDB0); /* input */
BIT_SET(PORTB, PORTB0); /* PORTx bit on an input = pull-up enabled */
}Read-modify-write is not atomic
An expression like PORTB |= mask reads, modifies and writes. If an interrupt changes the same register in between, an update can be lost. Disable interrupts around such sequences when ISRs touch the same port.
त्वरित जाँच: On the ATmega328P, which register sets whether a pin is an input or an output?
- DDRx
- PORTx
- PINx
- ADCSRA
Answer
DDRx — DDR stands for Data Direction Register.