Raspberry Pi Pico adalah papan mikrokontroler yang dikembangkan oleh Raspberry Pi Foundation, menggunakan chip RP2040. Salah satu fitur paling menarik dari RP2040 adalah Programmable I/O (PIO), sebuah blok perangkat keras yang memungkinkan pengguna membuat antarmuka input/output yang sangat fleksibel dan efisien. PIO memungkinkan pengembang untuk merancang protokol komunikasi khusus, mengontrol perangkat eksternal dengan presisi tinggi, dan bahkan mengimplementasikan antarmuka yang tidak didukung secara native oleh RP2040. Artikel ini akan membahas secara mendalam tentang fungsi, dan penggunaan PIO di Raspberry Pi Pico. Pelajari juga Trainer Kit Raspberry Pi Pico Lengkap untuk latihan praktis menggunakan PIO.
Apa Itu PIO (Programmable I/O)?
PIO adalah blok perangkat keras khusus di RP2040 yang terdiri dari empat mesin state kecil (state machines) yang dapat diprogram secara independen. Setiap mesin state dapat menjalankan kode assembly sederhana untuk mengontrol pin GPIO dengan sangat cepat dan efisien, tanpa membebani CPU utama.
Karakteristik Utama PIO
1. Mandiri dari CPU
- PIO merupakan unit terpisah dari dua core ARM Cortex-M0+ utama di RP2040.
- Artinya, PIO bisa menangani tugas I/O tanpa campur tangan CPU, sehingga CPU bisa fokus ke logika program utama.
- Cocok untuk tugas berulang atau real-time yang butuh presisi waktu tinggi, seperti komunikasi data atau pengaturan sinyal.
- Sangat membantu dalam mengurangi latensi dan bottleneck pada sistem.
- Membuka kemungkinan multitasking yang lebih efisien di proyek embedded.
2. Kecepatan Tinggi
- PIO dapat mengontrol pin GPIO hingga frekuensi maksimal clock sistem (sekitar 125 MHz).
- Hal ini membuatnya ideal untuk:
- Membuat sinyal gelombang persegi (square wave) presisi tinggi.
- Protokol komunikasi berkecepatan tinggi.
- Bit-banging protokol yang tidak umum.
- Lebih stabil dan konsisten dibanding pendekatan dengan polling dari CPU.
3. Fleksibilitas
- PIO bisa diprogram dengan bahasa assembler PIO sederhana untuk membuat protokol kustom.
- Dapat menggantikan peran hardware seperti:
- UART (jika port UART asli penuh).
- SPI/I2C tambahan.
- PWM kustom.
- Protokol non-standar seperti NeoPixel, DShot, atau Manchester Encoding.
- Mendukung input/output kompleks yang tidak tersedia secara default di RP2040.
4. Efisiensi Daya
- Karena berjalan secara paralel dan tidak membebani CPU, PIO mengonsumsi daya yang lebih rendah untuk tugas-tugas I/O tertentu.
- Tidak perlu menyalakan prosesor penuh hanya untuk menghasilkan sinyal atau membaca data secara berulang.
- Cocok untuk proyek berbasis baterai, IoT, atau wearable device yang butuh konsumsi daya minimal.
- Lebih ramah daya daripada solusi berbasis interrupt-loop di software.
Arsitektur PIO di RP2040
1. 4 State Machines (SM0–SM3)
- Masing-masing PIO block memiliki 4 mesin status (state machines) yang berjalan secara independen.
- Memiliki dua blok PIO, yang masing-masing terdiri dari empat state machine, sehingga total terdapat 8 state machine yang dapat digunakan secara bersamaan untuk menangani berbagai protokol I/O.
- Setiap state machine bisa menjalankan program PIO terpisah untuk mengatur atau membaca sinyal I/O.
- Bisa digunakan secara paralel untuk menangani banyak pin atau protokol sekaligus.
2. Instruction Memory (32 Instruksi per Block)
- Setiap PIO block memiliki instruction memory sebanyak 32 baris instruksi 16-bit.
- Semua state machine dalam satu blok berbagi memory ini, artinya program yang dijalankan oleh SM harus efisien.
- Bahasa instruksi PIO menyerupai assembly sederhana, tapi dirancang khusus untuk operasi I/O deterministik.
3. FIFO (First-In, First-Out Buffers)
- Tiap state machine dilengkapi:
- TX FIFO (CPU ➝ PIO): mengirim data dari program utama ke PIO.
- RX FIFO (PIO ➝ CPU): jalur antrian data dari PIO ke prosesor utama (CPU), memungkinkan data yang dikumpulkan atau dihasilkan oleh PIO dapat diteruskan ke program utama untuk diproses lebih lanjut.
- FIFO ini memungkinkan komunikasi asynchronous antara CPU dan PIO.
- Kapasitas FIFO: 4 kata (32-bit) per arah, cukup untuk buffering ringan dan efisien.
4. Clock Divider
- Setiap state machine memiliki clock divider sendiri.
- Clock divider menentukan seberapa cepat instruksi dieksekusi, memungkinkan pengaturan presisi timing sinyal.
- Ini membuat satu SM bisa berjalan lebih cepat atau lambat dibanding yang lain tergantung kebutuhan protokol.
5. Pin Mapping
- Setiap state machine dapat:
- Mengakses dan mengontrol berbagai pin GPIO,
- Membaca input, menulis output, dan bahkan mengatur direction pin (input/output) secara dinamis.
- Fleksibilitas ini memungkinkan satu SM mengontrol lebih dari satu pin untuk protokol yang lebih kompleks seperti SPI atau LED Matrix.
Bahasa Pemrograman PIO
Karakteristik Umum:
- Total ada 9 instruksi dasar.
- Setiap instruksi terdiri dari 16-bit.
- Ditulis dalam file berformat .pio.
- Dapat dikompilasi dan digunakan dalam C/C++ atau MicroPython (via binding).
- Disimpan dalam Instruction Memory PIO block.
Ingin belajar dasar-dasar MicroPython dan PIO? Beli E-Book Panduan Raspberry Pi Pico.
9 Instruksi Dasar PIO
1. JMP
- Fungsi: Melompat ke label/alamat instruksi tertentu.
- Contoh: jmp pin, do_something → digunakan untuk melompat ke label tertentu jika kondisi pada pin terpenuhi (misalnya pin bernilai HIGH).
- Aplikasi umum: Digunakan untuk membuat perulangan, percabangan, atau mengatur jalannya instruksi dalam program secara dinamis.
2. WAIT
- Fungsi: Menunggu hingga kondisi tertentu terpenuhi.
- Contoh: wait 1 pin 5 → tunggu hingga pin 5 menjadi HIGH.
- Aplikasi umum: Sinkronisasi dengan input luar.
3. IN
- Fungsi: Memindahkan data dari sumber (GPIO, ISR, dll) ke Input Shift Register (ISR).
- Contoh: in pins, 1 → ambil 1 bit dari pin dan masukkan ke ISR.
- Aplikasi umum: Membaca data serial/digital dari luar.
4. OUT
- Fungsi: Memindahkan data dari Output Shift Register (OSR) ke pin, register, atau lainnya.
- Contoh: out pins, 8 → kirim 8 bit dari OSR ke pin.
- Aplikasi umum: Untuk mengirimkan data satu per satu, baik secara bit maupun byte, melalui protokol kustom.
5. PUSH / PULL
- Fungsi:
- PUSH: Kirim data dari ISR ke RX FIFO.
- PULL: Ambil data dari TX FIFO ke OSR.
- Contoh: push → isi FIFO dari register internal.
- Aplikasi umum: Memungkinkan pertukaran data antara prosesor utama (CPU) dan blok PIO melalui FIFO buffer.
6. MOV
- Fungsi: Menyalin data antar register (OSR, ISR, X, Y, atau NULL).
- Contoh: mov x, isr → salin nilai dari ISR ke register X.
- Digunakan untuk: Manipulasi register dan logika sederhana.
7. IRQ
- Fungsi: Mengatur (set), menghapus (clear), atau menunggu interrupt.
- Contoh: irq 3 → digunakan untuk memicu interupsi, baik ke CPU maupun ke state machine lain dalam sistem.
- Digunakan untuk: Komunikasi antar modul/state machine.
8. SET
- Fungsi: Atur nilai register atau pin langsung.
- Contoh: set pins, 0 → instruksi ini mengatur pin output menjadi logika rendah (LOW) secara eksplisit.
- Digunakan untuk: Initialisasi atau kontrol langsung.
File .pio
- Instruksi PIO bisa ditulis dalam bentuk yang terstruktur dan modular agar mudah digunakan ulang dalam berbagai program.
- Contoh isi file .pio:
.program blink
loop:
set pins, 1
nop [31]
set pins, 0
nop [31]
jmp loop
Penggunaan dalam SDK:
- Dalam C/C++, kode .pio dikompilasi menggunakan CMake dan disisipkan dengan #include "blink.pio.h".
- Dalam MicroPython, bisa menggunakan helper function seperti StateMachine dan asm_pio().
Contoh Penggunaan PIO di Raspberry Pi Pico
1. Membuat Blink LED dengan PIO
Berikut contoh sederhana mengedipkan LED menggunakan PIO tanpa melibatkan CPU:
import rp2
from machine import Pin
@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
def blink():
set(pins, 1)
nop() [31]
set(pins, 0)
nop() [31]
sm = rp2.StateMachine(0, blink, freq=2000, set_base=Pin(25))
sm.active(1)
Penjelasan:
- `set_init=rp2.PIO.OUT_LOW` – Mengatur pin awal ke LOW.
- `set(pins, 1)` – Menyalakan LED.
- `nop() [31]` – Delay menggunakan no-operation.
- `freq=2000` – Frekuensi state machine (2 kHz).
2. Implementasi UART dengan PIO
PIO dapat digunakan untuk membuat UART software dengan presisi tinggi:
import rp2
from machine import Pin
@rp2.asm_pio(out_shiftdir=rp2.PIO.SHIFT_RIGHT, autopull=True)
def uart_tx():
pull()
set(x, 7)
label("bitloop")
out(pins, 1)
jmp(x_dec, "bitloop")
sm = rp2.StateMachine(0, uart_tx, freq=9600, out_base=Pin(0))
sm.active(1)
sm.put(0x55) # Kirim data 0x55 (huruf 'U')
Penjelasan:
- `out_shiftdir` – Mengatur arah shift data.
- `autopull=True` – Otomatis mengambil data dari FIFO.
- `set(x, 7)` – Loop 8 bit (7 + 1).
- `out(pins, 1)` – Mengirim 1 bit per instruksi.
3. Membuat PWM dengan PIO
PIO dapat menghasilkan sinyal PWM yang lebih presisi daripada PWM hardware:
import rp2
from machine import Pin
@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
def pwm():
pull(noblock)
mov(x, osr)
mov(y, isr)
label("pwmloop")
jmp(not_x, "off")
set(pins, 1)
label("on")
jmp(y_dec, "pwmloop")
label("off")
set(pins, 0)
jmp(y_dec, "pwmloop")
sm = rp2.StateMachine(0, pwm, freq=1000000, set_base=Pin(25))
sm.put(32768) # Duty cycle 50% (65536/2)
sm.active(1)
Penjelasan:
- `pull(noblock)` – Mengambil data tanpa blocking.
- `mov(x, osr)` – Memuat nilai duty cycle.
- `jmp(not_x, "off")` – Matikan pin jika x = 0.
Beli juga Starter Kit Raspberry Pi Pico untuk proyek berbasis PIO.
Baca juga : Mengenal Fungsi Internal Temperature Sensor di Raspberry Pi Pico
Siap Untuk Membuat Proyek Impianmu Menjadi Kenyataan?
Klik di sini untuk chat langsung via WhatsApp dan dapatkan dukungan langsung dari tim ahli kami!
0 on: "Mengenal Fungsi dan Penggunaan PIO (Programmable I/O) di Raspberry Pi Pico"