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 6 – CON TRỎ + MẢNG: HIỂU CÁCH STM32 TRUY CẬP DỮ LIỆU TRONG RAM

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

📘 BÀI 6 – CON TRỎ + MẢNG: HIỂU CÁCH STM32 TRUY CẬP DỮ LIỆU TRONG RAM

Ở Bài 5, chúng ta đã học con trỏ: biến con trỏ không giữ trực tiếp dữ liệu mà giữ địa chỉ của dữ liệu.

Bài 6 sẽ ghép hai thứ lại:

Mảng + con trỏ = nền tảng cực kỳ quan trọng khi lập trình STM32 bằng C.

Đây cũng là bước chuẩn bị để sau này bạn hiểu được buffer UART, ADC, DMA, GPIO register, struct, chuỗi ký tự…


1. Mảng là gì?

Ví dụ:

uint8_t data[5];

Ta có 5 phần tử:

data[0]
data[1]
data[2]
data[3]
data[4]

Giả sử địa chỉ bắt đầu của data là:

0x20000000

Vì uint8_t = 1 byte nên RAM có thể hình dung:

Địa chỉ        Dữ liệu

0x20000000     data[0]
0x20000001     data[1]
0x20000002     data[2]
0x20000003     data[3]
0x20000004     data[4]

2. Điều rất quan trọng: tên mảng gần giống một con trỏ

Xét:

uint8_t data[5];

Khi viết:

data

trong hầu hết các biểu thức, nó biểu diễn địa chỉ phần tử đầu tiên:

&data[0]

Vì vậy:

data == &data[0]

về mặt địa chỉ là tương đương.

Ví dụ:

printf("%p\n", data);
printf("%p\n", &data[0]);

sẽ cho cùng một địa chỉ.


3. data[0] thực chất liên quan đến con trỏ

Ta có:

data[0]

và:

*(data + 0)

là tương đương.

Tương tự:

data[1]

tương đương:

*(data + 1)

và:

data[2]

tương đương:

*(data + 2)

Có thể nhớ:

data[i]  <=>  *(data + i)

Đây là một trong những công thức quan trọng nhất của C.


4. Nhưng tại sao data + 1 lại tăng đúng kích thước kiểu dữ liệu?

Đây là điểm rất quan trọng.

Ví dụ:

uint8_t data[5];

thì:

data + 1

tăng:

1 × sizeof(uint8_t)
= 1 byte

Nhưng:

uint32_t data[5];

thì:

data + 1

tăng:

1 × sizeof(uint32_t)
= 4 byte

Ví dụ địa chỉ:

uint32_t data[5]

data
 ↓
0x20000000

data + 1
 ↓
0x20000004

data + 2
 ↓
0x20000008

data + 3
 ↓
0x2000000C

Con trỏ hiểu kích thước của kiểu dữ liệu mà nó trỏ tới.


5. Thí nghiệm rất quan trọng

Bạn hãy thử đoạn C này:

#include <stdio.h>
#include <stdint.h>

int main()
{
    uint32_t data[5];

    printf("%p\n", (void*)data);
    printf("%p\n", (void*)(data + 1));
    printf("%p\n", (void*)(data + 2));

    return 0;
}

Bạn sẽ thấy các địa chỉ cách nhau khoảng:

4 byte

vì:

sizeof(uint32_t) == 4

6. Con trỏ có thể duyệt qua mảng

Ví dụ:

uint8_t data[5] = {10, 20, 30, 40, 50};

uint8_t *p = data;

Ban đầu:

p
│
▼
data[0]

10

Nếu:

p++;

thì:

p
│
▼
data[1]

20

Tiếp tục:

p++;

thì:

p
│
▼
data[2]

30

Vì vậy ta có thể duyệt mảng bằng con trỏ.


7. Ví dụ thực tế

#include <stdio.h>
#include <stdint.h>

int main()
{
    uint8_t data[5] = {10, 20, 30, 40, 50};

    uint8_t *p = data;

    for(int i = 0; i < 5; i++)
    {
        printf("%d\n", *p);
        p++;
    }

    return 0;
}

