- Pahami terlebih dahulu kondisi yang akan digunakan
- Buka Wokwi
- Persiapkan alat dan bahan
- Buat rangkaian sesuai dengan kondisi dan modul
- Sesuaikan konfigurasi pin
- Buat kode program untuk mengoperasikan rangkaian tersebut sesuai dengan kondisi
- Jalankan simulasi rangkaian.
- Proses selesai
2. Hardware dan Diagram Blok[Kembali]
a. Hardware
1. STM32 NUCLEO-G474RE
1. STM32 NUCLEO-G474RE
STM32 NUCLEO-G474RE adalah development board (papan pengembangan) terjangkau dan fleksibel dari STMicroelectronics, yang didasarkan pada mikrokontroler STM32G474RE (Arm® Cortex®-M4 @170MHz, 512KB Flash). Papan ini mendukung konektivitas Arduino Uno V3 dan ST Morpho, serta dilengkapi debugger ST-LINK terintegrasi, menjadikannya ideal untuk pembuatan prototipe cepat.
LCD I2C dan OLED I2C adalah modul layar karakter atau grafis yang menggunakan protokol komunikasi serial I2C (Inter-Integrated Circuit).
Pushbutton adalah komponen sakelar mekanis sederhana yang dioperasikan dengan cara ditekan untuk menghubungkan (on) atau memutuskan (off) aliran arus listrik dalam suatu rangkaian..
4. Buzzer
Buzzer adalah suatu komponen elektronika yang berfungsi untuk mengubah energi listrik menjadi energi suara (bunyi) melalui mekanisme getaran. Komponen ini termasuk dalam kategori output device karena digunakan untuk memberikan respon berupa suara terhadap suatu kondisi atau perintah dalam rangkaian elektronik.
5. Resistor
Resistor adalah komponen elektronik pasif yang berfungsi untuk membatasi arus listrik dalam suatu rangkaian. Resistor bekerja berdasarkan hukum Ohm, yang menyatakan bahwa tegangan (V) = arus (I) × resistansi (R). Resistor memiliki satuan Ohm (Ω) dan digunakan dalam berbagai aplikasi seperti pembagian tegangan, kontrol arus, dan proteksi rangkaian elektronik.
6. LED
b. Diagram Blok3. Rangkaian Simulasi dan Prinsip Kerja[Kembali]
a) Master
#include "main.h"
#include "stm32g4xx_hal_i2c.h"
/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;
#define SSD1306_I2C_PORT hi2c1
/* Variabel Game */
int dinoY = GROUND_Y;
int velocityY = 0;
const int gravity = 2;
uint8_t isJumping = 0;
int cactusX = 128;
uint32_t score = 0;
char scoreBuf[10];
uint8_t gameOver = 0;
uint32_t highScore = 0;
/* Private function prototypes -----------------------------------------------*/
void ResetGame(void);
int main(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C1_Init();
/* USER CODE BEGIN 2 */
ssd1306_Init();
ssd1306_Fill(Black);
ssd1306_UpdateScreen();
/* USER CODE END 2 */
while (1)
{
if (!gameOver)
{
/* 1. Input Handling (Pull-up: LOW = Pressed) */
if (HAL_GPIO_ReadPin(JUMP_BTN_GPIO_Port, JUMP_BTN_Pin) == GPIO_PIN_RESET && !isJumping)
{
velocityY = -12;
isJumping = 1;
}
/* 2. Physics Update */
dinoY += velocityY;
velocityY += gravity;
if (dinoY >= GROUND_Y)
{
dinoY = GROUND_Y;
isJumping = 0;
velocityY = 0;
}
/* 3. Obstacle Update */
cactusX -= 6;
if (cactusX < -10)
{
cactusX = 128;
score++;
}
/* 4. Collision Detection */
// Hitbox sederhana: Jika kaktus berada di area Dino dan Dino tidak cukup tinggi
if (cactusX < 25 && cactusX > 5 && (dinoY + DINO_HEIGHT) > 48)
{
gameOver = 1;
}
/* 5. Rendering */
ssd1306_Fill(Black);
// Menggambar Dino (Kotak)
ssd1306_DrawRectangle(10, dinoY, 10 + DINO_WIDTH, dinoY + DINO_HEIGHT, White);
// Menggambar Kaktus (Isi penuh)
ssd1306_FillRectangle(cactusX, 48, cactusX + 8, 60, White);
// Garis Tanah
ssd1306_Line(0, 61, 127, 61, White);
// Menampilkan Score
sprintf(scoreBuf, "Score: %lu", score);
ssd1306_SetCursor(0, 0);
ssd1306_WriteString(scoreBuf, Font_7x10, White);
ssd1306_UpdateScreen();
}
else
{
char hsBuf[20];
ssd1306_Fill(Black);
ssd1306_SetCursor(35, 25);
ssd1306_WriteString("GAME OVER", Font_7x10, White);
ssd1306_SetCursor(20, 10);
sprintf(hsBuf, "HighScore: %lu", highScore);
ssd1306_WriteString(hsBuf, Font_7x10, White);
ssd1306_UpdateScreen();
// Update high score
if (score > highScore)
{
highScore = score;
}
// restart
if (HAL_GPIO_ReadPin(JUMP_BTN_GPIO_Port, JUMP_BTN_Pin) == GPIO_PIN_RESET)
{
ResetGame();
HAL_Delay(300);
}
}
}
}
void ResetGame(void)
{
dinoY = GROUND_Y;
velocityY = 0;
isJumping = 0;
cactusX = 128;
score = 0;
gameOver = 0;
}
void MX_I2C1_Init(void)
{
hi2c1.Instance = I2C1;
hi2c1.Init.Timing = 0x00303D5D;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}
}
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
/* Konfigurasi PA0 sebagai Input Pull-up */
GPIO_InitStruct.Pin = JUMP_BTN_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(JUMP_BTN_GPIO_Port, &GPIO_InitStruct);
}
void Error_Handler(void)
{
__disable_irq();
while (1) {}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV4;
RCC_OscInitStruct.PLL.PLLN = 85;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
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_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
Error_Handler();
}
}
b) slave
#include "main.h"
#include "stm32g4xx_hal_spi.h"
/* =========================================================
GLOBAL HANDLE
========================================================= */
SPI_HandleTypeDef hspi1;
/* =========================================================
GLOBAL VARIABLE
========================================================= */
static uint8_t rxData;
/* =========================================================
MAIN
========================================================= */
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI1_Init();
/* LED awal */
HAL_GPIO_WritePin(LED_GREEN_GPIO_Port,
LED_GREEN_Pin,
GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED_RED_GPIO_Port,
LED_RED_Pin,
GPIO_PIN_RESET);
while (1)
{
/* =====================================
TERIMA DATA SPI
===================================== */
HAL_SPI_Receive(&hspi1,
&rxData,
1,
HAL_MAX_DELAY);
/* =====================================
PROCESS COMMAND
===================================== */
switch (rxData)
{
/* ================================
GAME RUN
================================ */
case CMD_GAME_RUN:
HAL_GPIO_WritePin(LED_GREEN_GPIO_Port,
LED_GREEN_Pin,
GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_RED_GPIO_Port,
LED_RED_Pin,
GPIO_PIN_RESET);
break;
/* ================================
GAME OVER
================================ */
case CMD_GAME_OVER:
HAL_GPIO_WritePin(LED_GREEN_GPIO_Port,
LED_GREEN_Pin,
GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED_RED_GPIO_Port,
LED_RED_Pin,
GPIO_PIN_SET);
break;
/* ================================
JUMP SOUND
================================ */
case CMD_JUMP_SOUND:
Beep_Jump();
break;
/* ================================
HIT SOUND
================================ */
case CMD_HIT_SOUND:
Beep_Hit();
break;
default:
break;
}
}
}
/* =========================================================
BEEP JUMP
bib
========================================================= */
void Beep_Jump(void)
{
HAL_GPIO_WritePin(BUZZER_GPIO_Port,
BUZZER_Pin,
GPIO_PIN_SET);
HAL_Delay(80);
HAL_GPIO_WritePin(BUZZER_GPIO_Port,
BUZZER_Pin,
GPIO_PIN_RESET);
}
/* =========================================================
BEEP HIT
bib bib biiiiib
========================================================= */
void Beep_Hit(void)
{
/* bib */
HAL_GPIO_WritePin(BUZZER_GPIO_Port,
BUZZER_Pin,
GPIO_PIN_SET);
HAL_Delay(100);
HAL_GPIO_WritePin(BUZZER_GPIO_Port,
BUZZER_Pin,
GPIO_PIN_RESET);
HAL_Delay(100);
/* bib */
HAL_GPIO_WritePin(BUZZER_GPIO_Port,
BUZZER_Pin,
GPIO_PIN_SET);
HAL_Delay(100);
HAL_GPIO_WritePin(BUZZER_GPIO_Port,
BUZZER_Pin,
GPIO_PIN_RESET);
HAL_Delay(100);
/* biiiiib */
HAL_GPIO_WritePin(BUZZER_GPIO_Port,
BUZZER_Pin,
GPIO_PIN_SET);
HAL_Delay(500);
HAL_GPIO_WritePin(BUZZER_GPIO_Port,
BUZZER_Pin,
GPIO_PIN_RESET);
}
/* =========================================================
GPIO INIT
========================================================= */
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* =====================================
CLOCK ENABLE
===================================== */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/* =====================================
LED + BUZZER OUTPUT
===================================== */
GPIO_InitStruct.Pin =
LED_GREEN_Pin |
LED_RED_Pin |
BUZZER_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB,
&GPIO_InitStruct);
/* =====================================
SPI1 GPIO
PA4 = NSS
PA5 = SCK
PA6 = MISO
PA7 = MOSI
===================================== */
GPIO_InitStruct.Pin =
GPIO_PIN_4 |
GPIO_PIN_5 |
GPIO_PIN_6 |
GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA,
&GPIO_InitStruct);
}
/* =========================================================
SPI1 INIT
========================================================= */
void MX_SPI1_Init(void)
{
hspi1.Instance = SPI1;
hspi1.Init.Mode =
SPI_MODE_SLAVE;
hspi1.Init.Direction =
SPI_DIRECTION_2LINES;
hspi1.Init.DataSize =
SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity =
SPI_POLARITY_LOW;
hspi1.Init.CLKPhase =
SPI_PHASE_1EDGE;
hspi1.Init.NSS =
SPI_NSS_HARD_INPUT;
hspi1.Init.FirstBit =
SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode =
SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation =
SPI_CRCCALCULATION_DISABLE;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
}
/* =========================================================
CLOCK CONFIG
========================================================= */
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
HAL_PWREx_ControlVoltageScaling(
PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType =
RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState =
RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState =
RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource =
RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM =
RCC_PLLM_DIV4;
RCC_OscInitStruct.PLL.PLLN =
85;
RCC_OscInitStruct.PLL.PLLR =
RCC_PLLR_DIV2;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType =
RCC_CLOCKTYPE_SYSCLK |
RCC_CLOCKTYPE_HCLK |
RCC_CLOCKTYPE_PCLK1 |
RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource =
RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider =
RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider =
RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider =
RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(
&RCC_ClkInitStruct,
FLASH_LATENCY_4
);
}
/* =========================================================
ERROR HANDLER
========================================================= */
void Error_Handler(void)
{
__disable_irq();
while (1)
{
}
}
Download Video Simulasi [Klik Disini]
Download Analisa [Klik Disini]
.png)
No comments:
Post a Comment