Skip to content

Công nghệ 9 giây

“Website hướng dẫn, thử nghiệm và giải thích công nghệ theo cách dễ hiểu cho mọi người.”

Menu
  • Home
  • Công nghệ
  • STM32
  • ESP32
  • Altium Desinger
  • Kiến thức điện máy
Menu

BÀI 24 – GPIO STM32: ĐỌC NÚT NHẤN VÀ CHỐNG DỘI PHÍM

Posted on August 20, 2026August 23, 2026 by congnghe9s

BÀI 24 – GPIO STM32: ĐỌC NÚT NHẤN VÀ CHỐNG DỘI PHÍM

Ở Bài 23, chúng ta đã học cách đọc trạng thái của một chân GPIO Input.
Bây giờ ta nâng lên một bước rất quan trọng:

Dùng GPIO Input để đọc nút nhấn và điều khiển LED.

Đây là bài cực kỳ quan trọng vì sau này bạn sẽ dùng nguyên lý này cho:

  • nút nhấn
  • công tắc
  • cảm biến ON/OFF
  • relay feedback
  • encoder
  • keypad
  • tín hiệu báo lỗi
  • tín hiệu từ mạch điều khiển khác

1. Mạch thực tế

Ta làm một mạch rất đơn giản:

        STM32F103C8T6
       ┌──────────────┐
       │              │
       │         PC13 ├──── LED
       │              │
       │         PA0  ├─────┐
       │              │     │
       └──────────────┘     │
                            │
                         ┌──┴──┐
                         │ NÚT │
                         │ NHẤN│
                         └──┬──┘
                            │
                           GND

Ta muốn:

Không nhấn nút → LED OFF

Nhấn nút        → LED ON

Nhưng có một vấn đề:

PA0 không thể để hở khi nút không nhấn.


2. Tại sao GPIO Input không được để hở?

Giả sử:

PA0 ─────── Nút ───── GND

Khi nhấn:

PA0 = 0

Rất rõ ràng.

Nhưng khi thả nút:

PA0 ─────── X

PA0 không được nối với:

VCC

cũng không nối:

GND

Nó gọi là:

Floating Input – đầu vào bị thả nổi.

Khi đó PA0 có thể đọc:

0
1
0
0
1
1
0
...

mặc dù bạn không làm gì cả.


3. Dùng Pull-Up

Một giải pháp cực kỳ phổ biến là:

               VCC
                │
              10kΩ
                │
                ├──────── PA0
                │
              NÚT NHẤN
                │
               GND

Khi không nhấn:

VCC
 │
10k
 │
PA0

→ PA0 = 1

Khi nhấn:

VCC
 │
10k
 │
PA0
 │
NÚT
 │
GND

→ PA0 = 0

Vì vậy:

Nút PA0
Không nhấn 1
Nhấn 0

Đây là kiểu:

Active LOW


4. STM32 có Pull-Up bên trong

Điểm rất hay là STM32F103 có thể bật:

Internal Pull-Up

Do đó bạn thường không cần điện trở 10kΩ bên ngoài cho bài thử nghiệm đơn giản.

Ta cấu hình:

PA0 = Input Pull-Up

Sơ đồ:

       STM32F103
       ┌────────┐
       │        │
       │ PA0 ───┼──── NÚT
       │        │      │
       │        │     GND
       └────────┘

Bên trong STM32:

       VCC
        │
      Pull-Up
        │
        ├──── PA0
        │
       NÚT
        │
       GND

5. Logic của chương trình

Ta có:

if (PA0 == 0)
{
    LED_ON();
}
else
{
    LED_OFF();
}

Điều rất quan trọng cần nhớ:

Nút nhấn không nhất thiết phải tương ứng với logic 1.

Trong mạch Pull-Up:

Nhấn     → 0
Thả      → 1

Đây là lý do khi lập trình embedded bạn thường gặp:

ACTIVE_LOW

6. Đọc GPIO bằng Register

Bây giờ quay lại kiến thức các bài trước.

STM32 có:

GPIOA

và trạng thái Input được đọc từ:

GPIOA_IDR

IDR =

Input Data Register

Ví dụ:

uint32_t value;

value = GPIOA->IDR;

Lúc này:

value

chứa trạng thái của toàn bộ các chân GPIOA.

