STM32 với nút nhấn 3 chế độ click, double click và long click.

stm32 voi nut nhan

Trong bài này chúng ta cùng nhau tìm hiểu cách lập trình STM32 với nút nhấn 3 chế độ click, double click và long click, cũng như cách lập trình với các trạng thái của nút nhấn.

Bài này nằm trong Serie Học STM32 từ A tới Z

Ý tưởng lập trình nút nhấn nhiều trạng thái

Chắc hẳn các bạn ai cũng đã sử dụng máy tính. Trên chuột máy tính có các nút left click và right click, và ai cũng biết rằng chúng có 3 kiểu thao tác: click, double click và hold,
tương ứng với ấn 1 lần, ấn 2 lần liên tiếp và nhấn giữ.

Vậy làm thế nào chúng ta có thể lập trình được như vậy?

Ý tưởng như sau:

Khi nút nhấn không được bấm, nó ở trạng thái rảnh IDLE.

Khi nhấn nút lần đầu tiên, nó sẽ ở trạng thái click. Lúc này có 2 trường hợp xảy ra:

  • Nút nhấn được nhả ra
  • Nút nhấn được giữ (nút nhấn đang ở trạng thái hold)

Nếu nút nhấn được nhả ra, lại có 2 trường hợp xảy ra:

  • Nút nhấn được bấm tiếp: lúc này chúng ta xác định được đây là double click
  • Nút nhấn không được bấm tiếp: chúng ta xác định được đây là single click

Nếu nút nhấn được giữ, chúng ta sẽ bắt đầu đếm xem giữ được bao lâu. Nếu lớn hơn hoặc bằng thời gian đã định nghĩa (vd: 3 giây) thì chúng ta xác định được đây là long click.

Để biểu diễn các trạng thái nút nhấn một cách dễ hiểu, người ta sử dụng State machine.

States machine là gì

State machine (máy trạng thái) là một cách lập trình theo mô hình quản lý quá trình chuyển đổi trạng thái của thiết bị. Với máy trạng thái, chúng ta tiếp cận vấn đề bằng cách chia quá trình vận hành của thiết bị thành các trạng thái. Mỗi trạng thái gồm: các hành động được thực hiện khi thiết bị ở trạng thái này, các trạng thái có thể chuyển sang, và điều kiện kích hoạt việc chuyển trạng thái.

Giống như đèn giao thông vậy: đèn chỉ có thể ở 1 trong 3 trạng thái xanh, vàng, đỏ, và chỉ chuyển sang trạng thái kế tiếp khi hết thời gian của trạng thái hiện tại.

Mình sẽ có 1 bài nói chi tiết về State Machine trong lập trình nhúng.

states machine

Trong ví dụ về nút nhấn, chúng ta sẽ định nghĩa các trạng thái của nút nhấn như sau:

  • IDLE: chưa được nhấn
  • Click: nhấn lần đầu
  • Release: nhả nút nhấn
  • 2nd Click: click lần tiếp theo

Các sự kiện để chuyển trạng thái như sau:

  • IDLE – Click: nhấn nút nhấn
  • Click – Long Click: so sánh với thời gian 3s, nếu giữ trên 3s thì trả về long click
  • Click – Release: nhả nút nhấn
  • Release – Single click: so sánh với thời gian chờ click (nghĩa là trong thời gian này nếu không được nhấn lần tiếp theo sẽ trả về kết quả Single Click)
  • Release – 2nd Click: nút được nhấn tiếp
  • 2nd Click – Release: nút nhấn được nhả ra, trả về kết quả Double click.

Cứ như vậy bạn cũng có thể nhận biết được các trạng thái triple click,…

Lập trình STM32 với nút nhấn

Khởi tạo nút nhấn ở PA0 (Input Pull Up, nút nối xuống GND) và LED ở PC13 (LED có sẵn trên KIT Blue Pill). Làm như bài 3 STM32 GPIO led và nút nhấn nhé các bạn.

Sơ đồ đấu nối STM32F103C8T6 Blue Pill với nút nhấn: PA0 nối nút nhấn xuống GND, LED PC13 có sẵn trên board

Định nghĩa khoảng thời gian

