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 4 – HÀM (FUNCTION) TRONG C

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

Được chứ. Chúng ta tiếp tục đúng mạch học C cho STM32, sau:

  • Bài 1: 10 kiểu biến và STM32 lưu chúng trong RAM như thế nào.
  • Bài 2: các toán tử, phép tính và cách C xử lý dữ liệu.
  • Bài 3: cấu trúc điều khiển chương trình (if, else, switch, for, while…).

🟦 BÀI 4 – HÀM (FUNCTION) TRONG C

“Biến một đoạn chương trình thành một khối có thể gọi đi gọi lại”

Đây là bài cực kỳ quan trọng đối với STM32.

Khi lập trình STM32 thực tế, chương trình của bạn có thể có hàng nghìn, thậm chí hàng chục nghìn dòng. Nếu không biết sử dụng hàm, code sẽ rất khó quản lý.


1. Hàm là gì?

Ví dụ bạn viết:

int a = 10;
int b = 20;
int c = a + b;

Nếu phép cộng này xuất hiện 100 lần thì sao?

Bạn có thể tạo một hàm:

int Cong(int a, int b)
{
    return a + b;
}

Sau đó chỉ cần:

int c = Cong(10, 20);

Kết quả:

c = 30

Có thể hình dung:

             10
              \
               \
                ┌─────────────┐
                │    Cong     │
                │             │
                │   a + b     │
                └──────┬──────┘
                       │
                       ▼
                      30

Hàm giống như một chiếc máy:

INPUT  →  FUNCTION  →  OUTPUT

2. Cấu trúc một hàm

Một hàm C cơ bản:

int Cong(int a, int b)
{
    return a + b;
}

Có 4 phần:

int     Cong     (int a, int b)
│         │             │
│         │             └── tham số
│         └──────────────── tên hàm
└────────────────────────── kiểu trả về

Phần:

return a + b;

là giá trị mà hàm trả về.


3. return cực kỳ quan trọng

Ví dụ:

int Cong(int a, int b)
{
    return a + b;
}

Khi:

int x = Cong(5, 3);

quá trình xảy ra:

Cong(5,3)
   ↓
a = 5
b = 3
   ↓
a + b
   ↓
8
   ↓
x = 8

4. Hàm không trả về giá trị

Đây là loại hàm bạn sẽ gặp rất nhiều trong STM32.

Dùng:

void

Ví dụ:

void Led_On(void)
{
    // bật LED
}

void có nghĩa:

Hàm này không trả về giá trị.

Gọi:

Led_On();

Không thể viết:

int x = Led_On();

vì Led_On() không trả về dữ liệu.


5. Hàm có tham số

Ví dụ:

void Led_Set(int state)
{
    if(state == 1)
    {
        // bật LED
    }
    else
    {
        // tắt LED
    }
}

Gọi:

Led_Set(1);

→ LED ON.

Gọi:

Led_Set(0);

→ LED OFF.

Ở đây:

int state

là parameter – tham số.

Còn:

1

hoặc:

0

là argument – đối số truyền vào.


6. Nhiều tham số

Ví dụ điều khiển LED với độ sáng:

void LED_SetBrightness(int brightness)
{
    // đặt độ sáng
}

Gọi:

LED_SetBrightness(50);

hoặc:

LED_SetBrightness(100);

7. Hàm trả về float

Không nhất thiết phải là int.

Ví dụ:

float Voltage_Calculate(int adc)
{
    return adc * 3.3 / 4095.0;
}

Gọi:

float voltage;

voltage = Voltage_Calculate(2048);

Ta có điện áp khoảng:

1.65 V

Đây chính là kiểu bài toán bạn sẽ gặp khi làm ADC + biến trở trên STM32.


8. Hàm trả về char

Ví dụ:

char Get_Status(void)
{
    return 'A';
}

Gọi:

char status;

status = Get_Status();

Kết quả:

status = 'A'

9. Hàm trả về uint8_t

Khi làm STM32, bạn sẽ thường gặp:

uint8_t
uint16_t
uint32_t

Ví dụ:

uint8_t Get_Button(void)
{
    return 1;
}

Hoặc:

uint16_t Read_ADC(void)
{
    return 2048;
}

Đây là phong cách rất phổ biến trong embedded C.


10. Hàm không có tham số

Ví dụ:

void System_Init(void)
{
    // khởi tạo hệ thống
}

Gọi:

System_Init();

Bạn sẽ thấy STM32 HAL sử dụng kiểu này rất nhiều:

HAL_Init();

Đây chính là một hàm.


11. Hàm có tham số nhưng không trả về

Ví dụ:

void LED_Write(uint8_t state)
{
    // xử lý state
}

Gọi:

LED_Write(1);

Cấu trúc:

void
 ↓
không trả về

LED_Write
 ↓
tên hàm

(uint8_t state)
 ↓
tham số

12. Hàm vừa nhận dữ liệu vừa trả dữ liệu

Đây là loại rất quan trọng.

Ví dụ:

uint16_t ADC_To_PWM(uint16_t adc)
{
    return adc / 4;
}

STM32 ADC 12-bit:

0 → 4095

PWM 8-bit:

0 → 255

Ta có thể chuyển:

ADC
4095
 ↓
ADC_To_PWM()
 ↓