Ví dụ:

GPIOA_IDR

31 ................. 0
        ... PA2 PA1 PA0

7. Chỉ lấy PA0

PA0 tương ứng:

bit 0

Ta dùng:

if ((GPIOA->IDR & (1 << 0)) == 0)
{
    // PA0 = LOW
}

Có thể viết:

if ((GPIOA->IDR & (1U << 0)) == 0)
{
    // Nút đang nhấn
}

Hãy phân tích:

GPIOA->IDR

→ đọc thanh ghi Input.

(1U << 0)

→ tạo mask:

00000001

Sau đó:

GPIOA->IDR & (1U << 0)

→ chỉ giữ lại bit PA0.


8. Nếu PA0 là HIGH

Ví dụ:

GPIOA->IDR = xxxx xxxx xxxx 0001

Ta thực hiện:

0001
&
0001
----
0001

Kết quả khác 0.

→ PA0 = HIGH.


9. Nếu PA0 là LOW

Ví dụ:

GPIOA->IDR = xxxx xxxx xxxx 0000

Ta có:

0000
&
0001
----
0000

→ PA0 = LOW.


10. Code đọc nút

Ví dụ giả sử:

PA0 = button
PC13 = LED

Ý tưởng:

while (1)
{
    if ((GPIOA->IDR & (1U << 0)) == 0)
    {
        // Nhấn nút
        GPIOC->ODR &= ~(1U << 13);
    }
    else
    {
        // Thả nút
        GPIOC->ODR |= (1U << 13);
    }
}

Nhưng với Blue Pill, LED PC13 thường là active LOW.

Do đó:

PC13 = 0 → LED sáng
PC13 = 1 → LED tắt

Vì vậy:

GPIOC->ODR &= ~(1U << 13);

→ LED ON.

Còn:

GPIOC->ODR |= (1U << 13);

→ LED OFF.


11. Đây là điều rất đáng nhớ

Có hai loại logic khác nhau:

Nút nhấn

PA0 = 0 → nhấn
PA0 = 1 → thả

LED Blue Pill

PC13 = 0 → sáng
PC13 = 1 → tắt

Như vậy cả hai đều là:

Active LOW

Đây là một khái niệm cực kỳ quan trọng trong embedded.


12. Nhưng xuất hiện một vấn đề mới: Bounce

Bạn nhấn nút một lần.

Ta tưởng MCU nhận:

1 → 0

Nhưng thực tế cơ khí có thể tạo:

1
0
1
0
1
0
0
0

trong vài mili-giây.

Hiện tượng này gọi là:

Button Bounce / Contact Bounce


13. Vì sao xảy ra Bounce?

Nút nhấn cơ khí không đóng mạch hoàn hảo ngay lập tức.

Khi hai tiếp điểm chạm nhau:

CHẠM
↓
TÁCH
↓
CHẠM
↓
TÁCH
↓
CHẠM
↓
ỔN ĐỊNH

STM32 chạy rất nhanh.

Ví dụ:

STM32: MHz

Nút: vài ms

MCU có thể nhìn thấy hàng loạt lần chuyển trạng thái.


14. Chống dội bằng Delay

Cách đơn giản nhất:

if (button == 0)
{
    delay_ms(20);

    if (button == 0)
    {
        // thực sự nhấn
    }
}

Ý tưởng:

Phát hiện LOW
      ↓
   chờ 20 ms
      ↓
Đọc lại
      ↓
vẫn LOW?
      ↓
YES → nút thực sự nhấn

Đây là:

Software Debounce


15. Nhưng Delay có nhược điểm

Ví dụ:

delay_ms(20);

CPU bị giữ ở đó.

Nếu chương trình có:

UART
ADC
Motor
Timer
Sensor
Display

thì delay kiểu này không phải lúc nào cũng tốt.

Sau này chúng ta sẽ học cách chống dội tốt hơn bằng:

millis / timer / state machine


16. Một kiến thức cực kỳ quan trọng: Pull-Up và Pull-Down

Có hai kiểu phổ biến.

Pull-Up

VCC
 │
 R
 │
GPIO ─── Button ─── GND

Logic:

Thả  = 1
Nhấn = 0

Pull-Down

