自然语言编程时代,如何零基础学习掌握嵌入式编程

前面发文说自然编程语言时代,不要一上来死磕C语言,有人质疑,今天这篇算回应一下:

先说独创的学习培养方法:以做实际项目为目标,通过项目目标牵引学习,用什么学什么,指挥AI实现功能,指挥AI进行知识梳理,结合传统的单一知识点教学视频增强基础。最关键的是,学完以后,因为是做项目,你的知识是成体系化的。

整个过程是无痛学习,功能需求AI拆解,实现技术路径AI规划,测试标准AI定义,代码AI写,最后AI还给你90%进行注释,还一对一的对你进行辅导。

过去很多零基础想学嵌入式,一上来就懵:C 语言、电路、寄存器、时序...... 一堆名词,不知道从哪下手。传统方式,先啃半年理论,再碰硬件,枯燥又劝退,坚持下来的没几个。

其实核心问题很简单:以前没工具,只能先把所有知识学完,才能动手做东西;现在不一样了,完全可以直接从一个看得见、用得上的小项目开始,边做边学、缺啥补啥

直接上干货,AI太吓人了。

我先让他分解了需求,再让它写代码,后面有详细的需求分解,每一步的知识点。


代码交付计划

将创建以下文件(共约 13 个文件)

复制代码
D:\开发板课程\教学理念\code\
├── platformio.ini              # 项目配置(统一)
├── lib/
│   ├── oled/
│   │   ├── ssd1306.h           # OLED驱动头文件
│   │   └── ssd1306.c           # OLED驱动实现
│   ├── sensor/
│   │   ├── ntc_thermistor.h    # NTC温度换算
│   │   └── ntc_thermistor.c
│   ├── control/
│   │   ├── pid.h               # PID控制器
│   │   └── pid.c
│   └── ui/
│       ├── key_input.h         # 按键状态机
│       └── key_input.c
└── src/
    ├── main_step1.c            # 第1步:GPIO LED闪烁
    ├── main_step2.c            # 第2步:按键+LED
    ├── main_step3.c            # 第3步:串口printf
    ├── main_step4.c            # 第4步:ADC测温
    ├── main_step5.c            # 第5步:PWM呼吸灯
    ├── main_step6.c            # 第6步:I2C OLED
    ├── main_step7.c            # 第7步:按键交互UI
    ├── main_step8.c            # 第8步:PWM加热
    ├── main_step9.c            # 第9步:PID温控
    └── main_step10.c           # 第10步:完整集成

每一步包含

  • 完整可编译运行的 main.c

  • 硬件接线说明(代码注释顶部)

  • AI对话提示词(注释标注,知道怎么让AI帮你写和改)

  • 验证步骤(注释标注验收标准)

  • 关键概念注解(为什么这样做)

代码风格

  • 基于 STM32 HAL 库(PlatformIO 框架)

  • 从步骤4开始逐步模块化,提取可复用库

  • 每步代码独立可运行,用户只需改 src/main.c 即可跳步

这是我给AI最初规划学习的提示词:

以"做一个 STM32 控制的智能恒温杯垫,带温度设定、实时测温、自动恒温功能,用 PWM 调加热功率。"的项目为牵引,让零基础学习嵌入式开发。把需求进行拆解,每一步的软件和硬件,应用到的MCU模块,每一步的验证标准都需要明确。

AI输出的结果:

好的,这个项目选得好------硬件简单、功能完整、涵盖嵌入式核心模块。以下是以项目为牵引、逐层递进的完整学习方案。


项目:智能恒温杯垫 ------ 零基础嵌入式学习路线

项目总览

复制代码
┌──────────────────────────────────────────┐
│          智能恒温杯垫 系统框图              │
│                                            │
│   [按钮 +/-] ──→ GPIO输入                  │
│   [NTC热敏] ──→ ADC采样 ──→ 温度计算       │
│   [OLED屏]  ←── I2C通信 ──→ 显示温/设定    │
│   [加热片]  ←── PWM(TIM) ──→ MOSFET驱动    │
│   [LED指示] ←── GPIO输出                   │
│   [串口]    ←── USART  ──→ PC调试监控      │
│                                            │
│   核心逻辑:PID温控循环(TIM定时触发)       │
└──────────────────────────────────────────┘