255

Ví dụ:

uint16_t adc;
uint8_t pwm;

adc = 3000;

pwm = ADC_To_PWM(adc);

13. Hàm trong STM32 thực tế

Ví dụ bạn có biến trở 50 kΩ.

ADC đọc:

uint16_t adc_value;

Bạn muốn chuyển ADC thành 20 mức độ sáng.

Có thể viết:

uint8_t ADC_To_Level(uint16_t adc)
{
    return (adc * 20) / 4096;
}

Sau đó:

uint8_t level;

level = ADC_To_Level(adc_value);

Chương trình chính trở nên rất dễ đọc:

Đọc ADC
   ↓
ADC_To_Level()
   ↓
độ sáng
   ↓
điều khiển LED

Đây chính là tư duy lập trình embedded chuyên nghiệp.


14. Một điều cực kỳ quan trọng: phạm vi biến

Xem:

void Test(void)
{
    int x = 10;
}

int main(void)
{
    Test();

    x = 20;   // SAI
}

Tại sao?

Vì x được tạo bên trong hàm Test().

Nó là local variable – biến cục bộ.

Test()
┌──────────────────┐
│ int x = 10;      │
│                  │
│ x chỉ tồn tại    │
│ trong hàm này    │
└──────────────────┘

Ra khỏi hàm:

x
↓
không còn truy cập được

15. Biến toàn cục

Nếu viết:

int x = 10;

void Test(void)
{
    x = 20;
}

int main(void)
{
    Test();
}

thì x là global variable.

Các hàm có thể truy cập nó.

             x
             │
      ┌──────┴──────┐
      │             │
    Test()        main()

Tuy nhiên khi lập trình STM32, không nên lạm dụng biến global.

Sau này chúng ta sẽ học kỹ hơn về:

static
const
volatile

đặc biệt là volatile, rất quan trọng trong embedded.


16. Prototype – khai báo hàm

Đây là một thứ bạn cần bắt đầu làm quen.

Ví dụ:

int Cong(int a, int b);

Đây gọi là function prototype.

Sau đó:

int main(void)
{
    int x;

    x = Cong(10, 20);
}

và phía dưới:

int Cong(int a, int b)
{
    return a + b;
}

Tại sao cần prototype?

Vì compiler cần biết trước:

Cong()
↓
nhận bao nhiêu tham số?
kiểu gì?
trả về kiểu gì?

17. Đây chính là kiểu tổ chức code STM32

Sau này bạn sẽ gặp:

main.c

int main(void)
{
    HAL_Init();

    SystemClock_Config();

    MX_GPIO_Init();

    MX_ADC1_Init();

    while(1)
    {
        Read_ADC();
        Control_LED();
    }
}

Trong đó:

Read_ADC();

là một hàm.

Control_LED();

cũng là một hàm.

Bạn không nhét toàn bộ chương trình vào:

while(1)

mà chia thành các hàm nhỏ.


18. Tư duy rất quan trọng

Một chương trình STM32 tốt thường có dạng:

main()
 │
 ├── Init()
 │
 ├── Read_Input()
 │
 ├── Process()
 │
 └── Output()

Ví dụ dự án biến trở + step motor của bạn:

main()
 │
 ├── ADC_Read()
 │
 ├── ADC_To_Speed()
 │
 ├── Stepper_SetSpeed()
 │
 └── Stepper_Run()

Thay vì viết một đống code:

while(1)
{
    // 100 dòng code
    // 200 dòng code
    // 300 dòng code
}

19. Bài tập thực hành Bài 4

Bạn hãy tự viết chương trình C này:

Bài 1

Viết hàm:

int Cong(int a, int b)

để cộng hai số.

Sau đó:

int x = Cong(15, 25);

Hỏi x bằng bao nhiêu?


Bài 2

Viết:

int Max(int a, int b)

để tìm số lớn hơn.

Ví dụ:

int x = Max(15, 25);

Kết quả:

x = 25

Bài 3

Viết:

int ADC_To_Level(uint16_t adc)

chuyển ADC 0–4095 thành 20 mức.

Ví dụ:

ADC = 0       → Level 0
ADC = 2048    → khoảng Level 10
ADC = 4095    → Level 19 hoặc 20 tùy cách thiết kế

Đây là bài rất đáng làm, vì nó nối trực tiếp kiến thức C với dự án STM32 biến trở mà bạn vừa làm.


🧠 Sau Bài 4, bạn cần nắm được

FUNCTION
│
├── kiểu trả về
│
├── tên hàm
│
├── tham số
│
├── thân hàm
│
├── return
│
├── void
│
├── prototype
│
└── local/global variable

Và quan trọng nhất:

Đừng học thuộc lòng hàm. Hãy hiểu cách một hàm nhận dữ liệu → xử lý → trả kết quả.

Đó là nền tảng để sang phần pointer, array, struct và register — những thứ thực sự bắt đầu làm C trên STM32 trở nên thú vị.

Bài 5 tôi đề xuất sẽ là: ARRAY + STRING – cách STM32 lưu một dãy dữ liệu trong RAM. Đây sẽ là bước nối rất tự nhiên từ biến đơn → hàm → mảng → sau đó tiến tới pointer, phần cực kỳ quan trọng của embedded C.

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