Skip to content

Công nghệ 9 giây

“Website hướng dẫn, thử nghiệm và giải thích công nghệ theo cách dễ hiểu cho mọi người.”

Menu
  • Home
  • Công nghệ
  • STM32
  • ESP32
  • Altium Desinger
  • Kiến thức điện máy
Menu

🟢 BÀI 9 – struct nâng cao: Struct + Con trỏ + Hàm

Posted on August 20, 2026August 23, 2026 by congnghe9s

Được. Chúng ta tiếp tục Bài 9 trong lộ trình học C để lập trình STM32.

🟢 BÀI 9 – struct nâng cao: Struct + Con trỏ + Hàm

Ở Bài 7, bạn đã học struct.
Ở Bài 8, bạn học hàm.

Bây giờ ta ghép chúng lại. Đây là kiến thức cực kỳ quan trọng khi chuyển sang lập trình STM32 thực tế, vì trong chương trình STM32 bạn sẽ gặp rất nhiều kiểu dữ liệu dạng cấu trúc.


1. Ôn lại struct

Ví dụ ta tạo thông tin của một LED:

struct LED
{
    int pin;
    int state;
};

Tạo biến:

struct LED led1;

Gán dữ liệu:

led1.pin = 13;
led1.state = 1;

Truy cập:

printf("%d", led1.pin);
printf("%d", led1.state);

Ta có:

led1
 ├── pin   = 13
 └── state = 1

2. Struct truyền vào hàm

Đây là phần rất quan trọng.

Ta có:

struct LED
{
    int pin;
    int state;
};

Viết hàm:

void LED_On(struct LED led)
{
    led.state = 1;
}

Sau đó:

struct LED led1;

led1.pin = 13;
led1.state = 0;

LED_On(led1);

Bạn có thể nghĩ:

“Sau khi gọi LED_On(led1), led1.state sẽ thành 1?”

Không!

Bởi vì:

LED_On(led1);

đang truyền bản sao của led1 vào hàm.

Hình dung:

led1 gốc
   |
   | copy
   ↓
led trong hàm

Hàm thay đổi bản copy, không thay đổi biến gốc.


3. Muốn hàm thay đổi Struct gốc → dùng con trỏ

Đây chính là lý do con trỏ + struct rất quan trọng.

Ta viết:

void LED_On(struct LED *led)
{
    led->state = 1;
}

Gọi:

LED_On(&led1);

Ở đây:

&led1

nghĩa là:

địa chỉ của led1.

Hàm nhận:

struct LED *led

nghĩa là:

led là con trỏ trỏ tới một biến struct LED.


4. Tại sao lại có ->?

Đây là cú pháp bạn cần nhớ:

Nếu có biến struct bình thường:

led1.state

Nếu có con trỏ tới struct:

led->state

Hai cách này tương đương:

led->state

và:

(*led).state

Ví dụ:

void LED_On(struct LED *led)
{
    (*led).state = 1;
}

hoàn toàn tương đương:

void LED_On(struct LED *led)
{
    led->state = 1;
}

Trong thực tế người ta thường dùng:

led->state

vì dễ đọc hơn.


5. Ví dụ hoàn chỉnh

#include <stdio.h>

struct LED
{
    int pin;
    int state;
};

void LED_On(struct LED *led)
{
    led->state = 1;
}

void LED_Off(struct LED *led)
{
    led->state = 0;
}

int main()
{
    struct LED led1;

    led1.pin = 13;
    led1.state = 0;

    printf("Before: %d\n", led1.state);

    LED_On(&led1);

    printf("After ON: %d\n", led1.state);

    LED_Off(&led1);

    printf("After OFF: %d\n", led1.state);

    return 0;
}

Kết quả:

Before: 0
After ON: 1
After OFF: 0

6. Đây chính là tư duy lập trình STM32

Sau này bạn sẽ gặp kiểu code như:

GPIO_Init(&GPIO_InitStruct);

Bạn thấy:

&GPIO_InitStruct

không?

Đó chính là địa chỉ của một struct được truyền vào hàm.

Ví dụ tưởng tượng:

struct GPIO
{
    int pin;
    int mode;
    int speed;
};

void GPIO_Init(struct GPIO *config)
{
    ...
}

Ta tạo:

struct GPIO config;

config.pin = 13;
config.mode = 1;
config.speed = 2;

Sau đó:

GPIO_Init(&config);

Đây chính là mô hình mà các thư viện STM32 sử dụng rất nhiều.


7. Một ví dụ gần với STM32 hơn

Giả sử ta mô tả một chân GPIO:

struct GPIO_Config
{
    int pin;
    int mode;
    int pull;
};

Tạo cấu hình:

struct GPIO_Config led;

led.pin = 13;
led.mode = 1;
led.pull = 0;

Hàm:

void GPIO_Init(struct GPIO_Config *config)
{
    printf("Pin  = %d\n", config->pin);
    printf("Mode = %d\n", config->mode);
    printf("Pull = %d\n", config->pull);
}

Gọi:

GPIO_Init(&led);

8. Một bước quan trọng hơn: typedef struct

Trong C, bạn thường thấy:

typedef struct
{
    int pin;
    int state;
} LED;

Bây giờ không cần viết:

struct LED led1;