十步学习路径

每一步都按 「需求 → 涉及模块 → AI怎么帮 → 软件实现 → 硬件连接 → 验证标准」 展开。

每步涉及的MCU模块汇总

步骤 GPIO ADC TIM USART I2C SysTick PID
0 建环境
1 LED
2 按键
3 串口
4 测温
5 PWM
6 OLED
7 交互
8 加热
9 PID
10 集成

学习时间估算

步骤 预计时间 难度
0 环境搭建 半天
1 GPIO输出 半天
2 GPIO输入 半天
3 串口 1天 ⭐⭐
4 ADC测温 1-2天 ⭐⭐
5 PWM 1天 ⭐⭐
6 OLED 1-2天 ⭐⭐⭐
7 交互 1天 ⭐⭐⭐
8 加热驱动 1天 ⭐⭐⭐
9 PID控制 2-3天 ⭐⭐⭐⭐
10 集成打磨 2-3天 ⭐⭐⭐⭐⭐

总计:约 2-3 周(每天投入 2-3 小时)

传统教程教你一行行写C代码、一页页翻数据手册。这份教程假定你身边有一个AI助手(你的主要工作是:

  1. 理解要做什么

    --- 看懂每步的目标和原理

  2. 向AI描述需求

    --- 用自然语言告诉AI你要什么

  3. 审查AI输出

    --- 判断代码对不对、安不安全

  4. 在硬件上验证

    --- 用示波器、串口、万用表确认

  5. 追问"为什么"

    --- 每个现象背后的原理,这是学习发生的时刻

你的角色 :系统设计师 + 审阅者 + 验证工程师
AI的角色:代码生成器 + 知识库 + 调试助手


项目最终形态

复制代码
┌─────────────────────────────────────────────┐
│                                             │
│           OLED 显示                          │
│    ┌─────────────────────┐                  │
│    │  当前: 55.2°C       │                  │
│    │  目标: 55°C  ████░  │  ← 加热功率条    │
│    │  加热中...  PWM:72% │                  │
│    └─────────────────────┘                  │
│      [SET]    [UP]    [DOWN]                │
│                                             │
│   ┌──────┐        ┌──────────┐              │
│   │ NTC  │ ────→  │  STM32   │──→ 加热片    │
│   │ 探头 │  ADC   │  F103    │  PWM         │
│   └──────┘        │          │              │
│                   └──────────┘              │
│                       │                     │
│                       ├─→ OLED (I2C)        │
│                       ├─→ 串口 (USART)       │
│                       └─→ LED 状态指示       │
│                                             │
└─────────────────────────────────────────────┘

功能清单:

  • 实时测温(NTC + ADC),精度 ±1°C

  • OLED显示当前温度、目标温度、加热功率

  • 三个按键:设定 / 加 / 减

  • PID闭环自动恒温控制

  • PWM调节加热功率

  • 串口实时数据输出(可画温度曲线)

  • 安全保护:NTC开路检测、过热保护、看门狗


第一步:环境搭建 ------ 让芯片跑起来

目标

工具链就绪 + AI助手上线 + 第一个程序烧录成功。

硬件连接

复制代码
STM32 Blue Pill          ST-Link V2
┌──────────────┐        ┌──────────┐
│ SWDIO ───────┼────────┤ SWDIO    │
│ SWCLK ───────┼────────┤ SWCLK    │
│ GND   ───────┼────────┤ GND      │
│ 3.3V  ───────┼────────┤ 3.3V     │
└──────────────┘        └────┬─────┘
                             │
                    ┌────────┴─────┐
                    │   USB → PC   │
                    └──────────────┘

软件安装

方案 工具 适合
方案A STM32CubeIDE(官方IDE) 稳,但AI支持一般
方案B(推荐) VSCode + PlatformIO + Claude/Cursor AI原生工作流

推荐方案B的安装步骤:

  1. 安装 VSCode

  2. 安装 PlatformIO 插件

  3. 配置 AI 助手(Cursor 或 Claude Desktop)

AI对话例

复制代码
你: "PlatformIO新建STM32F103C8T6项目,让PC13脚LED闪烁500ms,生成完整代码"

AI: [生成 platformio.ini + main.c]

你: "解释一下:RCC_APB2ENR是什么?为什么操作GPIO前要先操作它?"
AI: [解释时钟使能的原理]

你: "GPIO_BSRR和GPIO_ODR有什么区别?什么时候用哪个?"
AI: [解释位操作 vs 读写操作,原子性问题]

验证标准

  • 编译通过,0错误0警告

  • ST-Link识别到芯片

  • 烧录成功

  • 板载LED(PC13)稳定闪烁,周期1秒

  • 你用万用表测PC13电压,高电平≈3.3V,低电平≈0V

  • 你能用自己的话解释:这段代码从main()开始到LED亮灭,芯片内部发生了什么

关键概念

概念 一句话解释
GPIO 芯片的"手脚",可以输出高低电平或读取外部信号
寄存器 芯片内部的"开关",写1/0控制芯片行为,每个寄存器有固定地址
时钟 芯片的"心跳",每个外设用之前必须先给它"开钟"
推挽输出 能主动输出高电平和低电平,驱动能力强
volatile 告诉编译器"别优化这个变量,每次都要真的读硬件"

第二步:GPIO输入 ------ 按下按钮,点亮LED

目标

理解数字输入、上下拉电阻、机械消抖。

硬件连接

复制代码
       3.3V
        │
        ├── 内部上拉(约40KΩ)
        │
PB0 ────┼────[按钮]──── GND
        │
        └── 读取IDR寄存器

重要:按钮接在PB0和GND之间。按下 = 读到0,松开 = 读到1(因为有内部上拉)。 你也可以外接10KΩ上拉电阻到3.3V,两者等效。

AI对话例

复制代码
你: "PB0接一个按钮(按下接GND,松开上拉到3.3V),按下时PA0的LED翻转。加20ms消抖。"

AI: [生成带消抖的按钮检测代码]

你: "消抖为什么要延时?20ms这个值怎么来的?"

你: "如果我不用内部上拉,浮空输入会有什么问题?"

代码骨架(AI生成,你审查)

复制代码
// AI会生成类似这样的代码 ------ 你要能看懂每行,而不是复制粘贴
if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_RESET) {
    HAL_Delay(20);  // 消抖 ------ 为什么要等?
    if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_RESET) {
        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_0);  // 翻转LED
        while (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_RESET);  // 等释放
    }
}

