
---
#领域/未知

#复盘/0 #临时/备忘 #状态/待处理

20260528-备忘-主题名-文件内容

## 一句话描述

[________]

---
# 🔥 MicroPython ESP32 自定义**内置 C 模块** 完整标准流程

（适配你的 ESP32-S3，零报错、可直接复用，总结所有实操步骤）

## 一、核心前提

我们做的是 **编译进固件的 C 语言内置模块**（性能高、可直接 import）

开发目录固定：

plaintext

```
micropython/ports/esp32/
```

---

## 二、标准 5 步流程（必看）

### 步骤 1：创建模块文件

在 `ports/esp32/` 下新建 C 文件，命名规则：

`mod+模块名.c`

例：`modsayhello.c`

---

### 步骤 2：编写模块代码（固定万能模板）

直接复制，修改函数即可，**无报错、适配所有 ESP32**

```c
#include "py/obj.h"
#include "py/runtime.h"

// ====================== 函数1：无参数 hello() ======================
static mp_obj_t sayhello_hello(void) {
    mp_printf(&mp_plat_print, "Hello from ESP32-S3!\n");
    return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_0(sayhello_hello_obj, sayhello_hello);

// ====================== 函数2：带1个参数 hello(name) ======================
static mp_obj_t sayhello_hello_name(mp_obj_t name) {
    const char *str = mp_obj_str_get_str(name);
    mp_printf(&mp_plat_print, "Hello %s!\n", str);
    return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_1(sayhello_hello_name_obj, sayhello_hello_name);

// ====================== 函数3：带2个参数 add(a,b) ======================
static mp_obj_t sayhello_add(mp_obj_t a_obj, mp_obj_t b_obj) {
    int a = mp_obj_get_int(a_obj);
    int b = mp_obj_get_int(b_obj);
    return mp_obj_new_int(a + b); // 返回计算结果
}
static MP_DEFINE_CONST_FUN_OBJ_2(sayhello_add_obj, sayhello_add);

// ====================== 把所有函数注册到模块 ======================
static const mp_rom_map_elem_t sayhello_module_table[] = {
    { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sayhello) },
    
    // 在这里添加函数！
    { MP_ROM_QSTR(MP_QSTR_hello),    MP_ROM_PTR(&sayhello_hello_obj) },
    { MP_ROM_QSTR(MP_QSTR_hello_to), MP_ROM_PTR(&sayhello_hello_name_obj) },
    { MP_ROM_QSTR(MP_QSTR_add),      MP_ROM_PTR(&sayhello_add_obj) },
};

static MP_DEFINE_CONST_DICT(sayhello_module_dict, sayhello_module_table);

const mp_obj_module_t sayhello_module = {
    .base = { &mp_type_module },
    .globals = (mp_obj_dict_t*)&sayhello_module_dict,
};

MP_REGISTER_MODULE(MP_QSTR_sayhello, sayhello_module);
```

---

### 步骤 3：添加到编译列表（关键）

打开文件：`ports/esp32/esp32_common.cmake`

找到 `MICROPY_SOURCE_PORT` 列表，**添加你的 C 文件**：

cmake

```
list(APPEND MICROPY_SOURCE_PORT
    # ... 其他文件不变
    modsayhello.c   # 新增这一行
)
```

---

### 步骤 4：编译固件（必须清理缓存）

bash

运行

```
# 进入目录
cd micropython/ports/esp32
# 清理旧缓存（必做！）
make BOARD=ESP32_GENERIC_S3 clean
# 编译固件
make BOARD=ESP32_GENERIC_S3
```

编译成功后，固件位置：

plaintext

```
build-ESP32_GENERIC_S3/firmware.bin
```

---

### 步骤 5：烧录 + 测试

1. 烧录固件

bash

运行

```
esptool.py --chip esp32s3 --port /dev/ttyUSB0 write_flash -z 0x1000 firmware.bin
```

1. REPL 测试

python

运行

```
import 模块名
模块名.函数()
```

---

## 三、函数参数规则（万能记忆）

表格

|参数个数|注册宏|示例|
|---|---|---|
|0 个参数|MP_DEFINE_CONST_FUN_OBJ_0|无参数 hello ()|
|1 个参数|MP_DEFINE_CONST_FUN_OBJ_1|带名字 hello (name)|
|2 个参数|MP_DEFINE_CONST_FUN_OBJ_2|加法 add (a,b)|

---

## 四、添加多个函数（极简流程）

1. 写函数 → 2. 注册宏 → 3. 加入模块表

c

运行

```
// 新增函数
static mp_obj_t test_add(mp_obj_t a, mp_obj_t b) {
    return mp_obj_new_int(mp_obj_get_int(a)+mp_obj_get_int(b));
}
static MP_DEFINE_CONST_FUN_OBJ_2(test_add_obj, test_add);

// 加入模块表
{ MP_ROM_QSTR(MP_QSTR_add), MP_ROM_PTR(&test_add_obj) },
```

---

## 五、实战避坑（你踩过的所有坑）

1. **`STATIC` 报错**：用 C 原生 `static` 替代
2. **编译失败**：必须执行 `make clean` 清理缓存
3. **函数重复定义**：一个函数只能写一个注册宏
4. **文件不生效**：确认 `esp32_common.cmake` 文件名拼写正确
5. **模块找不到**：确认 `MP_REGISTER_MODULE` 模块名一致

---

## 六、一句话总结

创建 `modxxx.c` → 写函数 → 注册到 CMake → 清理编译 → 烧录测试

**这就是 MicroPython ESP32 自定义 C 模块的完整标准流程！**