嵌入式专用 Prompt 工程与模板库
第 2 章我们复盘了当前别人在用什么 AI 工具链。但很多读者会遇到同一个困惑:为什么我问的 AI 答不好? 不是 AI 不行,而是提问方式不对。给 AI 的指令就像给工程师的需求书:需求写得含糊,交付必然含糊。
本章你将学会一套可复用的提问框架,拿到 4 类嵌入式专用 Prompt 模板,并通过 4 个完整的实战演示把每个模板用熟。学完本章,你问 AI 的效率会明显拉开和只会随便问问的人的距离。
这里有一点非常重要的一点是,跟随本教程,随着嵌入式开发的深入,从裸机到free_RTOS再到linux。从驱动开发到算法应用。你将不断的积累你的模板库,以后做项目工程的时候,你只需要复刻你的模板库,就能高效的完成各种复杂功能的开发,我想这也是这个教程最具价值的地方,你的库就是你所有的经验,不存在忘记了,有需要重头理一遍。
另一点需要说明的是,AI虽然非常强大,可以回答您任何问题,但是如果你不懂,你就根本没办法判别他的好与坏。
因此,AI可以回答很多问题,但是好的回答就显得尤为重要!!!
3.1 学习目标
-
掌握 Prompt 工程的核心原则;
-
熟练使用 4 类嵌入式专用 Prompt 模板;
-
能根据实际需求自定义属于自己的 Prompt,并建立个人 Prompt 库。
3.2 核心内容
3.2.1 Prompt 工程基础:为什么你问的 AI 答不好
好 Prompt 的四要素框架(RTFC)
本专栏把高质量 Prompt 归纳为四要素,简称 RTFC:
| 要素 | 英文 | 含义 | 反例 |
|---|---|---|---|
| 角色 | Role | 告诉 AI 你是谁、以什么身份回答 | 帮我看看代码 |
| 任务 | Task | 清晰说明要做什么、做到什么程度 | 帮我优化一下 |
| 上下文 | Context | 给出芯片型号、内核版本、硬件连接、代码片段等背景 | 为什么串口乱码 |
| 格式 | Format | 指定输出的结构:表格/步骤/分级清单 | 分析一下 |
这四要素符合主流大模型厂商官方推荐的做法。
OpenAI 官方 Prompt Engineering 指南建议用指令→上下文→示例→输出要求组织消息;Anthropic 官方最佳实践提出黄金法则------提示词:要能让一个不了解任务的同事直接看懂;Google Gemini 官方文档同样推荐输入、约束、响应格式三段式结构。四要素正是把这三家官方建议浓缩成嵌入式场景可用的骨架。
嵌入式场景的特殊要求
通用 Prompt 基础上,嵌入式开发还有四个必须:
- **必须指定芯片型号与内核架构:**STM32F407 是 Cortex-M4,和 STM32F103(Cortex-M3)的寄存器、时钟树都不一样。只说STM32会让 AI 猜,猜就可能给错代码;
- **必须指定软件栈:**寄存器操作、HAL 库 、标准库是三套完全不同的写法;裸机 、FreeRTOS 、Linux 也是不同世界。不指定,AI 默认给你最流行的;
- **必须描述硬件连接:**引脚号、电平逻辑、外设接线(如:LED 接 PF9,高电平点亮,USART1 用 PA9/PA10)------这是 AI 无法凭空知道的,也是最容易出错的地方;
- **必须让 AI 区分"确定"与"推测":**要求它对拿不准的硬件细节明确标注需要人工核对数据手册,而不是自信地编一个。
研究显示:首个嵌入式综合基准 EmbedBench(ICSE 2026,arXiv 2506.11003)显示,最强代码模型在嵌入式任务上 pass@1 仅 55.6%,ESP-IDF 移植类任务最佳仅 29.4%;配合 RAG 检索 + 编译器反馈闭环后可提升至 65.1%。这说明:靠AI 自己猜硬件行不通,必须把硬件上下文喂进去。
三组反面案例 vs 正面案例
案例一:看代码
-
反面:帮我看看这个代码有什么问题?
-
正面:
角色:你是一位严格的嵌入式代码审查专家,擅长 STM32(Cortex-M4)开发。任务:审查以下 GPIO 初始化代码,检查寄存器配置是否正确、是否有遗漏。上下文:芯片 STM32F407,LED 接 PF9(高电平点亮),使用寄存器方式操作。格式:按严重程度分级(致命/警告/建议),每条给出位置、问题、修复方案。[粘贴代码]
案例二:串口乱码
-
反面:为什么我的串口乱码"
-
正面:
角色:你是一位嵌入式调试工程师。任务:分析串口乱码的可能原因,并给出排查顺序。上下文:- 芯片:STM32F407,主频 168MHz,USART1 挂 APB2(84MHz)- 配置:波特率 115200,8 数据位,无校验,1 停止位- 现象:发送英文和数字正常,中文和部分字符乱码- 串口工具:MobaXterm,波特率已核对格式:按可能性从高到低排序,每条给出原因 + 验证方法 + 修复方案。
案例三:生成初始化代码
-
反面:帮我写个串口初始化
-
正面:
角色:你是一位 STM32 HAL 库专家。任务:生成 USART1 的初始化函数。上下文:芯片 STM32F407,APB2=84MHz,波特率 115200,引脚 TX=PA9/RX=PA10(AF7)。约束:使用 HAL 库,开启全局中断,不使用 DMA。格式:先给设计思路(1 段),再给可编译的 .c 代码,最后标注需要人工核对的部分。
3.2.2 模板一:Datasheet 解读模板
适用场景:拿到新芯片/新外设,快速了解关键信息(寄存器、时序、电气特性、坑与 errata)。
模板结构:
角色:你是一位资深嵌入式工程师,精通 [芯片架构]。任务:请解读以下 datasheet 片段,重点关注:1. 关键寄存器及位域定义2. 初始化步骤与时序要求3. 常见坑与 errata4. 与 [其他芯片] 的差异上下文:我使用的是 [开发板型号],[具体硬件连接]。格式:用表格列出寄存器,用步骤列出初始化流程。[粘贴 datasheet 片段、或者上传PDF文档]
实战演示:解读一款 SPI 传感器的 datasheet
以常见 SPI 热电偶传感器 MAX6675 为例:
角色:你是一位传感器驱动专家,精通 MAX6675(SPI K 型热电偶接口)。任务:解读附件的 MAX6675 datasheet 手册,输出:1. SPI 通信时序要点(时钟极性 CPOL/相位 CPHA、最大时钟频率)2. 12 位温度数据的位定义与换算公式(含符号位处理)3. 热电偶开路检测位的用法与误判风险4. 初始化/读取流程步骤格式:寄存器/位定义用表格,流程用编号步骤,无法从片段确认的内容标注"需查官方 datasheet 对应章节"。[粘贴 MAX6675 datasheet 手册]



