GPIO Là Gì? Tổng Quan Về Chức Năng, Thanh Ghi Và Ứng Dụng

GPIO (General Purpose Input/Output) là một khái niệm quan trọng trong lĩnh vực hệ thống nhúng. Bài viết này sẽ đi sâu vào các khía cạnh khác nhau liên quan đến GPIO, giúp bạn nắm vững kiến thức từ cơ bản đến nâng cao.

GPIO Là Gì?

GPIO là một chân tín hiệu kỹ thuật số trên vi mạch, có khả năng hoạt động như đầu vào hoặc đầu ra, tùy thuộc vào cấu hình phần mềm. Về cơ bản, GPIO là một chân linh hoạt có thể được cấu hình để đọc tín hiệu từ thế giới bên ngoài (đầu vào) hoặc điều khiển các thiết bị bên ngoài (đầu ra). GPIO đóng vai trò là giao diện tiêu chuẩn giúp vi điều khiển giao tiếp với các thành phần và hệ thống khác.

Ví dụ, GPIO có thể được sử dụng để:

  • Đọc giá trị từ cảm biến analog hoặc kỹ thuật số.
  • Điều khiển đèn LED.
  • Điều khiển xung clock cho giao tiếp I2C.

Bản Đồ Bộ Nhớ Của Ngoại Vi GPIO

Vi điều khiển hiện đại sử dụng kỹ thuật ánh xạ bộ nhớ (memory mapping) để gán địa chỉ cho tất cả các thiết bị ngoại vi trong một không gian bộ nhớ thống nhất. Ví dụ, trong bộ điều khiển STM32F446RE (dựa trên ARM Cortex M4), một vùng bộ nhớ cụ thể được dành riêng cho các thiết bị ngoại vi.

Sơ đồ vùng nhớ ngoại vi trên STM32F446RE.

Địa chỉ bộ nhớ từ 0x40000000 đến 0x60000000 được các nhà sản xuất vi điều khiển sử dụng để ánh xạ các thiết bị ngoại vi khác nhau. Vùng này được chia thành các vùng nhỏ hơn, mỗi vùng tương ứng với một thiết bị ngoại vi cụ thể.

Để lập trình, bạn cần xác định địa chỉ mà một thiết bị ngoại vi được ánh xạ trong dải địa chỉ này. Thông tin này thường được cung cấp trong datasheet của vi điều khiển. Trong trường hợp GPIO, dải địa chỉ thường là 0x40020000 đến 0x40021FFF.

Ví dụ, ngoại vi GPIO được chia thành GPIOA, GPIOB, GPIOC,… và mỗi cổng có thể chứa tối đa 16 chân. GPIOA được ánh xạ từ địa chỉ 0x40020000 đến 0x400203FF và quản lý tất cả các chân kết nối với PORT-A.

Vi xử lý ARM Cortex M-4 có bus dữ liệu và bus địa chỉ rộng 32 bit, cùng với tập thanh ghi 32 bit. Điều này có nghĩa là mỗi từ (word) có kích thước 4 byte. Do đó, mỗi thanh ghi của ngoại vi GPIO cũng có độ dài 4 byte.

Các Thanh Ghi GPIO

Các GPIO trong vi điều khiển được nhóm thành các cổng (PORT), ví dụ PORT A, PORT B, PORT C,…

Mỗi cổng trong STM32F446RE bao gồm 16 chân. Để điều khiển hành vi của một chân cụ thể, bạn cần thay đổi nội dung của các thanh ghi liên quan.

Các thanh ghi chính để điều khiển GPIO trong STM32F446RE bao gồm:

  • Thanh ghi chế độ GPIO (GPIO Mode Register)
  • Thanh ghi kiểu đầu ra GPIO (GPIO Output Type Register)
  • Thanh ghi tốc độ GPIO (GPIO Speed Register)
  • Thanh ghi kéo lên/kéo xuống GPIO (GPIO Pull-up/Pull-down Register)
  • Thanh ghi dữ liệu đầu vào GPIO (GPIO Input Data Register)
  • Thanh ghi dữ liệu đầu ra GPIO (GPIO Output Data Register)
  • Thanh ghi set/reset bit GPIO (GPIO Bit Set/Reset Register)
  • Thanh ghi khóa cấu hình GPIO (GPIO Configuration Lock Register)
  • Thanh ghi chức năng thay thế GPIO (GPIO Alternate Function Register)

Hiểu rõ chức năng của từng thanh ghi này là rất quan trọng để bạn có thể kiểm soát chân GPIO theo yêu cầu ứng dụng.