Trong button.h mình sẽ định nghĩa các khoảng thời gian để chuyển trạng thái:

  • DEBOUND_TIME: thời gian chống rung phím (debounce)
  • SINGLE_Click_Time: mốc thời gian phân biệt single click và long click
  • Double_Click_Time: thời gian tối đa giữa 2 lần nhấn nút để được tính là double click.

Sau đó định nghĩa kiểu enum các trạng thái của nút nhấn.

stm32 nut nhan 1

Tiếp theo mình định nghĩa 1 struct để lưu port và pin của nút nhấn, trạng thái nút nhấn và các biến thời gian để so sánh.

stm32 nut nhan 2

Lập trình STM32 tại các trạng thái

Trong hàm read chúng ta sẽ lần lượt kiểm tra từ trạng thái IDLE.

Nếu được nhấn, chương trình sẽ chạy xuống kiểm tra nút được nhả ra hay vẫn đang giữ.

Nếu nút được nhả ra, chúng ta kiểm tra tiếp trong khoảng thời gian Double_Click_Time có được nhấn tiếp không?

  • Nếu được nhấn: trả về double click
  • Nếu không được nhấn: chúng ta kiểm tra tiếp thời gian đã giữ nút. Nếu nhỏ hơn SINGLE_Click_Time thì trả về single click, nếu lớn hơn thì trả về long click

stm32 button

Lưu ý: Để nhận biết được double click, chương trình bắt buộc phải chờ hết khoảng Double_Click_Time sau lần nhả nút đầu tiên rồi mới dám kết luận đó là single click. Vì vậy phản hồi của single click luôn bị trễ đúng bằng khoảng thời gian này. Đặt quá dài (vd 1s) thì người dùng thấy nút “ì”, đặt quá ngắn (dưới 200ms) thì rất khó bấm được double click, thường chọn khoảng 250 – 400ms.

Để tải full code các bạn đọc bài viết: Download tài liệu STM32 và tải thư viện cùng ví dụ (lib example) về nhé.

Trong main các bạn khai báo nút nhấn, khởi tạo nút nhấn và LED.

khoi tao led và nút nhấn 1

Trong while chúng ta đọc trạng thái nút nhấn, sau đó lập trình nháy LED tương ứng với mỗi trạng thái của nút.
Các bạn có thể dùng switch case thay cho if else nếu nút có nhiều trạng thái.

stm32 nút nhấn main

Kết quả

Kết

Lập trình STM32 với nút nhấn có thể sử dụng nhiều phương pháp khác nhau. Đơn giản nhất là chúng ta dùng while để chờ ở từng state, nhược điểm là chương trình có thể bị kẹt trong while và làm chậm các tác vụ khác nếu không tối ưu code (khi đó nên dùng HAL_GetTick() để kiểm tra thời gian theo kiểu non-blocking).

Nhưng cách này cũng rất đơn giản để các bạn hiểu thêm về khái niệm State Machine trong lập trình nhúng.

Nếu thấy bài viết này hay, hãy chia sẻ tới những người bạn học hay đồng nghiệp của mình. Và nếu thắc mắc điều gì, hãy để lại bình luận và cùng gia nhập những người anh em nghiện lập trình tại đây nhé: Hội anh em nghiện lập trình

5/5 - (6 bình chọn)

4 những suy nghĩ trên “STM32 với nút nhấn 3 chế độ click, double click và long click.”

  1. nam nói:

    Hi anh,
    cảm ơn bài viết rất hay của anh. em đã làm theo và chạy đc, nhưng có 1 lỗi nhỏ, đó là trong hàm main em có sử dụng if status button giống anh thì sau khi vào rẽ nhánh double click thì sau đó nó vẫn tiếp tục vào rẽ nhánh single click. em debug thì lại ko bị hiện tượng đó. ko biết anh có bị hiện tượng này ko, mong anh chỉ giúp em lỗi sai.
    thanks anh.

  2. lương nói:

    phần BUTTON_Init(&Button1,BUTTON_GPIO_Port ,BUTTON_Pin ); em nhâp vào toàn báo lỗi chố &Button1 em mông a chỉ cách sửa ạ

  3. Nguyễn Quang Bách nói:

    anh ơi a ra thêm nhiều bài hơn được không ạ. Đây là nguồn tư liệu quý báu cho bọn em học ạ tài vì nhiều kiến thức trường không đi sâu phải tự mò anh ak. Cảm ơn a nhiều

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *