单片机代码烧录

Tutorial: 电子电路 Category: 嵌入式 Published: 2026-08-29 08:09:36 Views: 1 Likes: 0 Comments: 0

028.0.2 单片机代码烧录

#include "reg52.h"
#include <intrins.h>
 
sbit LED1 = P1^0;
sbit LED2 = P1^1;
sbit LED3 = P1^2;
sbit LED4 = P1^3;
 
void Delay1000ms()    //@11.0592MHz
{
  unsigned char data i, j, k;
 
  _nop_();
  i = 8;
  j = 1;
  k = 243;
  do
  {
     do
     {
       while (--k);
     } while (--j);
  } while (--i);
}
 
 
void main()
{
  while(1)
  {
     LED1 = 0;
     LED2 = 1;
     LED3 = 1;
     LED4 = 1; 
     Delay1000ms();
     
     LED1 = 1;
     LED2 = 0;
     LED3 = 1;
     LED4 = 1; 
     Delay1000ms(); 
     
     LED1 = 1;
     LED2 = 1;
     LED3 = 0;
     LED4 = 1; 
     Delay1000ms(); 
 
     LED1 = 1;
     LED2 = 1;
     LED3 = 1;
     LED4 = 0; 
     Delay1000ms(); 
  }
 
}

一、从源码到单片机运行的完整流程

  • 本节完成的工作可以概括为:main.c 源码 → Keil 编译和链接 → mcu51.hex → AIapp-ISP 下载 → STC89C52 单片机运行。
  • C 源码不能直接写入单片机。Keil C51 先把源码编译、链接为目标程序,再输出 Intel HEX 格式的 .hex 文件;烧写工具读取该文件,并通过串口把程序写入单片机的 Flash。
  • 本节使用的配套源码位于 2、51单片机部分/2、51单片机教学篇/代码/0template/main.c,完整代码列在主标题下方。
  • 本节的电路分析依据课程配套的 51开发板电路.pdf。阅读原理图时,不要按元件在纸面上的远近判断连接关系;应沿导线和同名网络标号追踪电源、地及信号。

二、新建并组织 Keil 工程

2.1 建立文件夹层级

  • 先建立一个总的“代码”文件夹,用于保存后续所有课程工程。每个独立实验再使用一个子文件夹,避免不同工程的源文件、配置和编译产物互相混杂。
  • 本节把第一个工程作为模板工程,子文件夹命名为 0template;后续可以按照学习顺序建立 LED、中断、定时器、串口等不同工程目录。
  • 工程名称可以自定义,视频中使用 mcu51。一个清晰的目录结构示例如下:
代码/
└─ 0template/
   ├─ mcu51.uvproj
   ├─ main.c
   ├─ STARTUP.A51
   └─ Objects/
      └─ mcu51.hex

2.2 创建工程

  1. 启动 Keil μVision5,选择 Project → New μVision Project
  2. 进入总的代码目录,在其中新建并打开 0template 文件夹。
  3. 输入工程名 mcu51,单击“保存”。Keil 会把工程文件保存在当前子文件夹中。
  4. 创建其他实验工程时,应为每个工程建立自己的子文件夹,不要把所有工程直接保存在同一目录。

三、选择目标器件并添加 C 文件

3.1 选择 AT89C52

  1. 在器件选择窗口中展开厂商 Atmel
  2. 找到并选择 AT89C52,然后单击 OK
  3. Keil 询问是否把标准 8051 启动代码复制并加入工程时,选择“是”,工程中会出现 STARTUP.A51
  • 开发板实际使用的是 STC89C52RC/LE52RC 系列芯片,而 Keil 工程选择 AT89C52,是因为本节只使用标准 8051/52 内核兼容的寄存器和指令,AT89C52 的 C51 设备定义可以满足编译需要。
  • Keil 中的目标器件选择与烧写工具中的实际芯片选择含义不同:Keil 负责决定编译环境和寄存器定义;烧写时必须选择开发板上的真实芯片型号。若后续使用 STC 芯片特有外设,应改用与实际芯片匹配的头文件和配置,不能始终假定所有型号完全相同。
  • 只有启动文件的空工程在构建时可能出现警告。此时工程还没有 main 入口和用户代码,添加 main.c 后再重新检查构建结果。

3.2 添加 main.c

  1. 在工程树中右键单击 Source Group 1
  2. 选择 Add New Item to Group 'Source Group 1'
  3. 文件类型选择 C File (.c),名称输入 main.c,再单击 Add
  4. 将本节提供的模板源码粘贴到 main.c 中并保存。
  • 本工程使用的 C 源文件名是 main.c,它位于 Keil 工程的 Source Group 1 中。
  • 复制整段模板代码时,可以在原代码文档中按 Ctrl+A 全选、按 Ctrl+C 复制,再切换到 Keil 的 main.cCtrl+V 粘贴。

