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 5 – CON TRỎ (POINTER) TRONG C VÀ TẠI SAO STM32 RẤT CẦN CON TRỎ

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

Được 👍 Chúng ta tiếp tục BÀI 5 – Lập trình C cho STM32.

Ở các bài trước, ta đã đi từ kiểu dữ liệu → biến → cách dữ liệu nằm trong RAM → toán tử/câu lệnh cơ bản. Bài 5 tôi muốn đưa bạn sang một phần cực kỳ quan trọng khi lập trình STM32:

🔥 BÀI 5 – CON TRỎ (POINTER) TRONG C VÀ TẠI SAO STM32 RẤT CẦN CON TRỎ

Nếu học C để làm STM32 mà chưa hiểu pointer thì sau này bạn sẽ rất khó đọc HAL, thanh ghi GPIO, UART, DMA, cấu trúc dữ liệu…


1. Pointer thực chất là gì?

Hãy tưởng tượng RAM của STM32 giống như một dãy tủ:

Địa chỉ RAM

0x20000000 ──┐
             │
0x20000001 ──┤
             │
0x20000002 ──┤
             │
0x20000003 ──┘

Mỗi ô nhớ có một địa chỉ.

Ví dụ:

int x = 100;

Giả sử STM32 đặt x tại:

0x20000010

Ta có:

Tên biến       Giá trị        Địa chỉ

x              100            0x20000010

2. Toán tử &

Trong C:

&x

có nghĩa:

“Cho tôi địa chỉ của biến x.”

Ví dụ:

int x = 100;

printf("%d", x);

→ 100

Còn:

printf("%p", &x);

→ địa chỉ của x.

Ví dụ:

0x20000010

3. Pointer là gì?

Pointer là một biến dùng để lưu địa chỉ của một biến khác.

Ví dụ:

int x = 100;

int *p;

p = &x;

Bây giờ:

x
│
│ giá trị = 100
│
▼
RAM
0x20000010
      ▲
      │
      │
      p

p không chứa 100.

Nó chứa:

0x20000010

4. Dấu * có hai ý nghĩa

Đây là điểm rất nhiều người mới học C bị nhầm.

Khi khai báo:

int *p;

nghĩa là:

p là pointer tới int.


Khi sử dụng:

*p

nghĩa là:

lấy giá trị tại địa chỉ mà p đang trỏ tới.

Ví dụ:

int x = 100;
int *p = &x;

Ta có:

x   = 100

p   = địa chỉ của x

*p  = 100

5. Ví dụ cực kỳ quan trọng

int x = 100;
int *p = &x;

x = 200;

Khi đó:

x  = 200
*p = 200

Bởi vì p đang trỏ vào x.


Ngược lại:

*p = 500;

thì:

x = 500

Đây chính là sức mạnh của pointer.


6. Hãy nhớ sơ đồ này

              RAM
        ┌───────────────┐
        │               │
0x2000  │      x        │
        │     100       │
        └───────────────┘
             ▲
             │
             │
             │
        ┌────┴─────┐
        │    p     │
        │ 0x2000   │
        └──────────┘

p chứa địa chỉ.

*p lấy giá trị tại địa chỉ đó.


7. Pointer với các kiểu dữ liệu

Không phải pointer nào cũng giống nhau.

Ví dụ:

char *p1;
int  *p2;
float *p3;

Ý nghĩa:

char  *p1 → trỏ tới char
int   *p2 → trỏ tới int
float *p3 → trỏ tới float

Ví dụ:

char a = 10;
char *p = &a;

và:

int b = 1000;
int *q = &b;

8. Tại sao kiểu pointer lại quan trọng?

Vì CPU cần biết bao nhiêu byte dữ liệu cần đọc.

Ví dụ STM32F103:

char

thường:

1 byte

Trong khi:

int

thường:

4 byte

Do đó:

char *p;

khi p++ thì địa chỉ thường tăng:

+1 byte

Còn:

int *p;

khi p++ thì địa chỉ thường tăng:

+4 byte

Đây gọi là pointer arithmetic.


9. Pointer arithmetic

Ví dụ:

int a[3] = {10,20,30};

int *p = a;

Ban đầu:

p → a[0]

Nếu:

p++;

thì:

p → a[1]

Tiếp tục:

p++;

thì:

p → a[2]

Sơ đồ:

a:

┌────┬────┬────┐
│ 10 │ 20 │ 30 │
└────┴────┴────┘
  ▲
  p

p++

┌────┬────┬────┐
│ 10 │ 20 │ 30 │
└────┴────┴────┘
       ▲
       p

p++

