/* Lab 5 - Software State Machines
Combination Lock System
Personal Combination: 110, 3, 71 */
#include "stm32f1xx.h"
#include <stdint.h>
// Personal Combination Numbers
#define Num1 110
#define Num2 3
#define Num3 71
// Pin Bitmasks
#define LED1_PIN (1U << 5) // PB5
#define LED2_PIN (1U << 6) // PB6
#define LED3_PIN (1U << 7) // PB7
#define PASS_PIN (1U << 8) // PB8
#define FAIL_PIN (1U << 9) // PB9
#define LOCKIN_PIN (1U << 0) // PB0
#define RESTART_PIN (1U << 1) // PB1
#define ALL_LEDS (LED1_PIN | LED2_PIN | LED3_PIN | PASS_PIN | FAIL_PIN)
// Function Prototypes
void gpio_init(void);
void usart_init(void);
void set_leds(uint32_t mask);
uint8_t read_switches(void);
void uart_print(const char* str);
void print_status(const char* state_name, uint8_t sw, uint8_t expected);
// State Definitions
typedef enum { Check1, Check2, Check3, Pass, Fail } State_t;
int main(void) {
gpio_init();
usart_init();
State_t state = Check1;
uint8_t sw;
while (1) {
// Global Restart Check
if (!(GPIOB->IDR & RESTART_PIN)) {
state = Check1;
while (!(GPIOB->IDR & RESTART_PIN)); // Wait for release
}
switch (state) {
case Check1:
set_leds(0);
if (!(GPIOB->IDR & LOCKIN_PIN)) {
sw = read_switches();
print_status("Check1", sw, Num1);
if (sw == Num1) state = Check2;
else state = Fail;
while (!(GPIOB->IDR & LOCKIN_PIN));
}
break;
case Check2:
set_leds(LED1_PIN);
if (!(GPIOB->IDR & LOCKIN_PIN)) {
sw = read_switches();
print_status("Check2", sw, Num2);
if (sw == Num2) state = Check3;
else state = Fail;
while (!(GPIOB->IDR & LOCKIN_PIN));
}
break;
case Check3:
set_leds(LED1_PIN | LED2_PIN);
if (!(GPIOB->IDR & LOCKIN_PIN)) {
sw = read_switches();
print_status("Check3", sw, Num3);
if (sw == Num3) state = Pass;
else state = Fail;
while (!(GPIOB->IDR & LOCKIN_PIN));
}
break;
case Pass:
set_leds(LED1_PIN | LED2_PIN | LED3_PIN | PASS_PIN);
break;
case Fail:
set_leds(FAIL_PIN);
break;
}
}
}
void set_leds(uint32_t mask) {
GPIOB->ODR &= ~ALL_LEDS;
GPIOB->ODR |= (mask & ALL_LEDS);
GPIOB->ODR |= (LOCKIN_PIN | RESTART_PIN);
}
uint8_t read_switches(void) {
// FIXED: Added ~ to invert logic because your hardware reads 255 when OFF
return (uint8_t)(~(GPIOA->IDR) & 0xFF);
}
void gpio_init(void) {
RCC->APB2ENR |= (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN);
GPIOA->CRL = 0x44444444; // Input Floating
GPIOB->CRL = 0x22288888; // PB0, PB1 Input Pull-up; PB5, PB6, PB7 Output
GPIOB->CRH = (GPIOB->CRH & 0xFFFFFF00) | 0x22; // PB8, PB9 Output
GPIOB->ODR |= (LOCKIN_PIN | RESTART_PIN);
}
void usart_init(void) {
RCC->APB2ENR |= RCC_APB2ENR_USART1EN | RCC_APB2ENR_IOPAEN;
GPIOA->CRH = (GPIOA->CRH & ~GPIO_CRH_CNF9) | GPIO_CRH_CNF9_1;
GPIOA->CRH = (GPIOA->CRH & ~GPIO_CRH_MODE9) | GPIO_CRH_MODE9_0 | GPIO_CRH_MODE9_1;
USART1->BRR = 0x341;
USART1->CR1 = USART_CR1_UE | USART_CR1_TE;
}
void uart_write(int ch) {
while (!(USART1->SR & USART_SR_TXE));
USART1->DR = (ch & 0xFF);
}
void uart_print(const char* str) {
while (*str) uart_write(*str++);
}
void print_status(const char* state_name, uint8_t sw, uint8_t expected) {
uart_print("\r\n[");
uart_print(state_name);
uart_print("] Sw: ");
char buf[4];
int i = 0;
uint8_t temp = sw;
if (temp == 0) buf[i++] = '0';
else {
if (temp >= 100) { buf[i++] = (temp / 100) + '0'; temp %= 100; }
if (temp >= 10 || i > 0) { buf[i++] = (temp / 10) + '0'; temp %= 10; }
buf[i++] = temp + '0';
}
buf[i] = '\0';
uart_print(buf);
uart_print(" | Expected: ");
i = 0;
temp = expected;
if (temp == 0) buf[i++] = '0';
else {
if (temp >= 100) { buf[i++] = (temp / 100) + '0'; temp %= 100; }
if (temp >= 10 || i > 0) { buf[i++] = (temp / 10) + '0'; temp %= 10; }
buf[i++] = temp + '0';
}
buf[i] = '\0';
uart_print(buf);
uart_print("\r\n");
}Loading
stm32-bluepill
stm32-bluepill