Immagina un armadio con tanti cassetti. Ogni cassetto ha 8 compartimenti.
Nel nostro caso: indirizzo 4 (DDRB) e indirizzo 5 (PORTB) sono due cassetti vicini.
Ogni compartimento corrisponde a un pin fisico del microcontrollore.
Il compartimento numero 5 (bit 5) corrisponde al pin fisico D13 (quello con il LED integrato su Arduino).
Cassetto DDRB (indirizzo 4):
Ogni interruttore decide se il pin può "parlare" (OUTPUT) o solo "ascoltare" (INPUT).
Se metti 1 nel compartimento 5 del cassetto 4 → pin D13 diventa OUTPUT.
Cassetto PORTB (indirizzo 5):
Ogni interruttore manda corrente (5V) o no (0V) al pin.
Se metti 1 nel compartimento 5 del cassetto 5 → pin D13 va a 5V (LED acceso).
Se metti 0 → pin D13 va a 0V (LED spento).
Ecco perché funziona:
È solo aprire e chiudere interruttori in cassetti. Stesso identico principio vale per qualsiasi periferica programmabile: schede audio, centraline auto, altri microcontrollori.
Servo G90 360 pilotato in puro assembly, senza IDE, senza librerie, direttamente dal browser.
📌 Il valore di r17 determina la durata dell'impulso. 31 = 1.5ms = servo fermo al centro.
| Servo G90 360 | Arduino |
|---|---|
| Marrone (GND) | GND |
| Rosso (+5V) | 5V |
| Giallo (segnale PWM) | D13 (pin 13) |
Come caricare il codice:
Vai su costycnc.it/avr1/compiler.html, incolla il codice, clicca "Assemble" e poi "Connect".
Un servo G90 360 (rotazione continua) interpreta la durata dell'impulso come comando:
| Valore r17 | Durata impulso | Comportamento |
|---|---|---|
| 25-30 | 1.0-1.4 ms | Gira in un senso (es. orario) |
| 31 | 1.5 ms | FERMO al centro |
| 32-37 | 1.6-2.0 ms | Gira nell'altro senso (es. antiorario) |
Più il valore si allontana da 31, più veloce gira.
Con clock 16MHz, 31 × 512 cicli ≈ 15.872 cicli ≈ 0.99ms. Con due chiamate e il codice di contorno, si ottengono circa 1.5ms e 18.5ms.
All'accensione, tutti i registri generali (r16 compreso) valgono 0. La prima volta dec r16 → 0-1 = 255, poi 254... fino a 0. Funziona, ma in programmi complessi è meglio inizializzare con ldi r16, 0.
| Istruzione | Significato (spiegato semplice) |
|---|---|
| .org N | "indirizzo da dove comincia il codice" (es. .org 0 = parte dall'inizio, .org 0x68 = salta la tabella interrupt) |
| rjmp label | "salta a label" (vai avanti o indietro nel codice) |
| sbi a,b | "set bit b nel registro a" (compartimento b del cassetto a = 1) |
| cbi a,b | "clear bit b nel registro a" (compartimento b del cassetto a = 0) |
| rcall label | "chiama la subroutine label" (vai lì, fai quello che c'è, poi torna) |
| ret | "torna indietro" (dopo un rcall) |
| ldi r,val | "carica il valore val nel registro r" (es. ldi r17,31 = r17=31) |
| dec r | "decrementa il registro r" (r = r - 1) |
| brne label | "se l'ultima operazione non ha dato zero, salta a label" (altrimenti continua) |
Se capisci questo, hai capito come funziona qualsiasi periferica programmabile.
Esempio 1: Scheda audio Realtek
Il driver scrive bit in registri specifici per alzare/abbassare volume. Stessa cosa.
Esempio 2: Automobile e OBD2
La centralina (ECU) ha centinaia di registri. Velocità, giri, temperatura sono numeri in registri.
Esempio 3: Altri microcontrollori
STM32, ESP32, PIC: cambiano i nomi, ma il principio è identico.
Domanda: Cosa succede se cambio r17 da 31 a 28?
Impulso più corto (1.3-1.4ms). Il servo gira in un senso. Più piccolo è r17, più veloce.