四、理解流水灯源码

4.1 头文件与引脚定义

  • #include "reg52.h" 提供 8051/52 系列的特殊功能寄存器定义,例如程序中使用的端口寄存器 P1
  • #include <intrins.h> 提供 Keil C51 的内部函数,本程序中的 _nop_() 表示执行一条空操作指令。
  • sbit LED1 = P1^0; 等语句把 LED1~LED4 分别映射到 P1.0~P1.3。sbitP1^0 是 Keil C51 针对 8051 位寻址功能提供的扩展语法,不是通用标准 C 的写法。

4.2 低电平点亮

  • 根据课程开发板的 LED 接线,端口输出低电平 0 时 LED 点亮,输出高电平 1 时 LED 熄灭,这称为“低电平有效”。
  • 第一组赋值令 LED1 = 0、其余 LED 为 1,因此只点亮 LED1;后面三组依次只点亮 LED2、LED3 和 LED4。
  • 原理图中的四路 LED 完全相同:LED1~LED4 的阳极接 +5V,阴极分别经过 R8~R11(均为 10 kΩ)连接到 P1.0~P1.3。以 LED1 为例,电流路径如下:
                  正向电流方向
                       ───────►
+5V ──────── LED1 ───── R8 10 kΩ ───── P1.0(单片机引脚)
                                                    │
                                             引脚输出 0 时
                                                    │
                                                   GND
  • P1.0 = 0 时,引脚电压接近 0 V,形成 +5V → LED1 → R8 → P1.0 → GND 的闭合回路,单片机引脚以“灌电流”的方式吸收电流,因此 LED1 点亮。

  • P1.0 = 1 时,引脚电压接近电源电压,LED 两端缺少足够的正向压差,回路中几乎没有电流,因此 LED1 熄灭。这就是代码中“写 0 反而点亮”的电路原因。

  • R8 是限流电阻,用于保护 LED 和单片机 I/O 口。它画在 LED 后面还是前面不影响作用,只要与 LED 串联,流过二者的电流就相同。忽略引脚低电平残余电压时,电流可近似计算为:

    I_LED ≈ (5V - V_F) / 10kΩ

    蓝色 LED 的正向压降 V_F 通常约为 2.8~3.2 V,因此本板 LED 电流大约为 0.18~0.22 mA。该电流较小,适合作为状态指示,也减轻了单片机端口的负担。

  • P1.0~P1.3 与四路 LED 的对应关系是一一固定的。软件中的 sbit 只是给物理引脚起了更容易理解的名字,并不会改变电路连接。

4.3 延时与循环

  • Delay1000ms() 是按 11.0592 MHz 晶振频率生成的软件延时函数,调用一次约延时 1000 ms,也就是 1 秒。若晶振频率或编译器优化设置发生变化,实际延时时间也可能变化。
  • main() 是单片机 C 程序进入用户逻辑后的主函数。Keil C51 接受源码中的 void main() 写法。
  • while(1) 构成无限循环,使 LED1~LED4 按顺序反复点亮,最终形成循环流水灯效果,而不是执行一遍后停止。
  • 原理图中的时钟电路由晶振 X1(11.0592 MHz)和两个 22 pF 负载电容 C9、C10 构成:
                         X1 11.0592 MHz
单片机 XTAL2 ───────────[   晶振   ]─────────── XTAL1 单片机
       │                                             │
     C9 22 pF                                     C10 22 pF
       │                                             │
      GND                                           GND
  • 晶振与单片机内部振荡放大电路共同产生稳定时钟。CPU 执行指令、定时器计数和软件延时都以该时钟为时间基准,所以 Delay1000ms() 的循环次数必须与 11.0592 MHz 相匹配。
  • 11.0592 MHz 还便于分频得到常见串口波特率,能够降低波特率误差。后续学习串口通信时,这个晶振频率会再次发挥作用。
  • 如果把开发板换成其他晶振频率而不重新计算延时,函数名称虽然仍叫 Delay1000ms(),实际延时却不再等于 1 秒;这说明函数名是人的约定,真正决定时间的是时钟频率和执行的指令周期数。

五、编译工程并检查结果

