#include "stm32l0xx_hal.h"
// Định nghĩa chân cắm
#define LED_PIN GPIO_PIN_3 // Pin (Chân cắm) - Thực thể vật lý
#define LED_PORT GPIOB // Port (Cổng) - Đơn vị quản lý logic
#define BTN_PIN GPIO_PIN_0
#define BTN_PORT GPIOA
//Prototypes: Chính là 2 dòng bạn đang hỏi (Thông báo trước các hàm sẽ dùng).
void SystemClock_Config(void); //Đây là hàm thiết lập "nhịp tim" (tốc độ xử lý) cho vi điều khiển.
//Giúp chip chạy đúng tốc độ (ví dụ 32MHz). Nếu không có nó, chip có thể chạy rất chậm hoặc các hàm thời gian như HAL_Delay sẽ bị sai.
void GPIO_Init(void); //Tên của hàm. Đây là hàm thiết lập "chế độ" cho các chân cắm (Input/Output).
//Đây là nơi chứa các lệnh biến chân PB3 thành Output (để điều khiển LED) và chân PA0 thành Input (để đọc nút nhấn).
//Danh sách tham số đầu vào. void ở đây nghĩa là hàm này không cần bạn truyền thêm thông tin gì vào để nó hoạt động.
int main(void) {
HAL_Init(); //Đây là lệnh đầu tiên phải có.
//Nó khởi tạo các bộ đệm, cấu hình ưu tiên ngắt và quan trọng nhất là thiết lập SysTick (bộ đếm thời gian hệ thống) để bạn có thể dùng hàm HAL_Delay() sau này.
//HAL_Init(): Khởi tạo nền tảng của thư viện.
//Hardware Abstraction Layer (Lớp trừu tượng hóa phần cứng).
//HAL_GPIO_Init(): Thiết lập cấu hình chân.
//HAL_GPIO_ReadPin(): Đọc dữ liệu từ nút nhấn.
//HAL_GPIO_WritePin(): Xuất lệnh điều khiển LED.
SystemClock_Config(); //Thiết lập nguồn xung nhịp (Clock).
//Nếu không có lệnh này, chip sẽ chạy với tốc độ mặc định rất chậm, làm các giao tiếp ngoại vi bị sai lệch.
GPIO_Init(); // Khởi tạo các chân I/O
while (1) {
// Đọc trạng thái nút nhấn (Mức thấp '0' khi nhấn vì dùng Pull-up)
if (HAL_GPIO_ReadPin(BTN_PORT, BTN_PIN) == GPIO_PIN_RESET) {
//BTN_PORT, BTN_PIN: Chính là cặp cổng và chân (ví dụ: GPIOA, GPIO_PIN_0) mà bạn đã #define ở đầu bài.
//GPIO_PIN_RESET: Đại diện cho mức điện áp thấp (0V).
//Nguyên lý: Ở chế độ Pull-up, khi bạn không nhấn, chân sẽ ở mức cao (3.3V). Khi bạn nhấn nút, mạch bị nối xuống đất (GND) nên điện áp tụt về 0V (RESET).
// Bật LED
HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_SET);
} else {
// Tắt LED
HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_RESET);
}
}
}
void GPIO_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
// Cấp xung nhịp cho Port A và Port B
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
// Cấu hình LED (Output)
GPIO_InitStruct.Pin = LED_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // Đẩy kéo
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct);
// Cấu hình Nút nhấn (Input)
GPIO_InitStruct.Pin = BTN_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; // Chế độ đầu vào
GPIO_InitStruct.Pull = GPIO_PULLUP; // Trở kéo lên nội bộ
HAL_GPIO_Init(BTN_PORT, &GPIO_InitStruct);
}
void SystemClock_Config(void) {
// Ở môi trường mô phỏng Wokwi, hàm này có thể để trống
// Nhưng trong thực tế, nó sẽ chứa các thiết lập tốc độ xử lý của Chip.
}