Lập trình STM32F4 Phần 8: Thực hành về GPIO

22 Tháng Năm 2021

Trong các bài trước chúng ta đã tìm hiểu về GPIO của STM32F4, bài này chúng ta cùng thực hiện chương trình nho nhỏ với GPIO nhé

Lập trình STM32F4 Phần 8: Thực hành về GPIO

Giới thiệu  phần cứng

Trong những phần hướng dẫn lập trình hệ thống nhúng với STM32F4 lần này chúng ta sẽ viết chương trình đơn giản điều khiển chân IO của chip STM3F4 trên Discovery Board.

Trước khi bắt đầu, bạn cần biết thông tin về phần cứng chúng ta đang làm việc cùng đúng không nào, hãy tải User Manual của bộ KIT Discovery Board tại đây.

Để bạn không mất thời gian lắp mạch và kết nối phần cứng, ta sẽ thực hiện điều khiển tắt bật pin của STM43F047 và theo dõi sự thay đổi thông qua quan sát các con LED được kết nối sẵn với một số chân của chip.

Trong User Manual vừa mới tải về nhưng ở các tài liệu thuộc version cũ hơn, bạn có thể thấy phần thiết kế Schematic của KIT (nhưng version hiện tại không còn thấy nữa. Trên Board đã có sẵn 4 con LED được kết nối như sau

  • LED màu xanh lục à PD12
  • LED màu cam à PD13
  • LED màu đỏ à PD14
  • LED màu xanh dương à PD15

Với sơ đồ mạch  kết nối như vậy thì khi ta bật chân tín hiệu lên mức 1, LED sẽ sáng và ngược lại.

Lập trình phần mềm

Trong phần 5 - Tao project STM32F4 tren KeilC, tôi đã hướng dẫn bạn tạo 1 workspace cơ bản để làm việc, giờ chúng ta sẽ lập trình lên đó. 

Đầu tiên, bạn xóa hết tất cả code hiện tại có trong chương trình main.c chỉ để lại phần code như sau cho đỡ rối:

#include "main.h"

static __IO uint32_t uwTimingDelay;
static void Delay(__IO uint32_t nTime);

int main(void)
{
  while (1)
  {

  }
}

void Delay(__IO uint32_t nTime)
{ 
  uwTimingDelay = nTime;

  while(uwTimingDelay != 0)
	{
		uwTimingDelay--;
	}
	;
}

Bạn code thêm hàm User_GPIO_Init() với nội dung như sau:

void User_GPIO_Init(void)
{
	GPIO_InitTypeDef  GPIO_InitStructureOutput;
	
	/******************* Port CLock enable/disable ***************/
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
	
	/* Output PIN Config */
	GPIO_InitStructureOutput.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStructureOutput.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructureOutput.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_InitStructureOutput.GPIO_PuPd = GPIO_PuPd_NOPULL;

	/* BLUE_LED_PIN Config */
	GPIO_InitStructureOutput.GPIO_Pin = GPIO_Pin_15;		
	GPIO_Init(GPIOD, &GPIO_InitStructureOutput);

	/* RED_LED_PIN Config */
	GPIO_InitStructureOutput.GPIO_Pin = GPIO_Pin_14;
	GPIO_Init(GPIOD, &GPIO_InitStructureOutput);
    /* ORANGE_LED_PIN Config */   
	GPIO_InitStructureOutput.GPIO_Pin = GPIO_Pin_13;
	GPIO_Init(GPIOD, &GPIO_InitStructureOutput);

	/* GREEN_LED_PIN Config */   
	GPIO_InitStructureOutput.GPIO_Pin = GPIO_Pin_12;
	GPIO_Init(GPIOD, &GPIO_InitStructureOutput);
}

Giải thích đoạn chương trình User_GPIO_Init()

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

Dòng lệnh này có nghĩa là bật clock của khối GPIOD. Bạn thấy các chân LED chúng ta định dùng đều nằm trên port D nên ta chỉ cần bật clock cho khối này. Nếu bạn quên bước này thì chắc chắn chức năng bạn định lập trình sẽ không chạy. Sau này khi bạn lập trình ngoại vi khác chẳng hạn thì bạn đều phải bật clock khối đó lên chip mới có thể cấp xung nhịp hoạt động cho khối đó hoạt động

GPIO_InitStructureOutput.GPIO_Mode = GPIO_Mode_OUT;

Dòng này chọn mode output cho chân GPIO

GPIO_InitStructureOutput.GPIO_OType = GPIO_OType_PP;

Dòng này chọn chế độ pushpull cho chân GPIO, chế độ này hay được sử dụng để điều khiển GPIO nhất. Còn một mode khác đó là Open drain mode này sẽ mắc một cặp Fet thuận nghịch trước đầu ra của chip, bạn có thể xem lại phần lý thuyết GPIO để hiểu rõ

GPIO_InitStructureOutput.GPIO_Speed = GPIO_Speed_100MHz;

Chọn tốc độ đầu ra của chân out, bạn cứ chọn tốc độ cao nhất, phân này ta không cần quá quan tâm đến tốc độ chân IO, tuy nhiên đối với một số chuẩn giao tiếp lại cần chân IO có thể hoạt động ở tốc độ cao phù hợp

GPIO_InitStructureOutput.GPIO_PuPd = GPIO_PuPd_NOPULL;

Dòng 32: chế độ đầu ra nopull có nghĩa là không có điện trở nội kéo lên mức cao và mức thấp. Trên thực tế ở mode output thì điện trở nội không có ý nghĩa gì cả.

GPIO_InitStructureOutput.GPIO_Pin = GPIO_Pin_15;

Do phần cứng LED kết nối với chân PD15 nên tôi khai cáo chân tôi muốn config là GPIO_Pin_15, tương tự với các chân PD14, 13, 12. Bạn cũng có thể cấu hinh nhiều chân 1 lúc sử dụng dấu “|”, hoặc nếu muốn sử dụng tất cả các chân cùng lúc bạn có thể dùng GPIO_Pin_All. Tuy nhiên thì bạn sử dụng chân nào thì khai báo chân đó thôi, không nên khai báo tràn lan

GPIO_Init(GPIOD, &GPIO_InitStructureOutput);

Hàm GPIO_Init() được truyền vào 2 đối số là GPIOD mục đích là cấu hình cho port D và GPIO_InitStructureOutput là các tham số cấu hình chúng ta đã chọn ở các dòng code trước

Bây giờ nội dung hàm main() sẽ có dạng như sau:

int main(void)
{
	User_GPIO_Init();
  while (1)
  {
		GPIO_ToggleBits(GPIOD, GPIO_Pin_15);
		Delay(10000000);
  }
}

Giải thích các câu lệnh trong hàm main()

User_GPIO_Init();

Gọi hàm User_GPIO_Init() để cấu hình cho các chân GPIO

GPIO_ToggleBits(GPIOD, GPIO_Pin_15);

Hàm GPIO_ToggleBits() được hỗ trợ từ thư viện STD của hãng ST, tác dụng là đảo trạng thái của bit (ở đây 1 bit ứng với giá trị ngõ ra của 1 chân IO)

Delay(10000000);

Đây là 1 hàm delay cở bản, việc của nó là đếm hết một con số cố định mà không làm việc gì khác. Thực ra hàm delay này không hiệu quả nhưng đối với bài này chúng ta tạm dùng để tạo ra 1 khoảng thời gian trễ. 

Trong vòng lặp while(1) được lặp lại liên tục, chân PD15 sẽ được liên tục đảo trạng thái 0 sang 1 và 1 sang 0. Chúng ta sẽ thấy LED màu xanh dương nhấp nháy.

Tương tự với các chân khác và các LED màu khác bạn có thể thử thay thế GPIO_Pin_15 bằng chân mong muốn. Hoặc bạn có thể dùng các hàm khác được hỗ trợ như GPIO_SetBits() hay GPIO_ResetBits() chẳng hạn để biết tác dụng của chúng. Kết hợp các lệnh lại để tạo ra các animation, thay đổi màu LED qua lại chẳng hạn. Chúc bạn thành công lập trình cho GPIO output của STM32F4

Tạm Kết

Trong bài này mình đã giới thiệu về 1 chương trình nhỏ để bajnc có thể điều khiển GPIO, người việc điều khiển LED thì GPIO còn được ứng dụng trong nhiều mục đích khác nhau như điều khiển relay, đọc trạng thái nút, .. chúng ta sẽ lần lượt đi tìm hiểu trong các bài tiếp theo. Chúc bạn đọc vui vẻ.

Bình luận