5.1 编译

  • 保存 main.c 后,可以使用工具栏的 Build 或 Rebuild 按钮构建工程。Build 主要编译发生变化的文件,Rebuild 会重新编译整个目标;对于本节的小工程,两者都能得到最终结果。
  • 在底部 Build Output 窗口查看结果:0 Error(s), 0 Warning(s) 表示本次构建没有错误和警告。
  • 出现 Error 表示编译或链接失败,必须根据错误位置修正;出现 Warning 时程序有时仍能生成,但也应理解原因并尽量消除,不能只看是否生成了文件。
  • Build Output 区域太小时,可以向上拖动窗口边界,方便查看完整信息。

5.2 生成 HEX 文件

  1. 单击工具栏中的“魔术棒”按钮,打开 Options for Target 'Target 1'
  2. 切换到 Output 选项卡。
  3. 勾选 Create HEX File,单击 OK 保存配置。
  4. 重新 Build 或 Rebuild 工程,Keil 才会按照新配置生成 HEX 文件。
  5. 打开工程目录下的 Objects 文件夹,检查是否出现 mcu51.hex。可以结合文件修改时间确认它是刚刚构建生成的版本。
  • 本节配套工程的默认输出目录是 Objects。如果修改过 Keil 输出路径,应以 Options for Target → Output 中配置的位置为准。
  • .hex 文件是供烧写工具读取的机器码文本,不是 C 源码。修改 main.c 后必须重新编译,否则烧写的仍可能是旧 HEX 文件。

六、连接开发板并烧写程序

6.1 硬件与串口准备

  1. 将 Type-C 数据线连接到开发板上靠近 CH340 USB 转串口芯片的接口,不要插错到另一个供电接口。
  2. 打开 Windows“设备管理器”,展开“端口(COM 和 LPT)”,找到名称中包含 USB-SERIAL CH340 的端口。
  3. 记下它的 COM 编号。视频中的电脑是 COM3,其他电脑可能显示为 COM6 或其他编号,应以自己的设备管理器为准。
  • 开发板有两个 Type-C 接口。原理图中标为“供电/下载USB”的 USBC1 同时连接 VBUS、D+ 和 D-,既能供电又能传输数据;标为“供电USB”的 USB1 只连接电源和地,不能把程序传给 CH340。因此烧写时必须使用“供电/下载USB”。
  • 从电脑到单片机的主要电源和信号路径如下:
电脑 USB
  │
  ├─ VBUS 5V ── C3 10µF / C4 100nF ── D1(SS34) ── VCC ── 单片机
  │
  ├─ D+、D- ── CH340N(USB 转串口)
  │               ├─ TXD ── D2(1N4148) ─────────► P3.0 / RXD
  │               └─ RXD ◄── R1(300Ω) ────────── P3.1 / TXD
  │
  └─ RTS# ── C7 47µF ── Q2(AO3400) ── 自动断开/接通板端地线
  • **供电部分:**USBC1 的 VBUS 是电脑提供的 5 V。C3(10 µF)用于缓冲较慢的电压波动,C4(100 nF)用于旁路高频噪声;大、小电容配合,使电源更稳定。D1 是 SS34 肖特基二极管,串在 VBUS 与 VCC 之间,可减少板端电源向 USB 口反向灌电的风险,同时其正向压降比普通硅二极管小。
  • **USB 转串口:**电脑发送的是 USB 数据,STC89C52 的下载接口使用 UART 串口,二者协议不同。CH340N 负责把 USB 数据转换成串口的 TX/RX 电平信号。串口必须交叉连接:发送端 TXD 接收对方的 RXD,接收端 RXD 接收对方的 TXD,所以 CH340 的 TXD 最终连接单片机 P3.0/RXD,而单片机 P3.1/TXD 连接 CH340 的 RXD。
  • **串联保护:**R1(300 Ω)限制串口线上可能出现的瞬时电流,D2(1N4148)在另一条数据路径上提供单向隔离,降低两端电平冲突或反向供电对通信的影响。
  • **自动下载:**原理图把 USB 侧地标为 GND_U,板端地标为 GND。Q2 是串在两个地之间的 AO3400 N 沟道 MOSFET,R2(10 kΩ)给栅极提供正常导通偏置;CH340 的 RTS# 状态变化通过 C7(47 µF)耦合到 Q2 栅极,使两个地短暂断开再接通。对单片机而言,这相当于一次快速掉电重启,从而让 STC 的 ISP 引导程序获得接收新程序的时机。
  • **为什么串口灯会闪:**原理图中的 LD2、LD3 分别接在 TX、RX 网络上。下载时 TX/RX 电平不断变化,相应指示灯闪烁,说明串口链路上正在传输数据;灯闪只能证明有活动,最终是否成功仍应以烧写软件提示为准。
  • **Type-C 线的实际限制:**从这份原理图看,两个 Type-C 接口的 CC1、CC2 没有画出 USB-C 受电设备通常使用的下拉识别电阻。因此该板主要按 USB-A 转 Type-C 数据线的使用场景设计,部分 Type-C 转 Type-C 线或充电器可能不主动供电。若连接后完全不亮、设备管理器也没有新设备,可优先换用支持数据传输的 USB-A 转 Type-C 线。
  • **板上电源关系:**电源开关 SW1 用于接通 VCC 与板上的 +5V 电源网络;LED 等外围电路使用 +5V。AMS1117-3.3 再把 +5V 转换为 +3.3V,供排针或外接模块使用。不要把 +3.3V+5V 直接短接。