验证标准

  • 按一次按钮 → LED状态翻转一次(不会一次按出多次翻转)

  • 用万用表测PB0:松开=3.3V,按下=0V

  • 你能解释:把按钮接在PB0和3.3V之间(去掉GND),需要改成下拉模式------代码要改什么?


第三步:USART串口 ------ 让芯片开口说话

目标

建立调试通道。后续每一步的数据可视化全靠它。

硬件连接

复制代码
STM32                    USB-TTL (CH340)
PA9  (TX)  ────────────  RX
PA10 (RX)  ────────────  TX
GND        ────────────  GND
                          │
                          USB → PC

PC端:打开串口助手,波特率115200

注意:TX接RX,RX接TX,GND必须共地。

AI对话例

复制代码
你: "在PlatformIO STM32F103上把printf重定向到USART1,波特率115200。PA9=TX PA10=RX"

AI: [生成 USART 初始化 + fputc重定向代码]

你: "为什么PA9和PA10要配置成GPIO_MODE_AF_PP?AF是什么意思?"

你: "波特率115200是怎么算出来的?72000000/16/115200 等于多少?"

验证标准

  • PC串口助手收到 "Hello from STM32!\r\n"

  • 按下按钮时,串口打印 "Button Pressed! Count: N"

  • 每隔1秒打印一次 "Tick: N"(用HAL_GetTick())

  • 你能解释:为什么STM32输出的是TTL电平,而电脑USB口需要CH340模块转换?

从这一步开始养成习惯

以后所有调试,打开串口助手看数据。不要猜!


第四步:ADC测温 ------ 把温度变成数字

目标

理解模拟采样、ADC量化、电压→物理量换算。

硬件连接

