#include "stm32f1xx.h"
#include "stdio.h"
// ====================== ĐỊNH NGHĨA CHÂN ======================
#define LED_PORT GPIOB
const uint16_t LED_PINS[5] = {GPIO_PIN_5, GPIO_PIN_6, GPIO_PIN_7, GPIO_PIN_8, GPIO_PIN_9};
// ====================== BIẾN TOÀN CỤC ======================
volatile uint32_t ticks = 0;
// ====================== SYSTICK HANDLER ======================
void SysTick_Handler(void)
{
ticks++;
}
// ====================== DELAY SỬ DỤNG TICKS ======================
void delay_ms(uint32_t ms)
{
uint32_t start = ticks;
while ((ticks - start) < ms);
}
// ====================== HÀM HỖ TRỢ ======================
uint8_t readNumber(uint16_t p0, uint16_t p1, uint16_t p2, uint16_t p3);
void displayLED(uint8_t value);
int main(void)
{
// ==================== CẤU HÌNH SYSTICK ====================
SystemCoreClock = 8000000UL; // HSI 8MHz (mặc định trên Blue Pill)
SysTick_Config(SystemCoreClock / 1000); // Cấu hình ngắt 1ms
// 1. Bật clock cho GPIOA và GPIOB
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN;
// 2. Cấu hình PB5 ~ PB9 làm Output Push-Pull 2MHz
GPIOB->CRL &= ~0xFFF00000;
GPIOB->CRL |= 0x22200000;
GPIOB->CRH &= ~0x000000FF;
GPIOB->CRH |= 0x00000022;
// 3. Cấu hình Input Pull-down cho GPIOA
GPIOA->CRL &= ~(0xFF << 0);
GPIOA->CRL |= (0x88 << 0);
GPIOA->CRL &= ~(0xFFFF << 16);
GPIOA->CRL |= (0x8888 << 16);
GPIOA->CRH &= ~(0xFFFF << 4);
GPIOA->CRH |= (0x8888 << 4);
// Bật Pull-down
GPIOA->ODR &= ~( (1<<0)|(1<<1)|(1<<4)|(1<<5)|
(1<<6)|(1<<7)|(1<<9)|(1<<10)|
(1<<11)|(1<<12) );
// Tắt hết LED ban đầu
displayLED(0);
uint8_t numA, numB, mode, result;
while(1)
{
// Đọc số A (PA4-PA7)
numA = readNumber(GPIO_PIN_4, GPIO_PIN_5, GPIO_PIN_6, GPIO_PIN_7);
// Đọc số B (PA9-PA12)
numB = readNumber(GPIO_PIN_9, GPIO_PIN_10, GPIO_PIN_11, GPIO_PIN_12);
// Đọc mode (PA0, PA1)
mode = 0;
if (GPIOA->IDR & GPIO_PIN_0) mode |= (1 << 0);
if (GPIOA->IDR & GPIO_PIN_1) mode |= (1 << 1);
// Thực hiện phép toán
switch(mode)
{
case 0: result = numA + numB; break;
case 1: result = numA & numB; break;
case 2: result = numA | numB; break;
case 3: result = (~numA) & 0x0F; break;
default: result = 0;
}
displayLED(result);
delay_ms(50); // Delay ổn định 50ms
}
}
// ====================== HÀM ĐỌC 4 BIT ======================
uint8_t readNumber(uint16_t p0, uint16_t p1, uint16_t p2, uint16_t p3)
{
uint8_t value = 0;
if (GPIOA->IDR & p0) value |= (1 << 0);
if (GPIOA->IDR & p1) value |= (1 << 1);
if (GPIOA->IDR & p2) value |= (1 << 2);
if (GPIOA->IDR & p3) value |= (1 << 3);
return value;
}
// ====================== HÀM HIỂN THỊ LED ======================
void displayLED(uint8_t value)
{
for(uint8_t i = 0; i < 5; i++)
{
if (value & (1 << i))
LED_PORT->BSRR = LED_PINS[i]; // LED ON
else
LED_PORT->BSRR = (LED_PINS[i] << 16); // LED OFF
}
}