Skip to content

12 Bật Đèn Bằng Nút Nhấn

Trước tiên, ta cần thêm một bước chuẩn bị: chèn thư viện UART từ thư mục uart đã tạo khi khởi tạo project ban đầu.

Quy Trình Cấu Hình

Khi sử dụng GPIO ở chế độ đầu vào, ta cần thực hiện các bước cơ bản sau:

  • Bật clock cho cổng GPIO
  • Cấu hình chế độ hoạt động cho chân GPIO

Trên bo mạch, nút nhấn KEY được kết nối với chân PA0 của vi điều khiển, vì vậy cần cấu hình trạng thái cho chân PA0.

Bật Clock Cho GPIO

Do nút được nối vào PA0, nên cần bật clock cho GPIOA:

c
/* Bật clock cho GPIOA */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

Cấu Hình Chế Độ Cho GPIO

Từ chương trước, ta biết: để đọc trạng thái nhấn của nút thì chân PA0 phải cấu hình ở chế độ input. Mặc định khi nút không nhấn, mức điện áp là LOW (0V); khi nhấn thì lên HIGH (3.3V).

Trên bo mạch đã có điện trở kéo xuống (pull-down), nên trong code ta có thể cấu hình là GPIO_PuPd_DOWN hoặc để mặc định.

Cấu hình PA0 làm đầu vào, với chế độ kéo xuống:

c
GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_Init(GPIOA, &GPIO_InitStructure);

Đọc Trạng Thái Nút Nhấn

Sau khi cấu hình GPIO xong, ta có thể đọc trạng thái chân PA0 để xác định nút có được nhấn hay không.

Trong thư viện stm32f4xx_gpio.h, hàm đọc mức điện áp là:

c
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

Ví dụ đọc mức của chân PA0:

c
GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0);

Nếu giá trị trả về là 1PA0 ở mức cao → nút đang được nhấn. Nếu là 0 → không nhấn.

Cấu trúc kiểm tra nhấn nút:

c
if (SET == GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0))
{
    // Nút đang được nhấn
}

Như đã đề cập trước đó, nút nhấn cơ học khi được nhấn sẽ xảy ra hiện tượng "rung" (chattering) — tức tiếp điểm không ổn định trong một khoảng thời gian ngắn. Có hai cách xử lý:

  • Chống rung bằng phần cứng
  • Chống rung bằng phần mềm

Trên bo mạch phát triển đã có một phần xử lý chống rung bằng phần cứng đơn giản, nhưng giải pháp phần cứng chỉ giúp giảm thiểu, không thể loại bỏ hoàn toàn hiện tượng rung. Vì vậy, trong các ứng dụng thực tế, vẫn cần kết hợp thêm chống rung bằng phần mềm.

c
void key_scan(void)
{
    if (SET == GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0))
    {
        /* Delay chống rung */
        delay_ms(20);

        if (flag)
        {
            GPIO_SetBits(GPIOB, GPIO_Pin_2);  // Bật LED
            flag = 0;
        }
        else
        {
            GPIO_ResetBits(GPIOB, GPIO_Pin_2); // Tắt LED
            flag = 1;
        }

        printf("Key Press!!\r\n");

        // Đợi nút được nhả ra
        while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == SET) {}

        /* Delay chống rung */
        delay_ms(20);
        printf("Key Release!!\r\n");
    }
}

Chức năng đạt được ở đoạn mã trên là:mỗi lần nhấn nút, đèn LED sẽ bật; nhấn thêm lần nữa, đèn sẽ tắt. Mỗi lần nhấn và nhả nút, UART sẽ in ra "Key Press!!""Key Release!!" tương ứng.

Hiện tượng thí nghiệm

Mã nguồn của chương này nằm tại:

https://github.com/leybme/stm32f407_resource/tree/main/C03%20Code/Code%20Sample/006LED%20Control%20with%20Button%20Press

Sau khi nạp chương trình vào vi điều khiển, mỗi lần nhấn nút: đèn LED ở giữa sẽ bật; nhấn thêm lần nữa: đèn sẽ tắt — cứ lặp lại như vậy. Mỗi lần nhấn nút sẽ in "press!", và khi thả nút sẽ in "release!" qua UART, như hình minh họa bên dưới.

img