以下解读基于你提供的 MAX6675 datasheet 片段。片段未给出的参数我会明确标注 **“需查官方 datasheet 对应章节”**。
## 1. SPI 通信时序要点
| 项目 | 结论/要点 |
|---|---|
| 接口类型 | SPI 兼容、只读,SO 输出数据 |
| 片选 CS | `CS` 低使能串口并输出第一位;`CS` 低会立即停止转换;`CS` 高启动新的转换 |
| 读取长度 | 一次完整读取需要 **16 个 SCK 时钟周期** |
| 数据顺序 | D15 先输出,随后 D14…D0 |
| 采样边沿 | datasheet 明确:在时钟 **下降沿** 读取 16 位输出位 |
| CPOL/CPHA | 片段未直接给出参数。根据图 1b 中 SCK 空闲为高、且“下降沿读取”,通常可推断为 **CPOL=1, CPHA=0,即 SPI Mode 2**。但请以官方 Serial Interface Timing 章节为准。**需查官方 datasheet 对应章节** |
| 最大 SCK 频率 | 片段电气特性表中未列出最大 SCK 频率。常见 MAX6675 官方规格约 **4.3 MHz**,但必须以官方 Electrical Characteristics / Serial Interface Timing 为准。**需查官方 datasheet 对应章节** |
| 时序参数 | 图 1b 出现 `tCSS、tCH、tCL、tDV、tDO、tTR`,但片段未给出具体数值。**需查官方 datasheet 对应章节** |
| 转换时间 | 典型 0.17 s,最大 0.22 s(Note 2)。连续读取时必须等待转换完成,否则可能读到旧数据 |
| 电源与旁路 | VCC 3.0 V ~ 5.5 V;VCC 与 GND 间靠近引脚放 0.1 µF 陶瓷旁路电容 |
| 转换控制 | 上电后 `CS` 置高启动转换;读取时拉低 `CS`,读取完再拉高启动下一次转换 |
## 2. 16 位 SO 输出位定义与温度换算
SO 每次输出 16 位,位定义如下:
| 位 | 名称 | 含义 | 处理方式 |
|---|---|---|---|
| D15 | Dummy sign bit | 虚拟符号位,datasheet 说明始终为 0 | 忽略;若读到 1,通常说明时序/接线异常 |
| D14:D3 | 12-bit temperature reading | 12 位温度转换结果,D14 为 MSB,D3 为 LSB | 提取为 `code = (raw >> 3) & 0x0FFF` |
| D2 | Thermocouple input / open detect | 正常为低;热电偶输入开路时变高 | `open = (raw >> 2) & 0x01`,为 1 时报开路故障 |
| D1 | Device ID | MAX6675 器件 ID,datasheet 说明为低,即 0 | 可检查 `(raw >> 1) & 0x01` 是否为 0 |
| D0 | Three-state | 三态 | 忽略 |
### 温度换算公式
```text
raw16 = 读取到的 16 位数据
code = (raw16 >> 3) & 0x0FFF
T_hot = code × 0.25 °C
```
也可写为:
```text
T_hot = code / 4
```
范围与示例:
| code | 温度 |
|---|---|
| 0x000 | 0 °C |
| 0xFFF = 4095 | 4095 × 0.25 = +1023.75 °C |
### 符号位处理
- D15 是 **dummy sign bit**,始终为 0,不是二进制补码符号位。
- D14:D3 这 12 位温度数据按 **无符号数** 处理。
- MAX6675 热端可读范围是 **0 °C 到 +1023.75 °C**,不支持负热端温度。
- 冷端补偿范围 `-20 °C ~ +85 °C` 指的是 MAX6675 环境温度,不是输出负温度。
- 若把 D15 当作符号位,或把 12 位数据当补码,会得到错误结果。
## 3. 热电偶开路检测位 D2 的用法与误判风险
### 用法
- D2 正常为低。
- D2 为高表示热电偶输入开路。
- 每次读取 16 位后应检查 D2;若 D2=1,温度数据应视为无效,应报“热电偶开路/传感器故障”。
- 为使开路检测正常工作,`T-` 必须外部接地,并且接地连接尽量靠近 MAX6675 的 GND 引脚。
### 误判风险
- `T-` 未接地或接地不良时,开路检测器不能正常工作,可能误报开路。
- 电源噪声、地噪声、长导线拾取噪声可能导致 D2 误置位。
- 热电偶或接线瞬断、接触不良可能被捕获为开路。
- 未等待转换完成就读取,可能读到无效或旧数据。
- CS/SCK 时序错误、SO 在 D0 三态期间浮空,可能导致整帧数据错误,从而误判 D2。
- 片段未给出 D2 的检测阈值、滤波和故障判定细节。**需查官方 datasheet 对应章节**。
## 4. 初始化/读取流程步骤
1. **硬件连接与上电**
- VCC 接 3.0 V ~ 5.5 V,GND 接地。
- VCC 与 GND 间靠近器件放置 0.1 µF 旁路电容。
- K 型热电偶:`T+` 接 Chromel,`T-` 接 Alumel。
- `T-` 必须外部接地,接地尽量靠近 MAX6675 的 GND。
- `SO` 接 MCU 的 MISO,`SCK` 接 SPI 时钟,`CS` 接片选。
2. **上电复位**
- 确保 VCC 上升超过上电复位阈值,典型 2.25 V。
- 上电后先将 `CS` 置高,启动一次新的温度转换。
3. **等待转换完成**
- 等待典型 0.17 s,最大 0.22 s;建议等待大于 0.22 s,或按实际官方 Note 2 条件等待。
- 转换期间不要一直保持 `CS` 低,因为 `CS` 低会停止转换。
4. **启动串行读取**
- 拉低 `CS`,使能串口并输出第一位 D15。
- 产生 16 个 SCK 时钟周期。
- 在 SCK 下降沿读取 SO 数据。
- 读取顺序为 D15、D14、…、D0。
- 若使用硬件 SPI,通常按推断配置为 SPI Mode 2;但 CPOL/CPHA 需以官方时序为准。
5. **解析 16 位数据**
```text
raw16 = 读取的 16 位
open = (raw16 >> 2) & 0x01
id = (raw16 >> 1) & 0x01
code = (raw16 >> 3) & 0x0FFF
T_hot = code * 0.25
```
- 若 `open == 1`,报热电偶开路,温度无效。
- 若 `id != 0`,可视为通信异常。
- D15 应为 0,D0 忽略。
6. **结束读取并启动下一次转换**
- 拉高 `CS`,结束本次读取并启动新的转换。
- 若连续采样,重复“等待转换 → 拉低 CS 读取 16 位 → 拉高 CS 启动下一次转换”。
7. **误差与噪声处理**
- 使用 0.1 µF 旁路电容,远离噪声源。
- 长热电偶线建议使用双绞线。
- 避免热源靠近 MAX6675,冷端与 MAX6675 尽量同温。
- 使用大接地平面改善热性能。
### 需查官方 datasheet 的内容汇总
- CPOL/CPHA 的官方明确模式:**需查官方 datasheet 对应章节**。
- 最大 SCK 频率:**需查官方 datasheet 对应章节**。
- `tCSS、tCH、tCL、tDV、tDO、tTR` 具体数值:**需查官方 datasheet 对应章节**。
- Conversion Time 的 Note 2 条件:**需查官方 datasheet 对应章节**。 - D2 开路检测的阈值、滤波和详细误判条件:**需查官方 datasheet 对应章节**。
进阶技巧:分段喂入长 datasheet
datasheet 动辄几百页,一次性粘贴会超出上下文窗口。正确做法, Anthropic 官方建议长文档放顶部、查询放末尾:
-
第一轮:贴器件概述 + 引脚定义段落,问这个芯片有哪些功能模块、引脚如何分类;
-
第二轮:贴寄存器描述段落,问关键寄存器位定义汇总表;
-
第三轮:贴电气特性 + 时序图段落,问"初始化步骤与最小时序要求;
-
最后:让 AI 把三份摘要串联成一份快速上手笔记。
防幻觉要点:datasheet 提取后必须与厂商头文件、参考手册二次核对,AI 最容易忽略脚注footnote与 errata 勘误------这是社区多方验证的共识。
3.2.3 模板二:代码生成模板
适用场景:需要快速生成驱动框架、初始化代码、应用逻辑。
模板结构:
角色:你是一位嵌入式软件开发工程师,有 [X] 年经验。任务:请为 [芯片型号] 编写 [功能模块] 代码。要求:1. 使用 [寄存器/HAL/标准库] 方式2. 代码风格:[注释量/命名规范]3. 需要包含:初始化函数、读写函数、中断处理(如适用)4. 硬件连接:[具体引脚]上下文:这是一个 [项目类型] 项目,已有 [已有代码说明]。格式:先给出设计思路,再给出完整代码,最后标注需要人工确认的部分。
实战演示:用 AI 生成 STM32 的 UART 初始化 + DMA 接收代码
角色:你是一位 STM32 嵌入式专家,精通 HAL 库与 DMA。任务:生成 USART1 初始化 + DMA 接收的完整代码。上下文:- 芯片:STM32F407VGT6,APB2=84MHz- 引脚:TX=PA9、RX=PA10(复用功能 AF7)- 波特率 115200,8-N-1- DMA:USART1_RX 使用 DMA2 Stream2,Channel4(以工程实际分配为准)约束:1. 使用 HAL 库(禁止寄存器风格)2. DMA 配置使用 HAL_DMA 与 __HAL_LINKDMA 方式3. 接收使用空闲中断 + DMA 不定长接收思路(若实现复杂,给出可行简化方案)4. 所有外设基地址与宏定义以 STM32F407xx.h 为准,禁止凭记忆写格式:先给设计思路(2-3 段),再给可编译的 main.c/中断回调,最后列出"需要人工核对"的清单。

