2. Buat program untuk mikrokontroler STM32F103C8 di software STM32 CubeIDE dan program untuk mikrokontroler Raspberry Pi Pico di software Thonny.
3. Build program yang telah dibuat pada software STM32 CubeIDE, lalu inputkan program ke dalam mikrokontroler STM32F103C8 melalui stlink. Kemudian inputkan juga program dari software Thonny ke dalam mikrokontroler Raspberry Pi Pico melalui USB.
4. Setelah program diinputkan, uji rangkaian yang telah dirangkai sesuai dengan output yang ditentukan.
Rangkaian percobaan ini menggunakan beberapa komponen utama, yaitu Raspberry Pi Pico, STM32F103C8T6 / "Blue Pill", LCD OLED dengan antarmuka I2C, dan tiga buah push button yang masing-masing dilengkapi dengan resistor pull-down. Raspberry Pi Pico berperan sebagai master pengendali tampilan, sedangkan STM32 bertindak sebagai pengirim data input dari push button. Komunikasi antara STM32 dan Raspberry Pi Pico menggunakan protokol UART, sedangkan komunikasi antara Raspberry Pi Pico dengan OLED menggunakan protokol I2C.
Prinsip kerjanya dimulai dengan STM32 melakukan inisialisasi terhadap input digital dari ketiga push button. Ketika salah satu push button ditekan, STM32 akan membaca input tersebut dan mengirimkan data berupa karakter tertentu melalui SPI ke Raspberry Pi Pico. Raspberry Pi Pico yang terus memantau data SPI akan menerima informasi dari STM32, kemudian memproses data tersebut dan menampilkan hasilnya di layar OLED menggunakan komunikasi I2C. Misalnya, jika Button 1 ditekan, STM32 akan mengirim data ‘1’, lalu Raspberry Pi Pico akan menerjemahkannya menjadi teks "Kata Merah" dan menampilkannya pada LCD OLED. Hal yang sama berlaku untuk Button 2 dan 3 yang masing-masing akan menampilkan teks "Kata Hijau" dan "Kata Biru". Alur ini sesuai dengan diagram flowchart yang menunjukkan urutan mulai dari pembacaan input hingga output tampilan pada OLED. Dengan demikian, sistem ini merupakan contoh integrasi dua mikrokontroler menggunakan SPI serta pemanfaatan OLED sebagai media keluaran berbasis I2C.
#include "stm32f1xx_hal.h"
// Deklarasi handle SPI
SPI_HandleTypeDef hspi1;
// Deklarasi fungsi
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI1_Init(void);
int main(void) {
// Inisialisasi HAL, sistem clock, GPIO, dan SPI
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI1_Init();
// Buffer untuk status tombol [Merah, Hijau, Biru]
uint8_t button_states[3] = {0};
while (1) {
// Membaca tombol (logika terbalik karena menggunakan pull-up)
button_states[0] = !HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12); // Tombol Merah
button_states[1] = !HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_13); // Tombol Hijau
button_states[2] = !HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_14); // Tombol Biru
// Transmisi data via SPI
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // CS LOW (aktif)
HAL_SPI_Transmit(&hspi1, button_states, 3, 100); // Kirim 3 byte
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // CS HIGH (nonaktif)
HAL_Delay(100); // Delay untuk kestabilan
}
}
void SystemClock_Config(void) {
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
// Konfigurasi oscillator: HSE + PLL
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; // 8 MHz x 9 = 72 MHz
HAL_RCC_OscConfig(&RCC_OscInitStruct);
// Konfigurasi clock sistem
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK |
RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
}
static void MX_SPI1_Init(void) {
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_1LINE; // Hanya MOSI
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; // ~4.5 MHz
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 10;
HAL_SPI_Init(&hspi1);
}
static void MX_GPIO_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
// Aktifkan clock port GPIO
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
// Konfigurasi input tombol (PB12, PB13, PB14)
GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
// Konfigurasi SPI pin (PA5 = SCK, PA7 = MOSI)
GPIO_InitStruct.Pin = GPIO_PIN_5 | GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// Konfigurasi Chip Select (PA4)
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // Set awal CS HIGH
}
from machine import Pin, SoftI2C
import ssd1306
from rp2 import PIO, StateMachine, asm_pio
from time import sleep
# =========================
# OLED I2C Setup
# =========================
i2c = SoftI2C(scl=Pin(5), sda=Pin(4)) # GPIO5 = SCL, GPIO4 = SDA
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
oled.fill(0)
oled.text("SPI SLAVE READY", 0, 20)
oled.show()
# =========================
# SPI Slave PIO Program
# =========================
@asm_pio(autopush=True, push_thresh=8)
def spi_slave():
wait(0, pin, 0) # Tunggu CS LOW
set(x, 7) # Inisialisasi penghitung bit (8 bit)
label("bitloop")
in_(pins, 1) # Baca 1 bit dari MOSI (GP3)
jmp(x_dec, "bitloop") # Ulangi hingga 8 bit masuk
push(block) # Kirim byte ke FIFO
wait(1, pin, 0) # Tunggu CS HIGH
# =========================
# State Machine Setup
# =========================
sm = StateMachine(0, spi_slave,
freq=4_500_000, # Frekuensi sinkronisasi SPI
in_base=Pin(3), # GP3 sebagai MOSI
jmp_pin=Pin(1)) # GP1 sebagai CS
sm.active(1)
# =========================
# Main Loop
# =========================
while True:
if sm.rx_fifo() >= 3:
# Ambil 3 byte dari FIFO
data = [sm.get() for _ in range(3)]
print("SLAVE:", data) # Contoh output: [1, 0, 1]
# Tampilkan data di OLED
oled.fill(0)
oled.text("Data diterima:", 0, 10)
oled.text(f"Merah: {data[0]}", 0, 25)
oled.text(f"Hijau: {data[1]}", 0, 35)
oled.text(f"Biru: {data[2]}", 0, 45)
oled.show()
sleep(0.1)
Tidak ada komentar:
Posting Komentar