Lập trình chức năng GPIO INPUT trên vi điều khiển STM32F103C8T6

General-purpose Input/Output (GPIO) rất phổ biến, là một chức năng ngoại vi cơ bản của các vi điều khiển, bao gồm các chân đầu vào và chân đầu ra, có thể được điều khiển bởi người dùng. Nó tương tự với các dòng vi điều khiển  8 bit như AVR và PIC. Tuy nhiên. những dòng vi điều khiển 8bit, chỉ có 8 chân IO trên 1 port thì ở các vi điều khiển 32bit, có đến 16 chân IO trên 1 port. Cụ thể đối với chip STM32F103C8Tx gồm có 3 Port chính đó là GPIOA, GPIOB, GPIOC. Trong đó, GPIOA, GPIOB trên kit thì có đủ 16 chân GPIO, GPIOC 3 chân và GPIOD có 2 chân. 

Cấu trúc 1 chân GPIO của Vi điều khiển STM32F103C8T6: 

Có 2 khối điều khiển khác nhau (khung hình nét đứt):

– Input

– Output và các điều khiển đầu ra khác

Chức năng của GPIO bao gồm:

1/ GPIO Input:

Sơ lược qua cấu trúc phần cứng và khối điều khiển input:

2/ Các thanh ghi dữ liệu:

Input Data Register (IDR): Nhận mức tín hiệu tại chân IO, thông qua việc đọc thanh ghi GPIOx_IDR thì chúng ta có thể đọc được trạng thái mức “1” hay mức “0” của chân đó tại Port tương ứng.

Khi cấu hình các chân ở Port tương ứng có chức năng Input thì các thanh ghi dữ liệu Output (Output data register) sẽ tự động bị khóa lại vì chân đó đã được khai báo là Input. Lúc này, chúng ta chỉ được phép đọc dữ liệu từ thanh ghi Input Data Register để biết trạng thái của chân tại port đó chứ không được phép ghi.

3/ TTL Schmitt Trigger:

Quá trình đọc sườn tín hiệu Input thường bị ảnh hưởng bởi 2 hiện tượng:

– Nhiễu

– Tốc độ chuyển đổi tín hiệu chậm

Khi cấu hình chân ở Port tương ứng là Input thì khối TTL Schmitt Trigger sẽ được nối với chân vật lý. Cơ chế của mạch tích hợp TTL Schemitt Trigger này mục đích dùng để khi nó tiếp nhận điện áp Vin, nó giúp chúng ta phân biệt được tín hiệu bằng ngưỡng  VT  đó để quyết định ngõ ra Vout là cao hay thấp. Với thiết kế TTL Schmitt Trigger giúp chúng ta chống nhiễu đầu vào tốt hơn ở bên trong vi điều khiển. Chi tiết về TTL Schmitt Trigger các bạn đọc thêm tại đây.

4/ Điện trở kéo:

Khi cấu hình chân ở Port tương ứng có chức năng Input, thì tại chân đó chúng ta có thể chọn điện trở để định mức điện áp trước tại chân đó là mức “1” hay mức “0”, có thể gọi là điện trở pull up (kéo nguồn) hoặc điện trở pull down (kéo đất). Nếu không cấu hình cho nó kéo nguồn hay kéo đất thì chân IO sẽ ở điện áp thả nổi nằm giữa mức “1” và mức “0” (Input floating).

Điện trở kéo nguồn

 

Điện trở kéo đất

Trong hướng dẫn này, chúng ta sẽ sử dụng CubeMX để sinh code và lập trình trên môi trường KeilC-V5.  Khi sinh code,  chúng ta sẽ làm việc dựa trên lớp thư viện HAL-Hardware Abstraction Layer. Thư viện này được xây dựng dựa trên các thư viện tiêu chuẩn (Std) của STM32, để tiếp cận được nhanh chóng dòng vi điều khiển này thì chúng ta sẽ không đi quá sâu vào thanh ghi GPIOx_IDR(Input data register). Mà sử dụng phần mềm CubeMX để sinh code và sử dụng các hàm GPIO có sẵn trong thư viện HAL.