objectivec/* ============================================================ * main.c --- USART1 DMA 空闲中断不定长接收 * 芯片: STM32F407VGT6 | APB2 = 84MHz * TX=PA9 RX=PA10 AF7 * DMA: USART1_RX -> DMA2_Stream2, Channel 4 * 参考: stm32f407xx.h (USART1_BASE, DMA2_Stream2_BASE 等宏) * ============================================================ */ #include "stm32f4xx_hal.h" #include <string.h> /* ---------- 全局句柄 ---------- */ UART_HandleTypeDef huart1; DMA_HandleTypeDef hdma_usart1_rx; /* ---------- 接收缓冲区 ---------- */ #define RX_BUFFER_SIZE 256U uint8_t g_rx_buffer[RX_BUFFER_SIZE]; volatile uint16_t g_rx_len = 0; /* 上一帧实际接收长度 */ volatile uint8_t g_rx_ready = 0; /* 帧就绪标志,供主循环轮询 */ /* ---------- 前向声明 ---------- */ static void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_DMA_Init(void); static void MX_USART1_UART_Init(void); /* ============================================================ * main * ============================================================ */ int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_DMA_Init(); MX_USART1_UART_Init(); /* 启动 DMA 接收(循环模式,缓冲满自动回卷) */ HAL_UART_Receive_DMA(&huart1, g_rx_buffer, RX_BUFFER_SIZE); /* 使能 USART1 空闲中断(IDLE) */ __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); while (1) { if (g_rx_ready) { g_rx_ready = 0; /* 此处处理 g_rx_buffer 中长度为 g_rx_len 的数据 */ /* 例如:回传 */ HAL_UART_Transmit(&huart1, g_rx_buffer, g_rx_len, 100); memset(g_rx_buffer, 0, g_rx_len); g_rx_len = 0; } } } /* ============================================================ * 时钟配置:HSE 8MHz -> PLL -> SYSCLK 168MHz, APB2 = 84MHz * 此处保留占位,实际工程请使用 CubeMX 生成的时钟树代码 * ============================================================ */ static void SystemClock_Config(void) { /* ... 由 CubeMX / 手动配置生成,确保 APB2 Prescaler = 2 分频 */ /* 不在此处展开,避免与用户工程冲突 */ } /* ============================================================ * GPIO:PA9 (TX), PA10 (RX) --- AF7, 复用推挽 / 上拉输入 * ============================================================ */ static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); /* PA9 --- USART1_TX, AF7, 推挽复用 */ GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* PA10 --- USART1_RX, AF7, 上拉输入(防浮空误触发 IDLE) */ GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; /* AF 模式内部可配输入 */ GPIO_InitStruct.Pull = GPIO_PULLUP; /* 关键:上拉抑制噪声 */ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } /* ============================================================ * DMA 初始化 --- USART1_RX -> DMA2_Stream2 / Channel 4 * * 映射依据:STM32F407 DMA 请求映射表中 * USART1_Rx -> DMA2_Stream2 或 DMA2_Stream5, 通道均为 Channel4 * 用户指定 Stream2,此处遵循用户分配。 * ============================================================ */ static void MX_DMA_Init(void) { __HAL_RCC_DMA2_CLK_ENABLE(); /* ---------- USART1_RX DMA 配置 ---------- */ hdma_usart1_rx.Instance = DMA2_Stream2; hdma_usart1_rx.Init.Channel = DMA_CHANNEL_4; hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE; /* 外设地址固定 */ hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE; /* 存储器地址递增 */ hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_usart1_rx.Init.Mode = DMA_CIRCULAR; /* 循环模式 */ hdma_usart1_rx.Init.Priority = DMA_PRIORITY_HIGH; hdma_usart1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; HAL_DMA_Init(&hdma_usart1_rx); /* ---------- 将 DMA 句柄链接到 UART 句柄的 hdmarx ---------- */ __HAL_LINKDMA(&huart1, hdmarx, hdma_usart1_rx); /* ---------- DMA2_Stream2 NVIC 配置 ---------- */ /* 本方案中 DMA 本身不需要中断(循环模式 + IDLE 通知), 但保留 NVIC 使能以兼容 HAL 错误处理路径。若不需要可注释。 */ HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 5, 0); HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn); } /* ============================================================ * USART1 初始化 --- 115200, 8-N-1, APB2 = 84MHz * ============================================================ */ static void MX_USART1_UART_Init(void) { __HAL_RCC_USART1_CLK_ENABLE(); huart1.Instance = USART1; huart1.Init.BaudRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; HAL_UART_Init(&huart1); /* ---------- USART1 NVIC:用于 IDLE 中断 ---------- */ HAL_NVIC_SetPriority(USART1_IRQn, 5, 0); HAL_NVIC_EnableIRQ(USART1_IRQn); }
后面我们安装完工具后让他跑起来,看起来是没什么问题的。