复制代码
      3.3V
       │
      ┌┴┐
      │ │ NTC 10KΩ @25°C, B=3950
      │ │ (温度越高,电阻越小)
      └┬┘
       │
       ├────── PA1 (ADC12_IN1)
       │
      ┌┴┐
      │ │ R_ref 10KΩ 1%
      │ │
      └┬┘
       │
      GND

工作原理:NTC和固定电阻串联分压。温度变化 → NTC阻值变化 → 分压变化 → ADC读数变化 → 温度计算。

AI对话例

复制代码
你: "PA1配置ADC1,12位精度,每1秒采样一次。10KΩ B=3950 NTC,参考电阻10KΩ接GND,3.3V供电。写温度计算函数,结果用printf打印。"

AI: [生成ADC配置 + 温度换算]

你: "这个温度公式每一步在算什么?"
你: "Steinhart-Hart方程和B值简化公式有什么区别?我这个场景用哪个?"
你: "ADC读到2048对应几V?对应NTC多少Ω?对应多少度?一步步算给我看。"

温度换算公式

复制代码
// ADC → 电压
float voltage = adc_value * 3.3f / 4095.0f;

// 电压 → NTC电阻(下分压电路)
float r_ntc = (3.3f - voltage) * 10000.0f / voltage;

// NTC电阻 → 温度(B值公式)
float temp = 1.0f / (logf(r_ntc / 10000.0f) / 3950.0f + 1.0f / 298.15f) - 273.15f;

验证标准

  • 串口每秒打印 "ADC: 2048, R: 10000, Temp: 25.0°C"

  • 用手捏NTC → 温度上升2-5°C

  • 用冰水混合物(≈0°C)校准:误差 < ±2°C

  • 用手边的温度计(水银/电子均可)做对比验证

  • 你能从头推导一遍:给定ADC值 → 算出温度


第五步:定时器PWM ------ 让呼吸灯会呼吸

目标

理解定时器、PWM原理、频率和占空比计算。

硬件连接

复制代码
PA0 (TIM2_CH1) ──→ [220Ω] ──→ LED ──→ GND

PWM原理

复制代码
ARR (自动重载) = 周期
CCR (比较值)   = 占空比

         ┌──────┐        ┌──────┐
输出     │  ON  │  OFF   │  ON  │
         ┘      └────────┘      └────
         ← CCR →← ARR-CCR →
         ←────── ARR ──────────→

频率 = 定时器时钟 / (PSC+1) / (ARR+1)
占空比 = CCR / ARR

AI对话例

复制代码
你: "TIM2_CH1, PA0,72MHz,输出1kHz PWM,占空比呼吸效果:0→100%→0,步进1%,每步10ms"

AI: [生成TIM2 PWM配置 + 呼吸灯代码]

你: "72M/(71+1)/(999+1)=1kHz,这71和999怎么来的?为什么PSC和ARR要+1?"
你: "如果我要100Hz呢?改哪个参数?"
你: "CCR=500在ARR=999时,占空比是多少?"

验证标准

  • LED呈现平滑呼吸效果(不是频闪)

  • 用逻辑分析仪/示波器看PA0波形,验证频率=1kHz

  • 占空比=50%时,波形高电平时间=0.5ms(用示波器验证)

  • 你能在白板上画出:72MHz → 预分频 → 1MHz → ARR=999 → 1kHz 这条计算链


第六步:I2C OLED ------ 给芯片配一个显示器

目标

掌握I2C通信协议,理解从机地址、开漏输出、ACK机制。

硬件连接

复制代码
STM32                    OLED (SSD1306)
PB6 (I2C1_SCL) ──────── SCL
PB7 (I2C1_SDA) ──────── SDA
3.3V          ──────── VCC
GND           ──────── GND

SCL和SDA各接4.7KΩ上拉电阻到3.3V(部分模块已内置)

I2C协议速览

复制代码
起始: SDA在SCL高电平时从高→低
数据: SCL低时SDA变化, SCL高时SDA稳定
应答: 第9个SCL脉冲, 从机拉低SDA = ACK
停止: SDA在SCL高电平时从低→高

帧格式: [起始] [从机地址+R/W] [ACK] [寄存器地址] [ACK] [数据] [ACK] ... [停止]
SSD1306地址: 0x3C (7bit) → 0x78 (写) / 0x79 (读)