mà chỉ cần:

LED led1;

Ví dụ:

typedef struct
{
    int pin;
    int state;
} LED;

Sau đó:

LED led1;
LED led2;
LED led3;

Hàm:

void LED_On(LED *led)
{
    led->state = 1;
}

Gọi:

LED_On(&led1);

Cách này bạn sẽ gặp rất nhiều trong STM32 HAL.


9. Struct có thể chứa nhiều kiểu dữ liệu

Ví dụ một thiết bị:

typedef struct
{
    uint8_t id;
    uint16_t adc;
    uint32_t time;
    float voltage;
    uint8_t state;
} Device;

Tạo:

Device dev1;

Gán:

dev1.id = 1;
dev1.adc = 2048;
dev1.time = 1000;
dev1.voltage = 2.5;
dev1.state = 1;

Bạn đang gom rất nhiều thông tin liên quan vào một đối tượng dữ liệu.

Đây là tư duy cực kỳ hữu ích trong embedded.


10. Struct chứa con trỏ

Đây là phần nâng cao hơn một chút.

Ví dụ:

typedef struct
{
    int pin;
    int *value;
} Sensor;

Ta có:

int temperature = 30;

Sensor sensor1;

sensor1.pin = 5;
sensor1.value = &temperature;

Sau đó:

printf("%d", *(sensor1.value));

Kết quả:

30

Sơ đồ:

sensor1
 ├── pin
 │    └── 5
 │
 └── value
      │
      ↓
   temperature
      │
      └── 30

Đây là lúc bạn bắt đầu thấy struct + pointer mạnh như thế nào.


11. Vì sao kiến thức này quan trọng với STM32?

Sau này bạn sẽ gặp các cấu trúc kiểu:

GPIO_InitTypeDef
UART_HandleTypeDef
TIM_HandleTypeDef
ADC_HandleTypeDef
I2C_HandleTypeDef

Ví dụ:

UART_HandleTypeDef huart1;

Đây là một struct.

Rồi truyền địa chỉ:

HAL_UART_Transmit(&huart1, ...);

Ta có:

UART_HandleTypeDef huart1
          │
          │ &
          ↓
     &huart1
          │
          ↓
   hàm HAL_UART_Transmit()

Vì vậy nếu bạn hiểu chắc:

struct
   ↓
pointer
   ↓
struct pointer
   ↓
function
   ↓
struct + pointer + function

thì khi bước vào STM32 HAL bạn sẽ đỡ bị choáng rất nhiều.


🎯 12. Bài tập Bài 9

Bạn hãy tự viết chương trình sau.

Tạo:

typedef struct
{
    int pin;
    int state;
    int brightness;
} LED;

Tạo 2 LED:

LED led1;
LED led2;

Yêu cầu:

LED1

pin        = 13
state      = 0
brightness = 50

LED2

pin        = 8
state      = 1
brightness = 100

Viết 2 hàm:

void LED_On(LED *led);

và:

void LED_Off(LED *led);

Trong main():

  1. Khởi tạo LED1, LED2.
  2. In trạng thái ban đầu.
  3. Gọi LED_On(&led1).
  4. Gọi LED_Off(&led2).
  5. In trạng thái sau khi thay đổi.

🧠 Sau Bài 9 bạn cần nắm chắc 6 thứ

1. struct
2. typedef struct
3. struct truyền vào hàm
4. con trỏ tới struct
5. toán tử ->
6. truyền địa chỉ struct bằng &

Đặc biệt hãy thuộc cặp này:

LED led1;

LED_On(&led1);

và:

void LED_On(LED *led)
{
    led->state = 1;
}

Đây là một trong những mẫu cú pháp bạn sẽ gặp liên tục khi lập trình STM32.

Bài tiếp theo nên là Bài 10 – enum, typedef, const, static và volatile: 4 từ khóa cực kỳ quan trọng trong C nhúng.

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recent Posts

  • Bạn có thể hướng dẫn tôi quy trình sửa chữa một mainboard laptop cũng như mainboard của máy tính để bàn không?
  • Có những mức nguồn DC nào trên một bo mạch mainboard laptop?Kỹ thuật đốt dòng để kiểm tra nguồn laptop được thực hiện như thế nào?
  • bài tiếp theo hợp lý là: BÀI 63 – SENSOR FUSION THỰC CHIẾN: ENCODER + IMU MPU6050 + EKF + ODOMETRY X,Y,θ TRÊN STM32F103
  • BÀI 62 – EKF (EXTENDED KALMAN FILTER) CHO ROBOT 2 BÁNH: FUSION ENCODER + IMU + ƯỚC LƯỢNG X, Y, θ, V, ω
  • BÀI 61 – KALMAN FILTER CHO ENCODER + IMU: ƯỚC LƯỢNG TỐC ĐỘ, GÓC θ VÀ SENSOR FUSION

Recent Comments

No comments to show.

Archives

  • September 2026
  • August 2026
  • July 2026
  • June 2026
  • May 2026
  • February 2026

Categories

  • Altium Desinger
  • Công nghệ
  • ESP32
  • Khác
  • Kiến thức điện máy
  • STM32
Live 3D Globes Visitor
©2026 Công nghệ 9 giây | Design: Newspaperly WordPress Theme