ESP32 GPIO Interrupt

Trong hướng dẫn này, chúng ta sẽ học cách sử dụng GPIO interrupt trên ESP32. GPIO interrupt trên ESP32 cho phép xử lý các sự kiện bên ngoài một cách nhanh chóng và hiệu quả, làm cho chúng trở nên thiết yếu cho các ứng dụng thời gian thực trong IoT và hệ thống nhúng. Bằng cách hiểu và cấu hình đúng các interrupt này, bạn có thể tạo ra những dự án mạnh mẽ và phản hồi nhanh, phản ứng ngay lập tức với môi trường.

ESP32 gpio interrupt

Linh Kiện Cần Thiết

1×mô-đun phát triển ESP-WROOM-32
1×Alternatively, ESP32 Uno-form board
1×Alternatively, ESP32 S3 Uno-form board
1×Cáp USB Type-C
1×Nút Nhấn
1×breadboard
1×Dây Jumper
1×(Khuyến nghị) Screw Terminal Expansion Board for ESP32
1×(Khuyến nghị) Breakout Expansion Board for ESP32
1×(Khuyến nghị) Power Splitter for ESP32

Or you can buy the following kits:

1×DIYables ESP32 Starter Kit (ESP32 included)
1×DIYables Sensor Kit (30 sensors/displays)
1×DIYables Sensor Kit (18 sensors/displays)

GPIO Interrupt là gì?

GPIO interrupt là một tín hiệu khiến bộ xử lý dừng việc thực thi hiện tại và nhảy đến một đoạn code cụ thể được gọi là interrupt service routine (ISR). Điều này cho phép ESP32 xử lý các tác vụ có độ ưu tiên cao ngay lập tức, mà không cần phải liên tục kiểm tra trạng thái các chân GPIO.

Interrupt trong ESP32

ESP32 hỗ trợ nhiều loại GPIO interrupt khác nhau:

  • Rising Edge (Sườn lên): Được kích hoạt khi chân GPIO chuyển từ LOW sang HIGH.
  • Falling Edge (Sườn xuống): Được kích hoạt khi chân GPIO chuyển từ HIGH sang LOW.
  • Both Edge (Cả hai sườn): Được kích hoạt khi có bất kỳ sự thay đổi trạng thái nào, từ LOW sang HIGH hoặc HIGH sang LOW.
  • Level Low (Mức thấp): Được kích hoạt khi chân GPIO ở trạng thái LOW.
  • Level High (Mức cao): Được kích hoạt khi chân GPIO ở trạng thái HIGH.

Cách cấu hình GPIO Interrupt trên ESP32

Để cấu hình GPIO interrupt trên ESP32, bạn cần thực hiện các bước sau:

Khởi tạo GPIO: Đặt chế độ chân GPIO là input hoặc output theo yêu cầu. Ví dụ:

pinMode(GPIO_Pin, INPUT_PULLUP);

Gắn Interrupt: Sử dụng hàm attachInterrupt() để liên kết chân GPIO với ISR.

attachInterrupt(GPIO_Pin, ISR_function, mode);

Hàm này nhận ba tham số:

  • GPIO_Pin: Chỉ định chân GPIO được sử dụng làm chân interrupt, cho biết chân nào ESP32 sẽ theo dõi.
  • ISR_function: Tên của hàm sẽ được gọi mỗi khi interrupt xảy ra.
  • mode: Xác định điều kiện kích hoạt interrupt. Có năm hằng số được định nghĩa sẵn có thể sử dụng:
    • RISING: Kích hoạt khi chân chuyển từ LOW sang HIGH (trên Rising Edge).
    • FALLING: Kích hoạt khi chân chuyển từ HIGH sang LOW (trên Falling Edge).
    • CHANGE: Kích hoạt khi có bất kỳ thay đổi nào trong trạng thái chân (trên Both Edge).
    • HIGH: Kích hoạt khi chân ở mức HIGH (trên Level High).
    • LOW: Kích hoạt khi chân ở mức LOW (trên Level Low).

    Định nghĩa hàm ISR: Viết interrupt service routine sẽ thực thi khi interrupt được kích hoạt.

    Interrupt Service Routine (ISR) là một hàm được gọi mỗi khi interrupt xảy ra trên chân GPIO. Cú pháp của nó như sau:

    void IRAM_ATTR ISR_function() { Statements; }

    Hãy cùng tìm hiểu một ví dụ thực tế về việc sử dụng interrupt với chân GPIO của ESP32 được kết nối với một nút nhấn.

Sơ Đồ Kết Nối

ESP32 nút nhấn sơ đồ đấu dây

This image is created using Fritzing. Click to enlarge image

Nếu bạn chưa rõ cách cấp nguồn cho ESP32 và các linh kiện khác, xem: Cách Cung Cấp Nguồn Điện Cho ESP32.