AI对话例

复制代码
你: "帮我写一个SSD1306 I2C OLED驱动,只需要三个功能:清屏、写字符串(5x7字体)、画矩形。用STM32 HAL库I2C1"

AI: [生成完整驱动]

你: "为什么要用开漏输出而不是推挽?上拉电阻的作用是什么?"

你: "如果我没接上拉电阻,I2C会怎样?帮我用示波器看看波形就知道了。"

你: "I2C的ACK是什么意思?如果从机不应答,代码怎么处理?"

验证标准

  • 屏幕显示 "Hello Embedded!"

  • 显示第4步的实时温度:"Temp: 25.3C"

  • 用逻辑分析仪抓到I2C波形,识别出:起始条件 → 0x78 → ACK → 数据字节 → 停止条件

  • 你能画出 I2C 写一个字节的完整时序图(SCL + SDA)


第七步:按键交互 ------ 设定你的目标温度

目标

状态机编程、人机交互设计、SysTick定时器。

硬件连接

复制代码
PB0 (SET)  ── [按钮] ── GND   (启用内部上拉)
PB1 (UP)   ── [按钮] ── GND
PB10(DOWN) ── [按钮] ── GND

按键逻辑

复制代码
状态机:

[正常模式] ───SET按下───→ [设定模式,数字闪烁]
                              │
              UP/DOWN ←───────┤ 目标温度 ±1
                              │
              5秒无操作或再按SET ──→ [正常模式]

AI对话例

复制代码
你: "设计一个三按键温度设定UI:SET键切换模式,UP/DOWN调节目标温度30-80°C。设定模式下数字闪烁,5秒超时退出。非阻塞实现,用状态机。"

AI: [生成按键状态机代码]

你: "这个状态机有哪些状态?每个状态之间转移的条件是什么?"

你: "为什么不用while(HAL_GPIO_ReadPin(...))这种阻塞方式?阻塞会带来什么问题?"

验证标准

  • OLED显示两行:当前温度(大字) + 目标温度(如 "SV: 55C")

  • 按SET进入设定,目标温度数字闪烁(500ms周期)

  • UP/DOWN调整目标温度,范围30-80°C

  • 再按SET 或 5秒超时退出设定

  • 串口打印每次设定变更:"Setpoint: 55°C"

  • 按键响应不阻塞温度读取和显示更新


第八步:PWM功率驱动 ------ 让加热片热起来

目标

PWM控制大电流负载,掌握MOSFET开关应用。

硬件连接

复制代码
PA6 (TIM3_CH1) ── [1KΩ] ──┬── MOSFET Gate (IRLZ44N)
                            │
                            │   IRLZ44N 引脚:
+5V电源 ── [加热片] ────── MOSFET Drain (中间脚)
                            │
                            MOSFET Source (右脚) ── GND

续流保护:
  二极管(1N5819)反向并联加热片(阴极接+5V,阳极接Drain)

为什么用IRLZ44N? 它是"逻辑电平"MOSFET,3.3V就能完全导通。普通MOSFET需要10V栅极电压,用3.3V驱动会半开半闭(发热严重)。

栅极电阻1KΩ:限制充放电电流,防止PWM边沿过冲振荡。

续流二极管:加热片是感性负载,关断时会产生反向高压,二极管提供续流回路。

AI对话例

复制代码
你: "TIM3_CH1, PA6, 1kHz PWM输出控制加热片。占空比0-100%对应0-100%功率。同时把当前PWM值显示在OLED上。"

你: "为什么MOSFET栅极要串1KΩ电阻?不串会怎样?"
你: "为什么选IRLZ44N而不是IRF540N?逻辑电平MOSFET和普通MOSFET的区别是什么?"
你: "二极管为什么要反并联在加热片上?这个二极管叫什么名字?"

验证标准

  • 占空比0% → 加热片不发热

  • 占空比50% → 温热(用NTC贴在加热片上验证温度)

  • 占空比100% → 明显发热

  • 用手摸MOSFET------不烫。烫 = 栅极驱动电压不足,工作在放大区

  • 串口打印:占空比(%) + NTC温度 + 对应关系合理

  • 示波器看PA6波形和MOSFET Drain波形一致(PWM正常)