Chi Tiết Về Các Thanh Ghi GPIO

  • Thanh ghi chế độ GPIO (GPIO Mode Register – MODER):

    • Được sử dụng để chọn chế độ hoạt động của chân.
    • Các chế độ bao gồm:
      • Đầu vào (Input): Chân được cấu hình để đọc dữ liệu từ bên ngoài, ví dụ từ cảm biến. Mỗi chân có một bộ đệm đầu vào tương ứng để đọc dữ liệu.
      • Đầu ra đa năng (General Purpose Output): Chân được cấu hình để ghi giá trị logic (cao/thấp) ra bên ngoài, ví dụ để điều khiển đèn LED. Mỗi chân có một bộ đệm đầu ra tương ứng để ghi dữ liệu.
      • Chức năng thay thế (Alternate Function): Chân được gán cho một thiết bị ngoại vi khác, ví dụ UART, SPI, I2C.
      • Analog: Chân được gán cho các thiết bị ngoại vi ADC (Analog to Digital Converter) hoặc DAC (Digital to Analog Converter).

    Ví dụ, để sử dụng giao tiếp I2C, bạn cần hai chân SDA và SCL. Bạn có thể chọn các chân cụ thể được nhà cung cấp vi điều khiển cung cấp, và cấu hình chúng ở chế độ chức năng thay thế.

    Bảng chức năng thay thế cho các chân GPIO.

  • Thanh ghi kiểu đầu ra GPIO (GPIO Output Type Register – OTYPER):

    • Xác định loại đầu ra của chân.
    • Hai loại đầu ra chính:
      • Push-pull: Đầu ra có thể kéo chân lên VCC (logic 1) hoặc xuống GND (logic 0). Đây là cấu hình mặc định.
      • Open-drain: Đầu ra chỉ có thể kéo chân xuống GND (logic 0). Để kéo chân lên VCC, cần sử dụng điện trở kéo lên (pull-up resistor) bên ngoài hoặc bên trong (kích hoạt thông qua thanh ghi GPIO). I2C thường sử dụng cấu hình open-drain cho các chân SDA và SCL.

    Để hiểu rõ hơn, hãy xem xét sơ đồ mạch đơn giản của chân GPIO:

    Sơ đồ đơn giản của một chân GPIO.

    Mỗi chân bao gồm bộ đệm đầu vào và đầu ra, cùng với một dòng enable. Khi dòng enable là 0, bộ đệm đầu ra được kích hoạt và bộ đệm đầu vào bị vô hiệu hóa.

    Bộ đệm đầu ra push-pull bao gồm hai transistor CMOS:

    Cấu hình push-pull.

    Khi ghi 1, chân được kéo lên VCC. Khi ghi 0, chân được kéo xuống GND.

    Khi dòng enable là 1, chân được cấu hình ở chế độ đầu vào, kích hoạt bộ đệm đầu vào:

    Cấu hình đầu vào.

    Trong chế độ open-drain, transistor PMOS phía trên không có mặt:

    Cấu hình open-drain.

    Chân chỉ có thể được kéo xuống mức thấp (GND).

  • Thanh ghi tốc độ GPIO (GPIO Speed Register – OSPEEDR):

    • Xác định tốc độ chuyển mạch của GPIO, tức là tốc độ chân có thể chuyển từ 0V lên VDD và ngược lại.
    • Tốc độ nhanh hơn không có nghĩa là tần số chuyển đổi GPIO cao hơn.
    • Điều chỉnh tốc độ quay (slew rate) của GPIO, ảnh hưởng đến sự phát xạ EMI của bo mạch.

    Đường cong chuyển đổi của tín hiệu GPIO.

  • Thanh ghi kéo lên/kéo xuống GPIO (GPIO Pull-up/Pull-down Register – PUPDR):

    • Cho phép bật/tắt điện trở kéo lên và kéo xuống bên trong của chân.
  • Thanh ghi dữ liệu đầu vào GPIO (GPIO Input Data Register – IDR):

    • Đọc trạng thái logic (cao/thấp) trên chân.
  • Thanh ghi dữ liệu đầu ra GPIO (GPIO Output Data Register – ODR):

    • Thiết lập logic trên chân đầu ra. Ghi 1 để kéo chân lên cao.
  • Thanh ghi set/reset bit GPIO (GPIO Bit Set/Reset Register – BSRR):

    • Cho phép thiết lập và đặt lại từng bit riêng lẻ trong thanh ghi dữ liệu đầu ra GPIO.
    • Cung cấp cách thực hiện xử lý theo từng bit nguyên tử.
  • Thanh ghi khóa cấu hình GPIO (GPIO Configuration Lock Register – LCKR):

    • Khóa cấu hình của chân cho đến lần thiết lập lại tiếp theo. Cần ghi theo một trình tự cụ thể để kích hoạt khóa.
  • Thanh ghi chức năng thay thế GPIO (GPIO Alternate Function Register – AFR):

    • Định cấu hình các chân GPIO để sử dụng các chức năng thay thế (ví dụ, UART, SPI, I2C).
    • Mỗi chân I/O có một bộ ghép kênh với 16 đầu vào chức năng thay thế (AF0 đến AF15).

    Sơ đồ kết nối chức năng thay thế.

Truy Cập Thanh Ghi GPIO Trong Chương Trình

Để truy cập và lập trình các thanh ghi GPIO, bạn cần xác định địa chỉ cơ sở của thiết bị ngoại vi GPIO và hiểu chức năng của các thanh ghi.

Một cách tiếp cận phổ biến là sử dụng cấu trúc C để trừu tượng hóa ánh xạ ngoại vi:

Ví dụ cấu trúc C định nghĩa thanh ghi GPIO.

Bằng cách trỏ cấu trúc GPIO_TypeDef đến địa chỉ cơ sở của thiết bị ngoại vi GPIOA (ví dụ, 0x40020000), bạn có thể truy cập các thanh ghi thông qua con trỏ cấu trúc. Ví dụ, GPIOA->MODER sẽ truy cập thanh ghi chế độ của GPIOA.

Trạng Thái GPIO Sau Khi Khởi Động Lại

Ngay sau khi khởi động lại, hầu hết các chân GPIO I/O được cấu hình ở chế độ nổi đầu vào. Tuy nhiên, các chân dành riêng cho mạch debug (ví dụ, JTAG/SWD) được cấu hình ở chế độ chức năng thay thế để mạch debug có thể hoạt động ngay lập tức.

Kết Luận

GPIO là một thành phần cơ bản trong hệ thống nhúng, cho phép vi điều khiển tương tác với thế giới bên ngoài. Việc hiểu rõ các khái niệm liên quan đến GPIO, bao gồm cấu trúc, thanh ghi và cách lập trình, là rất quan trọng đối với các kỹ sư phần mềm và phát triển ứng dụng nhúng.