Code ESP32 Interrupt

#define BUTTON_PIN 21 // The ESP32 pin GPIO21 connected to the button void IRAM_ATTR handleButtonPress(); void setup() { Serial.begin(9600); // Initialize the GPIO pin as an input pinMode(BUTTON_PIN, INPUT_PULLUP); // Attach interrupt to the GPIO pin attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), handleButtonPress, FALLING); } void loop() { // Main code here } // Interrupt Service Routine (ISR) void IRAM_ATTR handleButtonPress() { Serial.println("Button pressed!"); }

Trong ví dụ này:

  • BUTTON_PIN được định nghĩa là GPIO21.
  • Hàm pinMode() đặt chân GPIO làm input với điện trở pull-up nội bộ.
  • Hàm attachInterrupt() gắn ISR handleButtonPress vào BUTTON_PIN, được cấu hình để kích hoạt trên sườn xuống.
  • Hàm handleButtonPress là ISR thực thi khi nút nhấn được bấm.

Code trên minh họa interrupt code trông như thế nào, nhưng có thể không hoạt động trong thực tế vì nó sử dụng hàm Serial.println(), hàm này mất thời gian xử lý lâu hơn so với thời gian được phép trong interrupt service routine.

Để kiểm tra cách interrupt hoạt động, hãy xem ví dụ code thực tế dưới đây:

#define BUTTON_PIN 21 // The ESP32 pin GPIO21 connected to the button volatile bool buttonPressed = false; // use volatile for variable that is accessed from inside and outside ISR void IRAM_ATTR handleButtonPress(); void setup() { Serial.begin(9600); // Initialize the GPIO pin as an input pinMode(BUTTON_PIN, INPUT_PULLUP); // Attach interrupt to the GPIO pin attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), handleButtonPress, FALLING); } void loop() { // Main code here if (buttonPressed) { Serial.println("Button pressed!"); buttonPressed = false; // Reset the flag } // Other code here } // Interrupt Service Routine (ISR) void IRAM_ATTR handleButtonPress() { // Serial.println("Button pressed!"); // do NOT use function that takes long time to execute buttonPressed = true; }

Các Bước Thực Hiện

  • Nếu đây là lần đầu tiên bạn sử dụng ESP32, hãy xem ESP32 - Cài Đặt Phần Mềm.
  • Thực hiện kết nối theo hình ảnh trên.
  • Kết nối board ESP32 với PC qua cáp micro USB
  • Mở Arduino IDE trên PC của bạn.
  • Chọn đúng board ESP32 (ví dụ: ESP32 Dev Module) và COM port.
  • Copy code trên và mở bằng Arduino IDE
  • Nhấp nút Upload trên Arduino IDE để upload code lên ESP32
  • Nhấn nút nhiều lần
  • Kiểm tra kết quả trên Serial Monitor
COM6
Send
Button pressed! Button pressed! Button pressed! Button pressed!
Autoscroll Show timestamp
Clear output
9600 baud  
Newline  

Bạn có thể nhận thấy rằng một lần nhấn nút duy nhất dẫn đến nhiều sự kiện nhấn được hiển thị trên Serial Monitor. Đây không phải là vấn đề của interrupt mà là vấn đề với chính nút nhấn. Để tìm hiểu cách giải quyết vấn đề này, hãy tham khảo hướng dẫn ESP32 - Nút Nhấn - Debounce.

Bạn có thể xem một ví dụ khác sử dụng interrupt trong hướng dẫn ESP32 - Rotary Encoder.

Những Lưu Ý Quan Trọng

  • Không có Tham Số hoặc Giá Trị Trả Về: Hàm ISR không thể có bất kỳ tham số nào và không nên trả về gì.
  • Thời Gian Thực Thi ISR: Giữ cho code ISR ngắn gọn và hiệu quả nhất có thể. ISR dài có thể khiến hệ thống bỏ lỡ các interrupt khác hoặc làm giảm hiệu suất tổng thể.
  • Đồng Thời: Chú ý đến các tài nguyên được chia sẻ được truy cập trong ISR. Sử dụng các phép toán atomic hoặc vô hiệu hóa interrupt nếu cần thiết để tránh race condition. Cụ thể, sử dụng từ khóa volatile cho các biến được truy cập cả bên trong và bên ngoài hàm ISR.
  • IRAM_ATTR: Đặt code ISR trong IRAM bằng cách sử dụng thuộc tính IRAM_ATTR để đảm bảo nó chạy nhanh mà không cần lấy từ flash memory.

Video Tutorial

Việc sản xuất video tốn rất nhiều thời gian. Nếu video hướng dẫn hữu ích cho việc học của bạn, hãy đăng ký kênh YouTube để ủng hộ. Nếu nhu cầu đủ cao, chúng tôi sẽ cố gắng làm thêm nhiều video.

Bài hướng dẫn liên quan