6.2 配置 AIapp-ISP

  1. 双击课程配套的 【STC烧写工具】AIapp-ISP-v6.95A.exe
  2. 在“芯片型号”中选择 STC89C52RC/LE52RC。不能仅根据列表中的位置选择,因为不同软件版本的排列顺序可能变化,应核对完整型号文字。
  3. 在“扫描串口”处选择设备管理器中看到的 CH340 COM 端口。
  4. 单击“打开程序文件”,进入 0template/Objects,选择刚刚生成的 mcu51.hex。打开后可在软件底部核对文件路径。
  5. 单击“下载/编程”开始烧写。烧写过程中,开发板的串口指示灯会闪烁;软件提示操作成功后,程序即已写入单片机。

6.3 验证运行效果

  • 烧写成功后,开发板上的四个 LED 应按照 LED1、LED2、LED3、LED4 的顺序依次点亮,每个状态保持约 1 秒,然后循环执行。
  • 这个现象与源码中的四组端口赋值及每组后面的 Delay1000ms() 一一对应。通过修改 LED 顺序或延时时间并重新编译、烧写,可以进一步验证“源码—HEX—硬件现象”的关系。

七、烧写失败的排查顺序

  1. 确认 Type-C 线插在靠近 CH340 芯片的接口,并且数据线支持数据传输。
  2. 确认 CH340/CH341 驱动已安装,设备管理器中能够看到对应 COM 端口。
  3. 确认 AIapp-ISP 中选择的是本机实际 COM 号,而不是照抄视频中的 COM3
  4. 确认芯片型号为 STC89C52RC/LE52RC
  5. 确认载入的是当前工程最新生成的 Objects/mcu51.hex,可通过修改时间和软件底部路径判断。
  6. 单击“下载/编程”后,如果一直等待目标单片机,可按一下开发板复位键,使芯片重新进入启动阶段。
  7. 仍然失败时,重新插拔数据线后再次尝试,并观察串口指示灯是否闪烁。
  • 开发板的 RST 为高电平有效,手动复位电路如下:
             C8 100 nF
+5V ──────────||──────────┬──────── RST(单片机复位脚)
                          │
                        R4 10 kΩ
                          │
                         GND

+5V ────────── SW2(按下)───────── RST
  • 正常稳定运行时,R4 把 RST 拉到低电平,避免引脚悬空而误复位。刚上电的一瞬间,C8 会把 +5V 的电压变化耦合到 RST,形成一个短暂高脉冲,完成上电复位;随后 R4 将 RST 拉回低电平。
  • 按下 SW2 时,RST 被直接接到 +5V,单片机立即复位;松开后又被 R4 拉低并重新运行。复位不会擦除已经写入 Flash 的程序,只会让 CPU 从复位入口重新开始执行。
  • AIapp-ISP 等待下载时按一下复位键,是为了让 STC 芯片重新进入上电后的 ISP 检测阶段。它与前面 Q2 控制地线的“自动下载”电路目的相同,都是制造一次重新启动;一个由人工按键触发,另一个由 CH340 控制信号自动触发。

八、常见问题归纳

  • 思维导图中提供了常见问题网页。选中浏览器小图标,单击右键,再选择“打开链接”或“打开外部链接”(视频中使用右键菜单第二项)即可打开。
  • 归纳文档覆盖 51 单片机、STM32 和 RT-Thread 等课程中学员经常遇到的问题。
  • 与本节有关的内容包括:工程代码如何打包、串口驱动安装失败、不同电脑的 COM 号不一致、烧写软件配置、代码下载失败,以及如何新建 .c.h 文件。
  • 遇到问题时应先核对错误信息和上述关键配置,再查阅归纳文档。下一节将开始讲解 51 单片机的基本知识。