Kết quả:

10
20
30
40
50

8. Đây chính là điều STM32 sử dụng rất nhiều

Ví dụ sau này bạn đọc UART:

UART
 │
 ▼
RAM
 │
 ▼
buffer[]

Ví dụ:

uint8_t rxBuffer[64];

STM32 nhận 64 byte vào vùng RAM:

rxBuffer[0]
rxBuffer[1]
rxBuffer[2]
...
rxBuffer[63]

Bạn có thể dùng con trỏ để xử lý:

uint8_t *p = rxBuffer;

Sau đó:

p++;

để chuyển sang byte tiếp theo.


9. Một ví dụ cực kỳ quan trọng với STM32

Giả sử ADC tạo ra 10 giá trị:

uint16_t adc[10];

Có thể hình dung:

RAM

adc
 ↓
┌────────┬────────┬────────┬────────┬─────
│ ADC0   │ ADC1   │ ADC2   │ ADC3   │ ...
└────────┴────────┴────────┴────────┴─────

Mỗi phần tử uint16_t chiếm 2 byte.

Nếu:

uint16_t *p = adc;

thì:

*p

là ADC0.

Sau:

p++;

thì:

*p

là ADC1.

Sau:

p++;

thì:

*p

là ADC2.


10. Một điều rất quan trọng: p++ không phải lúc nào cũng tăng 1 byte

Ví dụ:

uint8_t *p;

thì:

p++;

→ tăng 1 byte.

Nhưng:

uint16_t *p;

thì:

p++;

→ tăng 2 byte.

Và:

uint32_t *p;

thì:

p++;

→ tăng 4 byte.

Cho nên:

Con trỏ tăng theo kích thước kiểu dữ liệu mà nó trỏ tới.


11. Bài tập 1 – bạn hãy tự suy nghĩ

Cho:

uint8_t a[4] = {10,20,30,40};

uint8_t *p = a;

Hỏi:

Sau câu lệnh:

printf("%d", *p);

in ra gì?


Sau:

p++;
printf("%d", *p);

in ra gì?


Sau:

p++;
p++;
printf("%d", *p);

in ra gì?

Bạn hãy tự trả lời trước, chưa cần chạy chương trình.


12. Bài tập 2 – rất quan trọng

Cho:

uint16_t adc[4] = {1000,2000,3000,4000};

uint16_t *p = adc;

Hãy xác định:

*p

bằng bao nhiêu?

Sau:

p++;

thì:

*p

bằng bao nhiêu?

Sau:

p++;

thì:

*p

bằng bao nhiêu?


13. Bài tập 3 – liên quan trực tiếp đến RAM

Giả sử:

uint32_t data[3];

và:

data bắt đầu tại địa chỉ:

0x20000000

Hãy xác định địa chỉ của:

&data[0]
&data[1]
&data[2]

Biết:

sizeof(uint32_t) = 4

14. Kiến thức bạn cần nhớ sau Bài 6

Bạn chưa cần học thuộc hàng đống câu lệnh.

Chỉ cần thật sự hiểu 5 điều này:

① Mảng chứa nhiều phần tử cùng kiểu.

② data thường biểu diễn địa chỉ phần tử đầu tiên.

③ data[i] tương đương *(data + i).

④ p++ đưa con trỏ sang phần tử kế tiếp.

⑤ p++ tăng theo sizeof(kiểu dữ liệu).

Nếu bạn hiểu chắc 5 điều này thì bạn đã bắt đầu chuyển từ:

“lập trình Arduino bằng cách gọi hàm”

sang:

“hiểu cách C thực sự làm việc với RAM của STM32.”


🔜 Bài 7

Sau Bài 6, chúng ta nên học:

BÀI 7 – const, con trỏ tới const, const + con trỏ và tại sao STM32 có rất nhiều dòng const uint8_t *...

Phần này cực kỳ hữu ích trước khi chúng ta đi vào struct, function, UART, GPIO register và DMA.

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