第九步:PID闭环控制 ------ 让温度自动停在你设定的值

目标

理解反馈控制原理、PID三参数的作用、闭环vs开环。

控制原理

复制代码
                          ┌──────────┐
目标温度(SV) ──→(+)──→   PID控制器   ──→ PWM ──→ 加热片 ──→ 实际温度(PV)
                ↑ -                                    │
                │                                       │
                └─────────── NTC反馈 ───────────────────┘

误差 e = SV - PV
当 e>0 (温度不够) → 加大PWM → 加热
当 e<0 (温度过高) → 减小PWM → 自然冷却
当 e≈0 (温度正好) → PWM维持稳态

PID公式

复制代码
Output = Kp × e  +  Ki × Σe  +  Kd × (e - e_prev)

P项(比例): 现在差多少?    → 快速响应
I项(积分): 累积差了多少?   → 消除稳态误差
D项(微分): 变化有多快?    → 抑制超调, 预测趋势

调参直觉:
  P太大 → 震荡         P太小 → 响应慢, 到不了目标
  I太大 → 超调严重     I太小 → 有稳态误差(差几度停不下来)
  D太大 → 噪声敏感     D太小 → 超调抑制不住

AI对话例

复制代码
你: "帮我实现一个位置式PID控制器。输入:当前温度、目标温度;输出:PWM占空比0-100%。每秒调用一次。参数要可调。"

AI: [生成PID实现]

你: "我的温度一直震荡,帮我分析是哪个参数的问题?给出调参方向。"

你: "积分饱和是什么?我的代码里怎么防止积分饱和?"

你: "为什么控制周期(1秒)很重要?太快或太慢会有什么问题?"

PID代码骨架(AI生成,你审查)

复制代码
typedef struct {
    float kp, ki, kd;      // PID三参数
    float setpoint;         // 目标温度
    float integral;         // 积分累积
    float prev_error;       // 上一次误差(D项用)
    float integral_limit;   // 积分限幅(防饱和)
    float output_limit;     // 输出限幅(0-100)
} PID_Controller;

float PID_Compute(PID_Controller *pid, float current_temp) {
    float error = pid->setpoint - current_temp;

    // P 项
    float p_term = pid->kp * error;

    // I 项 (带限幅)
    pid->integral += error;
    if (pid->integral > pid->integral_limit) 
        pid->integral = pid->integral_limit;
    if (pid->integral < -pid->integral_limit)
        pid->integral = -pid->integral_limit;
    float i_term = pid->ki * pid->integral;

    // D 项
    float d_term = pid->kd * (error - pid->prev_error);
    pid->prev_error = error;

    // 合并且限幅
    float output = p_term + i_term + d_term;
    if (output > pid->output_limit) output = pid->output_limit;
    if (output < 0) output = 0;

    return output;
}

调参实操(最重要的学习环节)

复制代码
初始值: Kp=5.0, Ki=0.1, Kd=1.0

步骤1: 先只调P(Ki=0, Kd=0)
  加大Kp直到出现轻微震荡 → 取震荡Kp的60-70%

步骤2: 加I(消除稳态误差)
  小幅增加Ki → 温度能稳定到目标了

步骤3: 加D(抑制超调)
  增加Kd → 升温更快但不超调

把串口数据导出来画曲线!
  - 横轴时间, 纵轴温度
  - 观察: 上升时间、超调量、稳定时间、稳态误差

验证标准

  • 设定55°C,从室温25°C加热,最终稳定在55±1°C

  • 串口每秒打印:T:25.3 SV:55.0 Err:29.7 PID:72.5 PWM:72

  • 导出串口数据,用Excel/Python画出温度曲线

  • 改变设定值(如55→45),观察系统跟踪新目标

  • 用手摸加热片(模拟扰动如加冷水杯)→ 系统自动加大功率恢复

  • 你能解释:为什么纯P控制(Ki=0, Kd=0)永远到不了目标?积分的作用是什么?

  • 调Kp到很大,观察震荡 → 理解"比例带"


第十步:系统集成 ------ 从demo到产品

目标

整合所有模块、处理异常情况、打磨用户体验。