关键技巧:
- 明确指定标注需要人工确认的部分------要求 AI 主动暴露不确定性,而不是事后你去猜哪些可能是错的;
- 给出 APB 时钟值------波特率分频是 AI 最常算错的地方,把APB2=84MHz写进上下文能显著降错;
- 要求用宏不用魔法数------Anthropic 官方提示模板明确反对 hard-code 数值,对嵌入式可维护性尤其重要;
- 让 AI 最后自查寄存器------把你写到的每个寄存器地址与官方头文件核对一遍,无法确认就标注。
3.2.4 模板三:日志/报错分析模板
适用场景:编译报错、运行崩溃、内核 oops、硬件异常。
模板结构:
角色:你是一位嵌入式调试专家,擅长 [MCU/Linux 驱动] 问题排查。任务:分析以下报错信息,给出可能的原因和排查步骤。报错信息:[粘贴完整报错日志]上下文:- 硬件平台:[开发板]- 软件环境:[内核版本/编译器版本]- 操作步骤:[复现步骤]- 已尝试:[已做的排查]格式:按可能性排序,每条给出原因 + 验证方法 + 修复建议。
示例:分析 STM32 HardFault 报错
角色:你是一位 ARM Cortex-M4 故障分析专家。任务:根据以下崩溃信息定位 HardFault 根因并给出修复方案。崩溃现场(真实值,来自调试器):- CFSR (0xE000ED28) = 0x00008200(请逐位拆解说明触发的 fault 类型)- HFSR (0xE000ED2C) = 0x40000000- 触发位置:PC=0x08001234,LR=0x08004567- 代码上下文:崩溃发生在 USART1 中断回调中补充信息:- 已排查:电源稳定(3.3V)、MPU 配置- 尚未排查:栈溢出、野指针、中断优先级格式:先给出最可能的根因排序(概率从高到低),每条给验证步骤和修复方案。禁止编造寄存器值;所有数值以上面提供的为准。
3.2.5 模板四:代码审查模板
适用场景:AI 生成代码后自查、他人代码 Review。
模板结构:
角色:你是一位严格的嵌入式代码审查专家,关注硬件安全性和实时性。
任务:审查以下代码,重点检查:
1. 硬件相关:寄存器配置是否正确、时序是否满足
2. 内存安全:缓冲区溢出、野指针、内存泄漏
3. 并发安全:中断/多任务下的竞态条件
4. 实时性:阻塞调用、死循环、优先级问题
5. 代码风格:命名、注释、可维护性
上下文:代码运行在 [芯片],[RTOS/裸机] 环境。
格式:按严重程度分级(致命/警告/建议),每条给出位置、问题、修复方案。
[粘贴代码]
3.2.6 Prompt 进阶技巧
上下文管理:长对话如何保持上下文不丢失
-
核心信息(芯片型号、引脚、时钟)在每轮关键提问中都重申一遍,不要指望 AI 记得上一轮(Anthropic 官方建议:长上下文放开头,具体请求放结尾);
-
对话变长后,主动总结目前已确认、待确认清单,让 AI 基于最新状态继续;
-
规则类信息(约束、禁止项)写进项目级规则文件(如 AGENTS.md 、.trae、rules),每次会话自动注入------这是七家主流工具(Cursor 、Claude Code 、Copilot、 JetBrains、 Cline 、Qoder CN、Trae CN)官方共同推荐的做法。
多轮迭代:第一次不满意如何追问修正
-
第一次不满意,不要重新问一遍,而是指出具体偏差:你给的是标准库写法,我要求 HAL 库;请基于现有代码重写 USART 部分;
-
要求 AI 先解释它理解的需求,你确认后再写代码:先要求 AI 输出计划/Spec,审查纠正后再写代码;
-
编译报错时,把文件路径 + 行号 + 错误信息完整喂回:PhantomRun 实证这是修复率最高的模式。
角色设定:让 AI 扮演严格的导师vs乐于助人的同事的差异
-
严格的导师:更适合代码审查、方案评审------要求逐条挑错、按严重度分级、不给面子;
-
乐于助人的同事:更适合学习讲解、方案探讨------要求解释为什么、给替代方案;
-
关键不在措辞,而在你随后要求它做的事。角色设定要与任务、格式配套。
避免幻觉:如何让 AI 标注不确定的部分
-
在模板末尾追加兜底句:任何你无法从给定资料确认的硬件参数,明确列出并标注需人工核对,禁止自行补全或编造;
-
涉及寄存器/引脚,强制要求以厂商官方头文件为准:只依赖上下文中直接提到的事实,不要使用自己的知识;
-
datasheet 类提取任务,明确:只基于我提供的文本,禁止补充未写内容,无法确定填 null。
提示词保存与管理:用 Trae 建个人 Prompt 库,后面专门演示
推荐用 Trae CN(原豆包 MarsCode)搭建个人 Prompt 库:
-
新建一个专门的Prompt 库仓库/项目,按场景归档;
-
把本章 4 类模板存为
.md文件,每个文件头部写清楚适用场景 + 用法要点; -
需要时用 Trae 的
#Rule手动引用规则文件,或把模板粘贴进对话; -
实战中改好的模板回写覆盖,让模板随项目沉淀,这样你就具备大批的数据库。
常见坑与提醒
- **Prompt 不是越长越好:**关键信息要精准------芯片型号、引脚、时钟、约束给足即可,无关描述会稀释重点;
- **不要一次问太多问题:**拆成多轮对话,一轮聚焦一个问题(尤其调试场景,一次一个假设);
- **AI 生成的代码必须人工审核:**尤其是寄存器配置、引脚复用、时钟分频------烧录前与官方头文件核对;
- **模板是起点:**要根据实际情况调整,不要生搬硬套------把你的芯片、引脚、库版本填进模板再使用。