GPIO ─── Button ─── VCC
 │
 R
 │
GND

Logic:

Thả  = 0
Nhấn = 1

So sánh:

Kiểu Thả Nhấn
Pull-Up 1 0
Pull-Down 0 1

17. Tại sao Embedded rất thích Active LOW?

Bạn sẽ gặp rất nhiều tín hiệu kiểu:

RESET
CS
NSS
ENABLE
INT
IRQ
FAULT

và ký hiệu có thể xuất hiện dưới dạng:

RESET_N
CS_N
INT_N

Chữ:

_N

thường biểu thị:

Active LOW

Ví dụ:

RESET_N = 0

→ reset đang được kích hoạt.

Đây chính là lý do bạn nên làm quen với logic Active LOW ngay từ bây giờ.


18. Bài tập thực hành

Với Blue Pill của bạn, hãy thử mạch:

PA0 ─── Button ─── GND

Cấu hình:

PA0 = Input Pull-Up
PC13 = Output

Yêu cầu:

Không nhấn → LED tắt

Nhấn → LED sáng

Sau đó đảo lại:

Không nhấn → LED sáng

Nhấn → LED tắt

19. Bài tập nâng cao

Thêm 2 nút:

PA0 → Button 1
PA1 → Button 2

Yêu cầu:

Button 1 → LED ON

Button 2 → LED OFF

Logic:

if ((GPIOA->IDR & (1U << 0)) == 0)
{
    // ON
}

if ((GPIOA->IDR & (1U << 1)) == 0)
{
    // OFF
}

Đây là bước đầu tiên để bạn tiến tới:

GPIO Input
      ↓
Button
      ↓
Debounce
      ↓
State
      ↓
State Machine
      ↓
Menu
      ↓
Keypad

20. Điều cần nhớ sau Bài 24

Bạn chỉ cần nắm chắc 7 ý:

1. GPIO Input dùng để đọc tín hiệu bên ngoài.

2. Input không được để Floating.

3. Pull-Up:
       Thả = 1
       Nhấn = 0

4. Pull-Down:
       Thả = 0
       Nhấn = 1

5. GPIOx->IDR dùng để đọc GPIO Input.

6. Dùng & và mask để lấy một bit cụ thể.

7. Nút cơ khí có Bounce → cần Debounce.

Và công thức quan trọng nhất của bài:

if ((GPIOA->IDR & (1U << 0)) == 0)
{
    // PA0 đang LOW
}

Bạn hãy đặc biệt ghi nhớ câu này:

IDR là nơi STM32 cho chúng ta biết “chân GPIO hiện tại đang ở mức 0 hay 1”.

Bài 25 chúng ta có thể đi tiếp vào một phần rất quan trọng: GPIO Output Register – tại sao ODR, BSRR, BRR khác nhau và tại sao trong STM32 người ta thích dùng BSRR để điều khiển chân GPIO hơn ODR.

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recent Posts

  • Bạn có thể hướng dẫn tôi quy trình sửa chữa một mainboard laptop cũng như mainboard của máy tính để bàn không?
  • Có những mức nguồn DC nào trên một bo mạch mainboard laptop?Kỹ thuật đốt dòng để kiểm tra nguồn laptop được thực hiện như thế nào?
  • bài tiếp theo hợp lý là: BÀI 63 – SENSOR FUSION THỰC CHIẾN: ENCODER + IMU MPU6050 + EKF + ODOMETRY X,Y,θ TRÊN STM32F103
  • BÀI 62 – EKF (EXTENDED KALMAN FILTER) CHO ROBOT 2 BÁNH: FUSION ENCODER + IMU + ƯỚC LƯỢNG X, Y, θ, V, ω
  • BÀI 61 – KALMAN FILTER CHO ENCODER + IMU: ƯỚC LƯỢNG TỐC ĐỘ, GÓC θ VÀ SENSOR FUSION

Recent Comments

No comments to show.

Archives

  • September 2026
  • August 2026
  • July 2026
  • June 2026
  • May 2026
  • February 2026

Categories

  • Altium Desinger
  • Công nghệ
  • ESP32
  • Khác
  • Kiến thức điện máy
  • STM32
Live 3D Globes Visitor
©2026 Công nghệ 9 giây | Design: Newspaperly WordPress Theme