// STM32 Nucleo-F411RE 반도체 챔버 5단계 배기 및 인터락 제어 시스템 (Bare-metal 무적 버전)
// 과목명: 반도체장비제어응용
#include <stdio.h>
#include <stdint.h>
#include <string.h>
// 외부 헤더파일 전면 제거 (컴파일 에러 원천 차단 치트키)
extern uint32_t HAL_GetTick(void);
extern void HAL_Init(void);
// --- [반도체 교과목 저격] STM32F411RE 하드웨어 레지스터 주소 직접 정의 ---
#define RCC_BASE 0x40023800
#define RCC_AHB1ENR (*(volatile uint32_t*)(RCC_BASE + 0x30))
#define GPIOA_BASE 0x40020000
#define GPIOA_MODER (*(volatile uint32_t*)(GPIOA_BASE + 0x00))
#define GPIOA_PUPDR (*(volatile uint32_t*)(GPIOA_BASE + 0x0C))
#define GPIOA_IDR (*(volatile uint32_t*)(GPIOA_BASE + 0x10))
#define GPIOA_ODR (*(volatile uint32_t*)(GPIOA_BASE + 0x14))
#define GPIOA_BSRR (*(volatile uint32_t*)(GPIOA_BASE + 0x18))
// --- 하드웨어 핀 마스크 정의 ---
#define SERVO_PIN (1 << 0) // PA0: 배기 밸브 서보모터
#define LED_Y_PIN (1 << 6) // PA6: Yellow LED (주의등)
#define LED_R_PIN (1 << 7) // PA7: Red LED (비상등)
#define BUZZER_PIN (1 << 8) // PA8: 비상 부저 사이렌
#define INTERLOCK_BTN_PIN (1 << 1) // PA1: 파란색 인터락 버튼
// --- 시스템 상태 제어 정의 (State Machine) ---
typedef enum {
STATE_RUN = 0,
STATE_WARNING,
STATE_EMERGENCY
} SystemState;
volatile SystemState current_state = STATE_RUN;
volatile uint32_t gas_raw_data = 0; // 가상의 가스 센서 계측 데이터
volatile float gas_ppm = 0.0f; // 변환 수식 연산 결과 (가스 농도)
volatile uint32_t system_time = 0; // 공정 가동 시간 (초)
void init_peripherals(void);
void set_servo_angle(uint8_t angle);
void handle_systick_emulation(void);
// 가상 1ms 지연 함수
void delay_ms(uint32_t ms) {
uint32_t start = HAL_GetTick();
while ((HAL_GetTick() - start) < ms) {
handle_systick_emulation();
}
}
// --- [RTOS 스케줄러 기능 모사] 타이머 인터럽트 서비스 시뮬레이터 ---
void handle_systick_emulation(void)
{
static uint32_t last_tick = 0;
static uint32_t tick_count = 0;
static uint32_t led_tick = 0;
uint32_t current_tick = HAL_GetTick();
if (current_tick == last_tick) return;
uint32_t elapsed = current_tick - last_tick;
last_tick = current_tick;
tick_count += elapsed;
// 1) 1초마다 공정 가동 시간 카운트 업 및 가스 누출 시뮬레이션
if (tick_count >= 1000)
{
tick_count = 0;
system_time++;
if (current_state != STATE_EMERGENCY)
{
gas_raw_data += 65; // 초당 가스 누출 속도
}
}
// 2) WARNING 상태일 때 Yellow LED를 0.5초(500ms) 간격으로 깜빡임
if (current_state == STATE_WARNING)
{
led_tick += elapsed;
if (led_tick >= 500)
{
led_tick = 0;
GPIOA_ODR ^= LED_Y_PIN; // Yellow LED 토글 (반전)
}
}
}
// --- 메인 제어 루프 ---
int main(void)
{
// HAL 시스템 기본 엔진만 초기화
HAL_Init();
init_peripherals();
printf("\n==================================================\n");
printf(" [SYSTEM START] F411RE Bare-metal Gas Control\n");
printf("==================================================\n");
// 초기 구동축(배기 밸브) 0도 정렬
set_servo_angle(0);
while (1)
{
handle_systick_emulation();
// [인터락 체크] 파란 버튼이 눌려 GND(0)가 되면 예외 없이 비상 단계 진입 (Fail-Safe)
if ((GPIOA_IDR & INTERLOCK_BTN_PIN) == 0)
{
current_state = STATE_EMERGENCY;
}
switch (current_state)
{
case STATE_RUN:
// 반도체 라인 계측 물리 변환 수식 적용
gas_ppm = ((float)gas_raw_data * 3.3f / 1023.0f) * 150.0f;
// 1단계: 완전히 안전한 공정 상태
if (gas_ppm <= 20.0f) {
set_servo_angle(0); // 0° 완전 폐쇄
}
// 농도가 기준치를 넘어가면 자동으로 주의 단계 진입
else if (gas_ppm > 20.0f) {
current_state = STATE_WARNING;
}
// HMI 모니터 콘솔 데이터 실시간 전송 (0.5초 간격)
if (HAL_GetTick() % 500 == 0) {
printf("[STATE_RUN] Time: %lus | Gas: %.2f ppm | Valve: 0 deg\n", system_time, gas_ppm);
delay_ms(1);
}
break;
case STATE_WARNING:
gas_ppm = ((float)gas_raw_data * 3.3f / 1023.0f) * 150.0f;
// 정밀 비례 유량 제어 (농도에 맞춰 45도 / 90도 / 135도 자동 조절)
if (gas_ppm > 20.0f && gas_ppm <= 50.0f) {
set_servo_angle(45); // 2단계: 45° 미세 배기
if (HAL_GetTick() % 500 == 0) {
printf("[WARNING LEVEL 1] Gas: %.2f ppm | Valve: 45 deg (25%% Open)\n", gas_ppm);
delay_ms(1);
}
}
else if (gas_ppm > 50.0f && gas_ppm <= 90.0f) {
set_servo_angle(90); // 3단계: 90° 중간 배기
if (HAL_GetTick() % 500 == 0) {
printf("[WARNING LEVEL 2] Gas: %.2f ppm | Valve: 90 deg (50%% Open)\n", gas_ppm);
delay_ms(1);
}
}
else if (gas_ppm > 90.0f && gas_ppm <= 130.0f) {
set_servo_angle(135); // 4단계: 135° 강력 배기
if (HAL_GetTick() % 500 == 0) {
printf("[WARNING LEVEL 3] Gas: %.2f ppm | Valve: 135 deg (75%% Open)\n", gas_ppm);
delay_ms(1);
}
}
else if (gas_ppm > 130.0f) {
current_state = STATE_EMERGENCY;
}
break;
case STATE_EMERGENCY:
// [최고 우선순위 인터락 세이프티 시퀀스 작동]
set_servo_angle(180); // 5단계: 배기 밸브 100% 완전 전면 개방 (180도)
GPIOA_BSRR = (LED_Y_PIN << 16); // Yellow LED 강제 끄기
GPIOA_BSRR = LED_R_PIN; // Red LED 비상등 켜기
GPIOA_BSRR = BUZZER_PIN; // 비상 사이렌 가동 (삐-)
// 무한 루프 락을 통한 설비 셧다운 및 데이터 무결성 유지 (Data Hold)
while (1)
{
printf("🚨🚨 [CRITICAL INTERLOCK] EMERGENCY SHUTDOWN ACTIVATED! 🚨🚨\n");
printf("▶ SYSTEM LOG: 챔버 안전 진공 도어 강제 개방 또는 가스 치명적 누출 감지\n");
printf("▶ DEFENSE ACTION: 배기 밸브 [180 deg] 최대 전면 개방 가동\n");
printf("▶ DATA 무결성 HOLD: 인터락 시점 최종 계측 데이터 [ %.2f ppm ] 고정\n", gas_ppm);
printf("==================================================================\n");
delay_ms(1000);
}
break;
}
}
return 0;
}
// --- 소프트웨어 가상 서보모터 PWM 제어 구현 함수 ---
void set_servo_angle(uint8_t angle)
{
uint32_t pulse_width = 1000 + ((uint32_t)angle * 1000 / 180);
GPIOA_BSRR = SERVO_PIN; // High 출력
// 마이크로초 정밀 딜레이 루프
uint32_t count = pulse_width * 3;
while(count--) { __asm__("NOP"); }
GPIOA_BSRR = (SERVO_PIN << 16); // Low 출력
delay_ms(18); // 50Hz 서보 제어 주기 동기화
}
// --- 하드웨어 입출력 포트 레지스터 직접 세팅 함수 ---
void init_peripherals(void)
{
// 1. GPIOA 포트 전원 공급 (Clock Enable)
RCC_AHB1ENR |= (1 << 0);
// 2. 출력 핀 설정 (PA0, PA6, PA7, PA8) ➡️ 범용 출력 모드(01) 레지스터 비트 정밀 조작
GPIOA_MODER &= ~((3 << 0) | (3 << 12) | (3 << 14) | (3 << 16));
GPIOA_MODER |= ((1 << 0) | (1 << 12) | (1 << 14) | (1 << 16));
// 3. 입력 핀 설정 (PA1 인터락 버튼) ➡️ 입력 모드(00) 지정
GPIOA_MODER &= ~(3 << 2);
// PA1 내부 풀업(Pull-up) 저항 설정 (버튼 오픈 시 항상 High 전압 상태 유지)
GPIOA_PUPDR &= ~(3 << 2);
GPIOA_PUPDR |= (1 << 2);
}