CSDN专栏:
- 嵌入式程序开发实战
- 嵌入式双范式AI编程
- 嵌入式开发必掌握
- 嵌入式求职面试技术资料
第16讲:嵌入式Vibe标准流程——硬件需求口语化→AI生成驱动→烧录试错→迭代
一、Vibe标准流程概述
Vibe模式的核心是"快速试错、迭代修正",通过标准化的流程,确保快速开发的同时保持可控性。
1.1 标准流程四步骤
#mermaid-svg-gvPgxZSLj3OOlh1J{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-gvPgxZSLj3OOlh1J .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-gvPgxZSLj3OOlh1J .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-gvPgxZSLj3OOlh1J .error-icon{fill:#552222;}#mermaid-svg-gvPgxZSLj3OOlh1J .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-gvPgxZSLj3OOlh1J .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-gvPgxZSLj3OOlh1J .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-gvPgxZSLj3OOlh1J .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-gvPgxZSLj3OOlh1J .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-gvPgxZSLj3OOlh1J .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-gvPgxZSLj3OOlh1J .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-gvPgxZSLj3OOlh1J .marker{fill:#333333;stroke:#333333;}#mermaid-svg-gvPgxZSLj3OOlh1J .marker.cross{stroke:#333333;}#mermaid-svg-gvPgxZSLj3OOlh1J svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-gvPgxZSLj3OOlh1J p{margin:0;}#mermaid-svg-gvPgxZSLj3OOlh1J .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-gvPgxZSLj3OOlh1J .cluster-label text{fill:#333;}#mermaid-svg-gvPgxZSLj3OOlh1J .cluster-label span{color:#333;}#mermaid-svg-gvPgxZSLj3OOlh1J .cluster-label span p{background-color:transparent;}#mermaid-svg-gvPgxZSLj3OOlh1J .label text,#mermaid-svg-gvPgxZSLj3OOlh1J span{fill:#333;color:#333;}#mermaid-svg-gvPgxZSLj3OOlh1J .node rect,#mermaid-svg-gvPgxZSLj3OOlh1J .node circle,#mermaid-svg-gvPgxZSLj3OOlh1J .node ellipse,#mermaid-svg-gvPgxZSLj3OOlh1J .node polygon,#mermaid-svg-gvPgxZSLj3OOlh1J .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-gvPgxZSLj3OOlh1J .rough-node .label text,#mermaid-svg-gvPgxZSLj3OOlh1J .node .label text,#mermaid-svg-gvPgxZSLj3OOlh1J .image-shape .label,#mermaid-svg-gvPgxZSLj3OOlh1J .icon-shape .label{text-anchor:middle;}#mermaid-svg-gvPgxZSLj3OOlh1J .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-gvPgxZSLj3OOlh1J .rough-node .label,#mermaid-svg-gvPgxZSLj3OOlh1J .node .label,#mermaid-svg-gvPgxZSLj3OOlh1J .image-shape .label,#mermaid-svg-gvPgxZSLj3OOlh1J .icon-shape .label{text-align:center;}#mermaid-svg-gvPgxZSLj3OOlh1J .node.clickable{cursor:pointer;}#mermaid-svg-gvPgxZSLj3OOlh1J .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-gvPgxZSLj3OOlh1J .arrowheadPath{fill:#333333;}#mermaid-svg-gvPgxZSLj3OOlh1J .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-gvPgxZSLj3OOlh1J .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-gvPgxZSLj3OOlh1J .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gvPgxZSLj3OOlh1J .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-gvPgxZSLj3OOlh1J .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gvPgxZSLj3OOlh1J .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-gvPgxZSLj3OOlh1J .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-gvPgxZSLj3OOlh1J .cluster text{fill:#333;}#mermaid-svg-gvPgxZSLj3OOlh1J .cluster span{color:#333;}#mermaid-svg-gvPgxZSLj3OOlh1J div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-gvPgxZSLj3OOlh1J .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-gvPgxZSLj3OOlh1J rect.text{fill:none;stroke-width:0;}#mermaid-svg-gvPgxZSLj3OOlh1J .icon-shape,#mermaid-svg-gvPgxZSLj3OOlh1J .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gvPgxZSLj3OOlh1J .icon-shape p,#mermaid-svg-gvPgxZSLj3OOlh1J .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-gvPgxZSLj3OOlh1J .icon-shape .label rect,#mermaid-svg-gvPgxZSLj3OOlh1J .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gvPgxZSLj3OOlh1J .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-gvPgxZSLj3OOlh1J .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-gvPgxZSLj3OOlh1J :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
步骤一:硬件需求口语化
步骤二:AI生成驱动代码
步骤三:烧录试错验证
步骤四:迭代修正完善
1.2 流程特点
特点一:口语化输入
传统方式:
- 查阅数据手册
- 理解寄存器定义
- 编写配置代码
Vibe方式:
- 口语描述需求
- AI自动生成代码
- 无需深入理解寄存器
特点二:快速试错
传统方式:
- 仔细设计
- 一次写对
- 调试时间长
Vibe方式:
- 快速生成
- 立即试错
- 迭代修正
特点三:迭代完善
传统方式:
- 设计完整方案
- 实现全部功能
- 一次性完成
Vibe方式:
- 先实现基本功能
- 发现问题再修正
- 逐步完善
二、步骤一:硬件需求口语化
2.1 口语化描述的原则
原则一:明确硬件目标
必须明确:
- 使用哪个MCU(如STM32F103)
- 使用哪个外设(如USART1)
- 使用哪些引脚(如PA9/PA10)
原则二:明确功能需求
必须明确:
- 要实现什么功能(如串口通信)
- 具体参数(如波特率115200)
- 特殊要求(如中断接收)
原则三:明确开发环境
必须明确:
- 使用什么库(如HAL库、LL库)
- 使用什么IDE(如Keil、STM32CubeIDE)
- 使用什么工具链(如ARM GCC)
2.2 口语化描述模板
基础模板:
【硬件需求描述】
目标MCU:[STM32F103C8T6]
外设配置:
– 外设:[USART1]
– 引脚:[PA9(TX), PA10(RX)]
– 参数:[波特率115200, 8位数据, 1位停止, 无校验]
功能需求:
– [发送数据]
– [接收数据]
– [中断接收]
开发环境:
– 库:[HAL库]
– IDE:[Keil MDK]
2.3 典型案例:串口驱动口语化描述
案例:USART1串口通信
口语化描述:
【硬件需求描述】
目标MCU:STM32F103C8T6
外设配置:
– 外设:USART1
– 引脚:PA9(TX), PA10(RX)
– 参数:波特率115200, 8位数据, 1位停止, 无校验
功能需求:
– 初始化USART1
– 发送字符串"Hello World"
– 接收数据并回显
– 使用中断接收
开发环境:
– 库:HAL库
– IDE:Keil MDK
对应的Prompt:
请生成STM32F103的USART1驱动代码:
– 使用HAL库
– 引脚:PA9(TX), PA10(RX)
– 波特率:115200, 8N1
– 功能:
1. 初始化USART1
2. 发送字符串"Hello World"
3. 中断接收数据并回显
2.4 口语化描述的注意事项
注意一:参数要具体
错误描述:
"配置一个串口"
正确描述:
"配置USART1,波特率115200,8位数据,1位停止,无校验"
注意二:引脚要明确
错误描述:
"配置串口引脚"
正确描述:
"配置PA9为TX,PA10为RX"
注意三:功能要清晰
错误描述:
"实现串口功能"
正确描述:
"实现串口发送、接收、中断接收、回显功能"
三、步骤二:AI生成驱动代码
3.1 AI生成的Prompt技巧
技巧一:结构化Prompt
结构:
1. 目标MCU和库
2. 外设配置
3. 功能需求
4. 特殊要求
示例:
【目标】STM32F103 + HAL库
【外设配置】
USART1, PA9(TX)/PA10(RX), 115200-8N1
【功能需求】
1. 初始化
2. 发送数据
3. 接收数据(中断)
【特殊要求】
– 使用DMA发送
– 接收超时100ms
技巧二:提供上下文
如果是在现有工程基础上添加功能,需要提供:
– 现有工程结构
– 已有驱动代码
– 接口定义
示例:
【现有工程】
– 已有GPIO驱动
– 已有时钟配置
– 需要添加USART驱动
【接口要求】
– 函数名:USART1_Init(), USART1_Send(), USART1_Receive()
– 返回值:int8_t类型
技巧三:明确代码风格
明确要求:
– 命名风格:驼峰命名或下划线命名
– 注释风格:Doxygen格式或简洁格式
– 代码风格:缩进、括号位置
示例:
【代码风格】
– 函数命名:USART1_Init(下划线分隔)
– 注释:Doxygen格式
– 缩进:4空格
3.2 AI生成的典型结果
案例:USART1驱动生成
Prompt:
请生成STM32F103的USART1驱动代码:
– 使用HAL库
– 引脚:PA9(TX), PA10(RX)
– 波特率:115200, 8N1
– 功能:初始化、发送、中断接收
– 代码风格:函数命名使用下划线分隔
AI生成结果:
/* USART1 Driver */
#include "stm32f1xx_hal.h"
UART_HandleTypeDef huart1;
/* USART1 Initialization */
void USART1_Init(void) {
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 Send Data */
void USART1_Send(uint8_t *data, uint16_t len) {
HAL_UART_Transmit(&huart1, data, len, 100);
}
/* USART1 Receive Data (Interrupt) */
void USART1_Receive_IT(void) {
HAL_UART_Receive_IT(&huart1, &rx_data, 1);
}
/* USART1 IRQ Handler */
void USART1_IRQHandler(void) {
HAL_UART_IRQHandler(&huart1);
}
/* HAL UART Receive Complete Callback */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
if(huart->Instance == USART1) {
// Process received data
USART1_Send(&rx_data, 1); // Echo
HAL_UART_Receive_IT(&huart1, &rx_data, 1); // Continue receive
}
}
3.3 AI生成结果的评估
评估维度一:功能完整性
检查:
- 是否实现了所有需求的功能
- 是否遗漏了关键功能
- 是否有多余的功能
评估维度二:代码正确性
检查:
- 语法是否正确
- 逻辑是否正确
- 配置是否正确
评估维度三:代码风格
检查:
- 命名是否符合要求
- 注释是否完整
- 格式是否规范
四、步骤三:烧录试错验证
4.1 编译烧录流程
流程:
4.2 编译错误处理
常见编译错误:
错误一:头文件缺失
错误信息:fatal error: stm32f1xx_hal.h: No such file or directory
解决方法:
– 添加HAL库头文件路径
– 或在Prompt中要求包含完整头文件
错误二:变量未定义
错误信息:error: 'rx_data' undeclared
解决方法:
– 添加变量定义:uint8_t rx_data;
– 或要求AI生成完整的变量定义
错误三:函数重复定义
错误信息:error: redefinition of 'USART1_IRQHandler'
解决方法:
– 检查是否已有中断服务函数
– 删除重复定义
– 或要求AI生成时避免重复
4.3 运行现象观察
观察要点:
要点一:基本功能
检查:
- 是否能正常初始化
- 是否能正常发送
- 是否能正常接收
要点二:时序正确性
检查:
- 通信时序是否正确
- 波特率是否正确
- 数据是否完整
要点三:异常情况
检查:
- 是否有异常现象
- 是否有错误提示
- 是否有硬件异常
4.4 典型问题案例
案例:串口发送乱码
现象:
发送"Hello World",接收到乱码
分析:
可能原因:
验证方法:
五、步骤四:迭代修正完善
5.1 迭代修正的原则
原则一:每次只改一个问题
错误做法:
同时修改波特率、引脚、中断配置
正确做法:
先修改波特率,测试通过后再修改其他
原则二:明确描述问题
错误做法:
"代码不对,帮我改"
正确做法:
"串口发送乱码,波特率配置为115200,但实际测量为9600,请修正波特率配置"
原则三:验证每次修改
流程:
5.2 迭代修正的Prompt
修正Prompt模板:
【问题描述】
[具体问题现象]
【当前代码】
[粘贴当前代码]
【期望结果】
[期望的正确行为]
【分析】
[问题分析]
请修改代码,解决问题
案例:修正波特率错误
修正Prompt:
【问题描述】
串口发送乱码,使用逻辑分析仪测量实际波特率为9600,期望为115200
【当前代码】
huart1.Init.BaudRate = 115200;
【分析】
系统时钟可能配置错误,导致波特率计算错误
【期望结果】
实际波特率为115200
请检查时钟配置,修正波特率问题
AI修正结果:
/* Check system clock configuration */
void SystemClock_Config(void) {
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
// Configure HSE and PLL
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; // 8MHz * 9 = 72MHz
if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
Error_Handler();
}
// Configure system clock
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) {
Error_Handler();
}
}
5.3 迭代次数控制
建议:
单次迭代:解决1个具体问题 迭代次数:通常2-5次即可完成 迭代时间:每次迭代10-30分钟 总时间:通常30分钟-2小时完成一个驱动
避免过度迭代:
如果迭代超过5次仍未解决:
六、完整案例:温湿度传感器驱动
6.1 需求描述
口语化描述:
【硬件需求描述】
目标MCU:STM32F103C8T6
外设配置:
– I2C1:PB6(SCL), PB7(SDA)
– 传感器:SHT30(地址0x44)
– I2C速率:100kHz
功能需求:
– 初始化I2C1和SHT30
– 读取温度和湿度
– 通过USART1上报数据
开发环境:
– 库:HAL库
– IDE:Keil MDK
6.2 AI生成代码
Prompt:
请生成STM32F103的SHT30温湿度传感器驱动代码:
– 使用HAL库
– I2C1:PB6(SCL), PB7(SDA)
– SHT30地址:0x44
– I2C速率:100kHz
– 功能:
1. 初始化I2C1
2. 读取SHT30温度和湿度
3. 通过USART1上报数据(波特率115200)
AI生成结果:
/* SHT30 Driver */
#include "stm32f1xx_hal.h"
I2C_HandleTypeDef hi2c1;
UART_HandleTypeDef huart1;
/* I2C1 Initialization */
void I2C1_Init(void) {
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 100000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
HAL_I2C_Init(&hi2c1);
}
/* SHT30 Read Temperature and Humidity */
void SHT30_Read(float *temperature, float *humidity) {
uint8_t cmd[2] = {0x2C, 0x06}; // High repeatability measurement
uint8_t data[6];
HAL_I2C_Master_Transmit(&hi2c1, 0x44 << 1, cmd, 2, 100);
HAL_Delay(20);
HAL_I2C_Master_Receive(&hi2c1, 0x44 << 1, data, 6, 100);
// Calculate temperature
uint16_t rawTemp = (data[0] << 8) | data[1];
*temperature = –45.0f + 175.0f * (float)rawTemp / 65535.0f;
// Calculate humidity
uint16_t rawHumi = (data[3] << 8) | data[4];
*humidity = 100.0f * (float)rawHumi / 65535.0f;
}
/* Main Function */
int main(void) {
HAL_Init();
SystemClock_Config();
I2C1_Init();
USART1_Init();
float temp, humi;
char msg[100];
while(1) {
SHT30_Read(&temp, &humi);
sprintf(msg, "Temp: %.2f°C, Humi: %.2f%%\\r\\n", temp, humi);
HAL_UART_Transmit(&huart1, (uint8_t*)msg, strlen(msg), 100);
HAL_Delay(1000);
}
}
6.3 烧录试错
第一次测试:
现象:读取到的温度和湿度都是固定值(-45°C, 0%)
分析:I2C通信失败,传感器未正确响应
检查:
1. I2C引脚是否正确连接
2. SHT30地址是否正确
3. I2C速率是否合适
第一次迭代:
Prompt:
"读取SHT30返回固定值-45°C和0%,怀疑I2C通信失败。
请添加I2C通信错误检查,并打印调试信息"
AI修正:
添加HAL_I2C_IsDeviceReady检查设备是否就绪
添加错误处理和调试打印
第二次测试:
现象:检测到设备就绪,但读取数据仍错误
分析:可能是时序问题,SHT30需要测量时间
检查:测量命令发送后是否等待足够时间
第二次迭代:
Prompt:
"I2C通信正常,但读取数据错误。
SHT30发送测量命令后需要等待测量完成。
请增加延时等待"
AI修正:
HAL_I2C_Master_Transmit后增加HAL_Delay(20)
第三次测试:
现象:读取到正确的温度和湿度值
验证:
– 温度值合理(室温20-30°C)
– 湿度值合理(40-60%)
– 数据稳定,无跳变
结果:功能正常,迭代完成
6.4 总结
总耗时:
需求描述:5分钟
AI生成:2分钟
第一次测试:10分钟
第一次迭代:5分钟
第二次测试:10分钟
第二次迭代:5分钟
第三次测试:10分钟
总计:约47分钟
对比传统开发:
传统开发:
– 查阅SHT30数据手册:30分钟
– 理解I2C时序:20分钟
– 编写驱动代码:60分钟
– 调试排错:60分钟
总计:约170分钟
Vibe模式效率提升:约3.6倍
七、本讲核心要点
7.1 记住这三句话
Vibe标准流程四步骤:口语化描述→AI生成→烧录试错→迭代修正
口语化描述要明确:硬件目标、功能需求、开发环境
迭代修正要遵循:每次只改一个问题、明确描述问题、验证每次修改
7.2 实践建议
对于新手:
- 学习口语化描述技巧
- 学习Prompt编写技巧
- 实践完整流程
对于有经验工程师:
- 建立口语化描述模板
- 建立Prompt模板库
- 优化迭代流程
7.3 下讲预告
第17讲将深入讲解:不会写寄存器?Vibe模式快速搞定外设初始化
寄存器配置是嵌入式开发的难点,Vibe模式如何帮助快速搞定外设初始化?下一讲将详细讲解。