集成架构

复制代码
int main(void) {
    HAL_Init();           // HAL库初始化
    SystemClock_Config();  // 时钟配置
    GPIO_Init();          // 按键、LED
    ADC_Init();           // 温度传感器
    PWM_Init();           // 加热控制
    UART_Init();          // 调试串口
    OLED_Init();          // 显示屏
    PID_Init(&pid);       // PID控制器

    OLED_ShowLogo();      // 开机Logo
    HAL_Delay(2000);

    while (1) {
        // 每1秒执行一次控制循环
        if (HAL_GetTick() - last_tick >= 1000) {
            last_tick = HAL_GetTick();

            float temp = Read_Temperature();       // ADC+NTC
            float pwm = PID_Compute(&pid, temp);   // PID计算
            Set_PWM(pwm);                          // 更新加热
            OLED_Update(temp, pid.setpoint, pwm);  // 刷新显示
            Debug_Print(temp, pid.setpoint, pwm);  // 串口输出

            Safety_Check(temp);                    // 安全检查
        }

        Key_Scan();  // 按键扫描(非阻塞, 每循环都跑)
    }
}

异常处理

异常 检测方式 处理
NTC开路 ADC值≈4095(接近VCC) 停止加热,OLED显示"ERR NTC"
NTC短路 ADC值≈0 停止加热,OLED显示"ERR NTC"
过热保护 温度 > 85°C 强制PWM=0,OLED显示"OVERHEAT!"
加热超时 加热30分钟温度不升 停止加热,报警
系统跑飞 看门狗未按时喂狗 自动复位

看门狗配置(AI生成)

复制代码
你: "STM32F103配置独立看门狗IWDG,喂狗周期1秒,在main循环里喂狗。如果主循环卡死超过1秒,自动复位。"

AI: [生成IWDG配置代码]

最终验收标准

功能验收:

  • 上电 → OLED显示Logo 2秒 → 进入主界面

  • 主界面:当前温度(大字) + 目标温度 + 加热功率条

  • 三个按键操作流畅、响应即时、不卡屏

  • 恒温精度:稳态 ±1°C

  • 从室温到55°C升温时间记录在案

  • 串口每秒输出完整数据行

安全验收:

  • 拔掉NTC → 显示 "ERR" + 停止加热

  • 温度 > 85°C → 强制停止加热

  • 连续运行 1 小时不崩溃

  • 拔掉电源再插 → 正常运行

理解验收(对AI或面试官):

  • 画出系统框图,标出所有数据流

  • 说出每个外设用了MCU的什么模块

  • 解释PID为什么能让温度稳定

  • 说出至少3个可能导致事故的硬件故障,以及你的代码如何应对


AI协作黄金法则

✅ AI擅长的(放心用):

  • 生成外设初始化代码(GPIO、UART、ADC、PWM、I2C 等)

  • 生成驱动框架(SSD1306 OLED、NTC温度换算、PID控制器)

  • 解释你不懂的概念("volatile是干什么的?")

  • 分析bug(粘贴异常日志/现象)

  • 提出优化建议("这段代码有什么问题?")

  • 对比技术方案("中断 vs 轮询,什么时候用哪个?")

相关推荐
菜鸡儿齐5 小时前
编程模型学习记录
学习
乔江seven5 小时前
【Python补漏】1 基础
学习
efangfd5 小时前
TXS0104 和 TXB0104 的 IO 驱动电流对比
单片机·嵌入式硬件
怪祝浙6 小时前
AI学习-LangChain实战-多模态识别agent
人工智能·学习·langchain
逆境不可逃6 小时前
Hello-Agents 第二部分-第六章:框架开发实践
java·人工智能·分布式·学习·架构·rabbitmq
YangYang9YangYan6 小时前
2026学习数据分析对产品经理的价值
学习·数据分析·产品经理
淞綰6 小时前
c语言的练习-字符串的练习-寻找最长连续字符以及出现次数
c语言·数据结构·学习·算法·c语言的练习
玄米乌龙茶1236 小时前
项目开发学习笔记
笔记·学习
gihigo19986 小时前
STM32F407 Modbus RTU主站例程
stm32·单片机·嵌入式硬件