Lựa chọn chân trên kit STM32F103C8T6:

Quan sát trên kit STM32F103C8T6, hiện tại không có nút nhấn nào sẵn trên board nên mình sẽ sử dụng một nút nhấn ở ngoài cắm vào và chân đọc nút nhấn là chân PA0, các bạn có thể chọn giống mình hoặc đổi chân khác. Ngoài ra ở Port C chân thứ 13, trên kit đã layout sẵn một đèn led, chúng ta sẽ sử dụng đèn led này để thực hành nhấn nút thì led đảo trạng thái.

Cấu hình trên CubeMX:

Bước 1:

  • Mở CubeMX
  • Chọn chip STM32F103C8T6

Bước 2:

Bắt đầu project

Bước 3:

Cài đặt Serial wire để nạp code theo chuẩn SWDIO-SWCLK

Bước 4:

  • Click chuột phải vào chân PC13 
  • Chọn vào ô GPIO_Output

Bước 5:

  • Click chuột phải vào chân PA0 
  • Chọn  ô GPIO_Input

Bước 6:

  • Cấu hình các chân GPIO 
  • Chọn configuration

Bước 7:

  • GPIO output level: “LOW” (Trạng thái ban đầu của led và sẽ được kích khi xuất mức “0” tại chân IO)
  • GPIO mode: “Output push-pull”
  • Maximum output speed: Đối với các dòng vi điều khiển có tốc độ xử lý nhanh từ vài chục MHz trở lên, thì chúng ta phải khai báo tốc độ dao động tại chân đó để đáp ứng với tốc độ xử lý của vi điều khiển. Hiện tại, chúng ta đang sử dụng nguồn dao động nội với tốc độ là 8MHz nên ở đây sẽ chọn “LOW”

Bước 8:

  • GPIO Mode: Input mode
  • GPIO Pull-up/Pull-down: Pull-up

Ở đây mình sẽ kéo trở nguồn, định mức ban đầu cho chân PA0 là mức “1”. Nút nhấn sẽ được nối với GND để khi nhấn nút thì chân PA0 sẽ bị kéo xuống mức “0”, khi nhận thấy PA0 ở mức “0” thì ta sẽ đảo trạng thái led PC13.

Bước 9:

Setting project và sinh code

  • Đặt tên project và công cụ sử dụng để lập trình

  • Click vào Code Generator sau đó chọn coppy các thư viện cần thiết sau đó thì sinh code và mở project bên keilC lên

Bước 11:

Click vào Function quan sát các hàm sẽ sử dụng trong bài này.

Bước 12:

Ở đây chúng ta sẽ dùng hàm:

  • GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin) để đọc trạng thái của chân tại Port tương ứng. Hàm này sẽ trả về giá trị: 1 hoặc 0 tương ứng với trạng thái của các chân đã cấu hình
  • GPIO_TypeDef *GPIOx: Tham số này ta sẽ truyền vào Port A của chân nút nhấn là GPIOA
  • uint16_t GPIO_Pin: Tham số này ta sẽ truyền vào chân nút nhấn PA0 là GPIO_PIN_0

Bước 13:

Ở trong vòng while(1) chúng ta sẽ kiểm tra liên tục trạng thái của chân PA0, nếu nó ở mức “0” thì thỏa mãn điều kiện if và thực hiện các lệnh trong đó.

Bước 14:

Sử dụng while(HAL_GPIO_ReadPin(GPIOA,  GPIO_PIN_0)==0); để chống nhiễu cho nút nhấn, đợi đến khi chúng ta thả tay ra khỏi nút thì lúc đấy mới đổi trạng thái của led PC13

Phần cứng:

Link source code tại đây

Chúc các bạn thành công!

Nhóm TAPIT ARM R&D