A.Percobaan 1 (Kontrol Greenhouse)
Rangkaian:
Flowchart:
Program:
A. MASTER
#include "main.h"
ADC_HandleTypeDef hadc1;
SPI_HandleTypeDef hspi1;
uint8_t txData[2];
uint32_t ldrValue;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC1_Init(void);
static void MX_SPI1_Init(void);
/*=========================================================*/
uint32_t Read_LDR(void)
{
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1,100);
return HAL_ADC_GetValue(&hadc1);
}
/*=========================================================*/
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();
MX_SPI1_Init();
while (1)
{
ldrValue = Read_LDR();
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==GPIO_PIN_RESET)
txData[0] = 1;
else
txData[0] = 0;
if(ldrValue < 1500)
txData[1] = 1;
else
txData[1] = 0;
HAL_SPI_Transmit(&hspi1, txData, 2, 100);
HAL_Delay(200);
}
}
/*=========================================================*/
void SystemClock_Config(void)
{
}
/*=========================================================*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/*=========================================================*/
static void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0};
hadc1.Instance = ADC1;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
HAL_ADC_Init(&hadc1);
sConfig.Channel = ADC_CHANNEL_9;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
}
/*=========================================================*/
static void MX_SPI1_Init(void)
{
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
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_OUTPUT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
HAL_SPI_Init(&hspi1);
}
B.SLAVE
#include "main.h"
SPI_HandleTypeDef hspi1;
uint8_t rxData[2];
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI1_Init(void);
/*=========================================================*/
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI1_Init();
while (1)
{
HAL_SPI_Receive(&hspi1, rxData, 2, HAL_MAX_DELAY);
if(rxData[0]==1)
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);
else
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);
if(rxData[1]==1)
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET);
else
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET);
}
}
/*=========================================================*/
void SystemClock_Config(void)
{
}
/*=========================================================*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|GPIO_PIN_1,
GPIO_PIN_RESET);
GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1;
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);
}
/*=========================================================*/
static 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;
hspi1.Init.CRCPolynomial = 7;
HAL_SPI_Init(&hspi1);
}
B.Percobaan 2 (Game Geomerty Jump)
Rangkaian :
Flowchart :
• Logika Game
Program :
A.Program Master
#include "main.h"
#include "ssd1306.h"
#include <stdio.h>
/* ================= SPI ================= */
SPI_HandleTypeDef hspi1;
/* ================= OLED I2C ================= */
I2C_HandleTypeDef hi2c1;
/* ================= COMMAND ================= */
#define CMD_GAME_RUN 0x01
#define CMD_GAME_OVER 0x02
#define CMD_JUMP_SOUND 0x03
#define CMD_HIT_SOUND 0x04
/* ================= CS PIN ================= */
#define CS_PORT GPIOA
#define CS_PIN GPIO_PIN_4
/* ================= GAME ================= */
int dinoY, velocityY, cactusX;
uint32_t score, highScore;
uint8_t isJumping, gameOver;
#define GRAVITY 2
#define FRAME_DELAY 30
#define GROUND_Y 48
#define DINO_HEIGHT 10
char buf[20];
/* ================= SEND SPI ================= */
void Send_To_Slave(uint8_t cmd)
{
HAL_GPIO_WritePin(CS_PORT, CS_PIN, GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1, &cmd, 1, 100);
HAL_GPIO_WritePin(CS_PORT, CS_PIN, GPIO_PIN_SET);
HAL_Delay(1); // penting untuk sync slave
}
/* ================= MAIN ================= */
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI1_Init();
MX_I2C1_Init();
ssd1306_Init();
HAL_GPIO_WritePin(GPIOA, CS_PIN, GPIO_PIN_SET);
ResetGame();
while (1)
{
if (!gameOver)
{
UpdateGame();
DrawGame();
Send_To_Slave(CMD_GAME_RUN);
}
else
{
DrawGameOver();
if (score > highScore)
highScore = score;
Send_To_Slave(CMD_GAME_OVER);
if (HAL_GPIO_ReadPin(JUMP_BTN_GPIO_Port, JUMP_BTN_Pin) ==
GPIO_PIN_RESET)
{
ResetGame();
HAL_Delay(300);
}
}
HAL_Delay(FRAME_DELAY);
}
}
/* ================= GAME LOGIC ================= */
void UpdateGame(void)
{
if (HAL_GPIO_ReadPin(JUMP_BTN_GPIO_Port, JUMP_BTN_Pin) ==
GPIO_PIN_RESET && !isJumping)
{
velocityY = -12;
isJumping = 1;
Send_To_Slave(CMD_JUMP_SOUND);
}
dinoY += velocityY;
velocityY += GRAVITY;
if (dinoY >= GROUND_Y)
{
dinoY = GROUND_Y;
velocityY = 0;
isJumping = 0;
}
cactusX -= (6 + score / 15);
if (cactusX < -10)
{
cactusX = 128;
score++;
}
if (cactusX < 25 && cactusX > 5 && (dinoY + DINO_HEIGHT) > 48)
{
gameOver = 1;
Send_To_Slave(CMD_HIT_SOUND);
}
}
/* ================= DRAW ================= */
void DrawGame(void)
{
ssd1306_Fill(Black);
ssd1306_DrawRectangle(10, dinoY, 20, dinoY + DINO_HEIGHT,
White);
ssd1306_FillRectangle(cactusX, 48, cactusX + 8, 60, White);
ssd1306_Line(0, 61, 127, 61, White);
sprintf(buf, "Sc:%lu", score);
ssd1306_SetCursor(0, 0);
ssd1306_WriteString(buf, Font_7x10, White);
sprintf(buf, "Hsc:%lu", highScore);
ssd1306_SetCursor(80, 0);
ssd1306_WriteString(buf, Font_7x10, White);
ssd1306_UpdateScreen();
}
void DrawGameOver(void)
{
ssd1306_Fill(Black);
ssd1306_SetCursor(30, 15);
ssd1306_WriteString("GAME OVER", Font_7x10, White);
sprintf(buf, "HighScore:%lu", highScore);
ssd1306_SetCursor(25, 35);
ssd1306_WriteString(buf, Font_7x10, White);
ssd1306_UpdateScreen();
}
/* ================= RESET ================= */
void ResetGame(void)
{
dinoY = GROUND_Y;
velocityY = 0;
cactusX = 128;
score = 0;
isJumping = 0;
gameOver = 0;
}
/* ================= SPI INIT ================= */
void MX_SPI1_Init(void)
{
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
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_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
HAL_SPI_Init(&hspi1);
}
/* ================= GPIO ================= */
void MX_GPIO_Init(void)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* CS */
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* BUTTON */
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);
}
#ifndef __MAIN_H
#define __MAIN_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32g4xx_hal.h"
#include "ssd1306.h"
#include "ssd1306_fonts.h"
#include <stdio.h>
/* Definisi Pin Hardware */
#define JUMP_BTN_Pin GPIO_PIN_0
#define JUMP_BTN_GPIO_Port GPIOA
/* Konstanta Permainan */
#define GROUND_Y 44
#define DINO_WIDTH 15
#define DINO_HEIGHT 15
/* Prototipe Fungsi */
void SystemClock_Config(void);
void MX_GPIO_Init(void);
void MX_I2C1_Init(void);
void Error_Handler(void);
#ifdef __cplusplus
}
#endif
#endif /* __MAIN_H */
B.Program Slave
#include "main.h"
/* ================= SPI ================= */
SPI_HandleTypeDef hspi1;
/* ================= COMMAND ================= */
#define CMD_GAME_RUN 0x01
#define CMD_GAME_OVER 0x02
#define CMD_JUMP_SOUND 0x03
#define CMD_HIT_SOUND 0x04
/* ================= PROTOTYPE ================= */
void SystemClock_Config(void);
void MX_GPIO_Init(void);
void MX_SPI1_Init(void);
void Send(uint8_t data);
/* ================= MAIN ================= */
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI1_Init();
while (1)
{
Send(CMD_GAME_RUN);
HAL_Delay(500);
Send(CMD_JUMP_SOUND);
HAL_Delay(500);
Send(CMD_GAME_OVER);
HAL_Delay(1000);
}
}
/* ================= SEND SPI ================= */
void Send(uint8_t data)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // CS LOW
HAL_SPI_Transmit(&hspi1, &data, 1, 100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // CS HIGH
}
/* ================= SPI INIT ================= */
void MX_SPI1_Init(void)
{
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
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_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
HAL_SPI_Init(&hspi1);
}
/* GPIO CS */
void MX_GPIO_Init(void)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
}
/* CLOCK (simple safe) */
void SystemClock_Config(void) {}
C.Percobaan 3 (Smart Entry Indicator)
Rangkaian :
Flowchart :
Program :
/* USER CODE BEGIN Header */
/**
*************************************************************
*****************
* @file : main.c
* @brief : Main program body
*************************************************************
*****************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found
in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is
provided AS-IS.
*
*************************************************************
*****************
*/
/* USER CODE END Header */
/* Includes -------------------------------------------------
-----------------*/
#include "main.h"
/* Private includes -----------------------------------------
-----------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef ------------------------------------------
-----------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define -------------------------------------------
-----------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro --------------------------------------------
-----------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ----------------------------------------
-----------------*/
COM_InitTypeDef BspCOMInit;
UART_HandleTypeDef huart1;
/* USER CODE BEGIN PV */
uint8_t pir_state;
uint8_t data;
/* USER CODE END PV */
/* Private function prototypes ------------------------------
-----------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ----------------------------------------
-----------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration---------------------------------------
-----------------*/
/* Reset of all peripherals, Initializes the Flash
interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Initialize led */
BSP_LED_Init(LED_GREEN);
/* Initialize USER push-button, will be used to trigger an
interrupt each time it's pressed.*/
BSP_PB_Init(BUTTON_USER, BUTTON_MODE_EXTI);
/* Initialize COM1 port (115200, 8 bits (7-bit data + 1
stop bit), no parity */
BspCOMInit.BaudRate = 115200;
BspCOMInit.WordLength = COM_WORDLENGTH_8B;
BspCOMInit.StopBits = COM_STOPBITS_1;
BspCOMInit.Parity = COM_PARITY_NONE;
BspCOMInit.HwFlowCtl = COM_HWCONTROL_NONE;
if (BSP_COM_Init(COM1, &BspCOMInit) != BSP_ERROR_NONE)
{
Error_Handler();
}
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
pir_state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);
if (pir_state == GPIO_PIN_SET)
data = '1';
else
data = '0';
HAL_UART_Transmit(&huart1, &data, 1, 100);
HAL_Delay(500);
}
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
*/
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_
BOOST);
/** Initializes the RCC Oscillators according to the
specified parameters
* in the RCC_OscInitTypeDef structure.
*/
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();
}
}
/**
* @brief USART1 Initialization Function
* @param None
* @retval None
*/
static void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart1.AdvancedInit.AdvFeatureInit =
UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart1,
UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart1,
UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin : PA0 */
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error
occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL
error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the
source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file
name and line number,
ex: printf("Wrong parameters value: file %s on line
%d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/* USER CODE BEGIN Header */
/* USER CODE END Header */
/* Includes -------------------------------------------------
-----------------*/
#include "main.h"
/* Private includes -----------------------------------------
-----------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef ------------------------------------------
-----------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define -------------------------------------------
-----------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro --------------------------------------------
-----------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ----------------------------------------
-----------------*/
UART_HandleTypeDef huart1;
/* USER CODE BEGIN PV */
uint8_t rx_data;
/* USER CODE END PV */
/* Private function prototypes ------------------------------
-----------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ----------------------------------------
-----------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration---------------------------------------
-----------------*/
/* Reset of all peripherals, Initializes the Flash
interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
// Coba terima data (tidak blocking lama)
if (HAL_UART_Receive(&huart1, &rx_data, 1, 10) ==
HAL_OK)
{
if (rx_data == '1')
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5,
GPIO_PIN_SET); // LED ON
}
else if (rx_data == '0')
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5,
GPIO_PIN_RESET); // LED OFF
}
}
else
{
// Kalau tidak ada data → LED kedip
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
HAL_Delay(200);
}
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the
specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue =
RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
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_HSI;
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_0) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief USART1 Initialization Function
* @param None
* @retval None
*/
static void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
/*Configure GPIO pin : PA5 */
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error
occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the
source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
D.Percobaan 4 (SISTEM PARKIR OTOMATIS 2 PINTU)
Rangkaian :
Flowchart :
Program :
/* USER CODE BEGIN Header */
/**
************************************************************
******************
* @file : main.c
* @brief : Master Parking System - STM32G474RE
************************************************************
******************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------
------------------*/
#include "main.h"
/* Private includes ----------------------------------------
------------------*/
/* USER CODE BEGIN Includes */
#define SSD1306_INCLUDE_FONT_7x10
#include "ssd1306.h"
#include "ssd1306_fonts.h"
#include <stdio.h>
#include <string.h>
/* USER CODE END Includes */
/* Private typedef -----------------------------------------
------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------
------------------*/
/* USER CODE BEGIN PD */
#define MAX_PARKIR 10
/* USER CODE END PD */
/* Private macro -------------------------------------------
------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------
------------------*/
COM_InitTypeDef BspCOMInit;
I2C_HandleTypeDef hi2c1;
TIM_HandleTypeDef htim2;
UART_HandleTypeDef huart1; // komunikasi ke slave (PC4/PC5)
UART_HandleTypeDef huart2; // serial monitor via BSP COM1
(PA2/PA3)
/* USER CODE BEGIN PV */
uint8_t sisa_parkir = MAX_PARKIR;
uint8_t kendaraan_masuk = 0;
uint8_t uart_rx_buffer[1];
/* USER CODE END PV */
/* Private function prototypes -----------------------------
------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
static void MX_TIM2_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_USART2_UART_Init(void);
/* USER CODE BEGIN PFP */
void Update_Display(void);
void Servo_Buka(void);
void Servo_Tutup(void);
/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
MX_GPIO_Init();
MX_I2C1_Init();
MX_TIM2_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
BSP_LED_Init(LED_GREEN);
BSP_PB_Init(BUTTON_USER, BUTTON_MODE_EXTI);
// Serial monitor via BSP COM1 (USART2 PA2/PA3)
BspCOMInit.BaudRate = 115200;
BspCOMInit.WordLength = COM_WORDLENGTH_8B;
BspCOMInit.StopBits = COM_STOPBITS_1;
BspCOMInit.Parity = COM_PARITY_NONE;
BspCOMInit.HwFlowCtl = COM_HWCONTROL_NONE;
if (BSP_COM_Init(COM1, &BspCOMInit) != BSP_ERROR_NONE) {
Error_Handler();
}
ssd1306_Init();
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
htim2.Instance->CCR1 = 1000;
// USART1 untuk komunikasi ke slave (PC4=TX, PC5=RX)
HAL_UART_Receive_IT(&huart1, uart_rx_buffer, 1);
printf("=== MASTER PARKING READY ===\r\n");
printf("Slot tersedia: %d/%d\r\n", sisa_parkir,
MAX_PARKIR);
Update_Display();
/* USER CODE END 2 */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
uint8_t ir =
!HAL_GPIO_ReadPin(MASTER_IR_SENSOR_GPIO_Port,
MASTER_IR_SENSOR_Pin);
printf("IR: %d | Sisa: %d\r\n", ir, sisa_parkir);
// DETEKSI MASUK
if (ir && sisa_parkir > 0 && !kendaraan_masuk) {
HAL_Delay(50);
ir = !HAL_GPIO_ReadPin(MASTER_IR_SENSOR_GPIO_Port,
MASTER_IR_SENSOR_Pin);
if (ir) {
Servo_Buka();
sisa_parkir--;
kendaraan_masuk = 1;
Update_Display();
printf(">> MASUK! Sisa: %d/%d\r\n", sisa_parkir,
MAX_PARKIR);
HAL_UART_Transmit(&huart1, (uint8_t*)"M", 1, 100);
}
}
// PARKIR PENUH
if (ir && sisa_parkir == 0 && !kendaraan_masuk) {
printf(">> PARKIR PENUH!\r\n");
BSP_LED_Toggle(LED_GREEN);
HAL_Delay(200);
}
// KENDARAAN SUDAH LEWAT
if (!ir && kendaraan_masuk) {
HAL_Delay(50);
ir = !HAL_GPIO_ReadPin(MASTER_IR_SENSOR_GPIO_Port,
MASTER_IR_SENSOR_Pin);
if (!ir) {
Servo_Tutup();
kendaraan_masuk = 0;
printf(">> Palang ditutup\r\n");
}
}
HAL_Delay(100);
}
/* USER CODE END 3 */
}
/* USER CODE BEGIN 4 */
void Update_Display(void) {
char buf[25];
ssd1306_Fill(Black);
ssd1306_SetCursor(2, 0);
ssd1306_WriteString("SISTEM PARKIR", Font_7x10, White);
ssd1306_SetCursor(2, 14);
sprintf(buf, "Slot: %d/%d", sisa_parkir, MAX_PARKIR);
ssd1306_WriteString(buf, Font_7x10, White);
ssd1306_SetCursor(2, 28);
if (sisa_parkir == 0) {
ssd1306_WriteString(">> PENUH <<", Font_7x10, White);
} else {
ssd1306_WriteString(">> TERSEDIA <<", Font_7x10, White);
}
ssd1306_UpdateScreen();
}
void Servo_Buka(void) {
htim2.Instance->CCR1 = 2000;
HAL_Delay(600);
}
void Servo_Tutup(void) {
htim2.Instance->CCR1 = 1000;
HAL_Delay(600);
}
// Terima dari slave via USART1 (PC5=RX)
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1)
{
if (uart_rx_buffer[0] == 'K')
{
if(sisa_parkir < MAX_PARKIR) sisa_parkir++;
printf(">> KENDARAAN KELUAR (SLAVE)\r\n");
printf(">> Sisa: %d/%d\r\n", sisa_parkir, MAX_PARKIR);
Update_Display();
}
HAL_UART_Receive_IT(&huart1, uart_rx_buffer, 1);
}
}
/* USER CODE END 4 */
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1
_BOOST);
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();
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();
}
static void MX_I2C1_Init(void)
{
hi2c1.Instance = I2C1;
hi2c1.Init.Timing = 0x40B285C2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK) Error_Handler();
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1,
I2C_ANALOGFILTER_ENABLE) != HAL_OK) Error_Handler();
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
Error_Handler();
}
static void MX_TIM2_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
htim2.Instance = TIM2;
htim2.Init.Prescaler = 169;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 19999;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload =
TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK) Error_Handler();
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig)
!= HAL_OK) Error_Handler();
if (HAL_TIM_PWM_Init(&htim2) != HAL_OK) Error_Handler();
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode =
TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2,
&sMasterConfig) != HAL_OK) Error_Handler();
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 1000;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC,
TIM_CHANNEL_1) != HAL_OK) Error_Handler();
HAL_TIM_MspPostInit(&htim2);
}
static void MX_USART1_UART_Init(void)
{
// USART1 - komunikasi ke slave (PC4=TX, PC5=RX) 9600 baud
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling =
UART_ONE_BIT_SAMPLE_DISABLE;
huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart1.AdvancedInit.AdvFeatureInit =
UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK) Error_Handler();
if (HAL_UARTEx_SetTxFifoThreshold(&huart1,
UART_TXFIFO_THRESHOLD_1_8) != HAL_OK) Error_Handler();
if (HAL_UARTEx_SetRxFifoThreshold(&huart1,
UART_RXFIFO_THRESHOLD_1_8) != HAL_OK) Error_Handler();
if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK)
Error_Handler();
}
static void MX_USART2_UART_Init(void)
{
// USART2 - serial monitor via BSP COM1 (PA2=TX, PA3=RX)
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
huart2.Init.OneBitSampling =
UART_ONE_BIT_SAMPLE_DISABLE;
huart2.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart2.AdvancedInit.AdvFeatureInit =
UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart2) != HAL_OK) Error_Handler();
if (HAL_UARTEx_SetTxFifoThreshold(&huart2,
UART_TXFIFO_THRESHOLD_1_8) != HAL_OK) Error_Handler();
if (HAL_UARTEx_SetRxFifoThreshold(&huart2,
UART_RXFIFO_THRESHOLD_1_8) != HAL_OK) Error_Handler();
if (HAL_UARTEx_DisableFifoMode(&huart2) != HAL_OK)
Error_Handler();
}
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
// IR sensor PA1 - aktif LOW → PULLUP
GPIO_InitStruct.Pin = MASTER_IR_SENSOR_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(MASTER_IR_SENSOR_GPIO_Port,
&GPIO_InitStruct);
// USART1 TX=PC4, RX=PC5 untuk komunikasi ke slave
GPIO_InitStruct.Pin = MASTER_TX_Pin | MASTER_RX_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}
void Error_Handler(void)
{
__disable_irq();
while (1) {}
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line) {}
#endif
/* USER CODE BEGIN Header */
/**
**************************************************************
****************
* @file : main.c
* @brief : Slave Parking System - STM32G474RE
(Pintu Keluar)
**************************************************************
****************
*/
/* USER CODE END Header */
/* Includes --------------------------------------------------
----------------*/
#include "main.h"
/* Private includes ------------------------------------------
----------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include <string.h>
/* USER CODE END Includes */
/* Private typedef -------------------------------------------
----------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define --------------------------------------------
----------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro ---------------------------------------------
----------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables -----------------------------------------
----------------*/
COM_InitTypeDef BspCOMInit;
TIM_HandleTypeDef htim2;
UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
/* USER CODE BEGIN PV */
uint8_t kendaraan_keluar = 0;
uint8_t uart_rx_buffer[1];
/* USER CODE END PV */
/* Private function prototypes -------------------------------
----------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM2_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_USART2_UART_Init(void);
/* USER CODE BEGIN PFP */
void Servo_Buka(void);
void Servo_Tutup(void);
/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
MX_GPIO_Init();
MX_TIM2_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
BSP_LED_Init(LED_GREEN);
BSP_PB_Init(BUTTON_USER, BUTTON_MODE_EXTI);
BspCOMInit.BaudRate = 115200;
BspCOMInit.WordLength = COM_WORDLENGTH_8B;
BspCOMInit.StopBits = COM_STOPBITS_1;
BspCOMInit.Parity = COM_PARITY_NONE;
BspCOMInit.HwFlowCtl = COM_HWCONTROL_NONE;
if (BSP_COM_Init(COM1, &BspCOMInit) != BSP_ERROR_NONE) {
Error_Handler();
}
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
htim2.Instance->CCR1 = 1000;
// USART2 RX interrupt - terima dari master
HAL_UART_Receive_IT(&huart1, uart_rx_buffer, 1);
HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin,
GPIO_PIN_RESET);
printf("=== SLAVE READY - Pintu Keluar ===\r\n");
/* USER CODE END 2 */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
uint8_t ir = !HAL_GPIO_ReadPin(SLAVE_IR_SENSOR_GPIO_Port,
SLAVE_IR_SENSOR_Pin);
printf("IR: %d\r\n", ir);
// === DETEKSI KENDARAAN KELUAR ===
if (ir && !kendaraan_keluar) {
HAL_Delay(50);
ir = !HAL_GPIO_ReadPin(SLAVE_IR_SENSOR_GPIO_Port,
SLAVE_IR_SENSOR_Pin);
if (ir) {
Servo_Buka();
// 1. buka palang
kendaraan_keluar = 1;
// 2. set flag
HAL_UART_Transmit(&huart1, (uint8_t*)"K", 1, 100); //
3. kirim ke master
HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin,
GPIO_PIN_SET);
printf(">> KELUAR! Kuota +1 dikirim ke master\r\n");
}
}
// === KENDARAAN SUDAH LEWAT ===
if (!ir && kendaraan_keluar) {
HAL_Delay(50);
ir = !HAL_GPIO_ReadPin(SLAVE_IR_SENSOR_GPIO_Port,
SLAVE_IR_SENSOR_Pin);
if (!ir) {
Servo_Tutup();
kendaraan_keluar = 0;
HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin,
GPIO_PIN_RESET);
printf(">> Palang ditutup, siap kendaraan
berikutnya\r\n");
}
}
HAL_Delay(100);
}
/* USER CODE END 3 */
}
/* USER CODE BEGIN 4 */
void Servo_Buka(void) {
htim2.Instance->CCR1 = 2000;
HAL_Delay(600);
}
void Servo_Tutup(void) {
htim2.Instance->CCR1 = 1000;
HAL_Delay(600);
}
// Terima info dari master via USART2
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1)
{
if (uart_rx_buffer[0] == 'M')
{
printf(">> INFO: KENDARAAN MASUK (MASTER)\r\n");
}
HAL_UART_Receive_IT(&huart1, uart_rx_buffer, 1);
}
}
/* USER CODE END 4 */
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_B
OOST);
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();
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();
}
static void MX_TIM2_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
htim2.Instance = TIM2;
htim2.Init.Prescaler = 169;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 19999;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK) Error_Handler();
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig)
!= HAL_OK) Error_Handler();
if (HAL_TIM_PWM_Init(&htim2) != HAL_OK) Error_Handler();
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode =
TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2,
&sMasterConfig) != HAL_OK) Error_Handler();
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 1000;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC,
TIM_CHANNEL_1) != HAL_OK) Error_Handler();
HAL_TIM_MspPostInit(&htim2);
}
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart1.AdvancedInit.AdvFeatureInit =
UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK) Error_Handler();
if (HAL_UARTEx_SetTxFifoThreshold(&huart1,
UART_TXFIFO_THRESHOLD_1_8) != HAL_OK) Error_Handler();
if (HAL_UARTEx_SetRxFifoThreshold(&huart1,
UART_RXFIFO_THRESHOLD_1_8) != HAL_OK) Error_Handler();
if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK)
Error_Handler();
}
static void MX_USART2_UART_Init(void)
{
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart2.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart2.AdvancedInit.AdvFeatureInit =
UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart2) != HAL_OK) Error_Handler();
if (HAL_UARTEx_SetTxFifoThreshold(&huart2,
UART_TXFIFO_THRESHOLD_1_8) != HAL_OK) Error_Handler();
if (HAL_UARTEx_SetRxFifoThreshold(&huart2,
UART_RXFIFO_THRESHOLD_1_8) != HAL_OK) Error_Handler();
if (HAL_UARTEx_DisableFifoMode(&huart2) != HAL_OK)
Error_Handler();
}
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
// LED GREEN PB7 - output
HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin,
GPIO_PIN_RESET);
GPIO_InitStruct.Pin = LED_GREEN_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LED_GREEN_GPIO_Port, &GPIO_InitStruct);
// IR sensor PA1 - aktif LOW → PULLUP
GPIO_InitStruct.Pin = SLAVE_IR_SENSOR_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(SLAVE_IR_SENSOR_GPIO_Port, &GPIO_InitStruct);
// USART2 PA2=TX, PA3=RX untuk komunikasi ke master
GPIO_InitStruct.Pin = SLAVE_USART1_TX_Pin |
SLAVE_USART1_RX_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
void Error_Handler(void)
{
__disable_irq();
while (1) {}
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line) {}
#endif
Tidak ada komentar:
Posting Komentar