┌────┬────┬────┐
│ 10 │ 20 │ 30 │
└────┴────┴────┘
            ▲
            p

10. Pointer và mảng

Đây là một kiến thức cực kỳ quan trọng:

int a[5];

Tên a trong nhiều biểu thức có thể được sử dụng như địa chỉ phần tử đầu tiên:

a

tương đương về mặt địa chỉ với:

&a[0]

Do đó:

int *p = a;

có thể hiểu là:

int *p = &a[0];

11. Một điều rất quan trọng đối với STM32

Sau này bạn sẽ gặp những thứ kiểu:

uint32_t *address;

hoặc:

volatile uint32_t *reg;

Ví dụ một thanh ghi phần cứng nằm tại một địa chỉ cụ thể:

0x4001080C

Ta có thể hình dung:

volatile uint32_t *GPIO_REG =
    (volatile uint32_t *)0x4001080C;

Sau đó:

*GPIO_REG = 0x00000020;

Nghĩa là:

Ghi dữ liệu vào vùng nhớ tại địa chỉ 0x4001080C.

🔥 Đây chính là một trong những cơ chế nền tảng để C điều khiển phần cứng STM32.


12. volatile là gì?

Bạn sẽ gặp nó rất nhiều trong STM32.

Ví dụ:

volatile uint32_t GPIO_REG;

volatile nói với compiler rằng:

Giá trị này có thể thay đổi bởi phần cứng hoặc một cơ chế bên ngoài chương trình; đừng tự ý tối ưu hóa việc đọc/ghi nó.

Ví dụ thanh ghi phần cứng:

volatile uint32_t *REG;

Điều này cực kỳ quan trọng khi làm:

  • GPIO
  • UART
  • Timer
  • ADC
  • Interrupt
  • DMA
  • Peripheral registers

13. Pointer và hàm – cực kỳ quan trọng

Đây là phần bạn cần đặc biệt chú ý.

Giả sử:

void Tang(int x)
{
    x++;
}

Gọi:

int a = 10;

Tang(a);

Sau đó:

a = 10

Tại sao?

Vì hàm nhận bản sao của a.


Nhưng nếu dùng pointer:

void Tang(int *x)
{
    (*x)++;
}

Gọi:

int a = 10;

Tang(&a);

Sau đó:

a = 11

Sơ đồ:

main()

a = 10
│
│ &a
▼
Tang()
x ─────────────► a
                 │
                 ▼
                10
                 │
              (*x)++
                 │
                 ▼
                11

Đây là một ứng dụng pointer bạn sẽ gặp rất thường xuyên trong lập trình STM32.


14. Tại sao HAL của STM32 dùng pointer rất nhiều?

Bạn sẽ thường thấy các hàm dạng:

HAL_UART_Transmit(&huart1, ...);

Hãy chú ý:

&huart1

Đây chính là:

địa chỉ của biến huart1.

HAL nhận địa chỉ đó để có thể làm việc với cấu trúc cấu hình UART tương ứng.

Tương tự:

HAL_GPIO_WritePin(...)

và nhiều API khác cũng sử dụng pointer, cấu trúc và địa chỉ bộ nhớ.


15. Ba ký hiệu bạn phải thuộc

Nếu chỉ chọn 3 thứ quan trọng nhất của bài hôm nay, hãy nhớ:

&

→ lấy địa chỉ.

*

→ lấy giá trị tại địa chỉ.

int *p;

→ khai báo pointer p trỏ tới int.

Ví dụ:

int x = 100;

int *p = &x;

*p = 200;

Kết quả:

x = 200

🧠 BÀI TẬP BÀI 5

Bạn hãy tự trả lời trước, đừng chạy code.

Câu 1

int x = 10;
int *p = &x;

*p = 20;

Giá trị cuối cùng của x là bao nhiêu?


Câu 2

int x = 50;
int *p = &x;

x = 100;

Giá trị của:

*p

là bao nhiêu?


Câu 3

int a[3] = {10,20,30};

int *p = a;

p++;

*p bằng bao nhiêu?


Câu 4 – quan trọng

Giải thích bằng lời của bạn:

int *p = &x;

p, *p, &x lần lượt có ý nghĩa gì?


Câu 5 – STM32

Tại sao trong lập trình STM32 chúng ta phải hiểu pointer trước khi học sâu về:

GPIO → UART → Timer → ADC → Interrupt → DMA → thanh ghi phần cứng?

Bạn trả lời 5 câu này, tôi sẽ chấm và sửa từng câu, sau đó chúng ta sang BÀI 6 – STRUCT, ENUM, UNION: 3 thứ cực kỳ quan trọng để đọc được code STM32/HAL.

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