51 单片机单文件多文件结构工程模板的创建教程

        本章将详细介绍KEIL C51软件的使用方法及51单片机工程的创建流程。通过本章学习,掌握建立51单片机工程模板的技能,为后续51 单片机编程学习奠定基础。

单文件与多文件结构对比

对比项单文件结构多文件结构
项目规模小项目、实验项目中大型项目、正式开发
可读性初期好,后期差良好,结构清晰
维护性改一个容易牵一发而动全身模块独立,维护方便
可移植性极差模块可复用,易于移植
学习曲线入门简单需要理解模块化设计

单文件结构工程模板的创建

        在嵌入式开发中,仅包含一个 main.c 文件的工程通常称为"单文件结构"(Single File Structure)或单文件工程。这是最基础、最简化的项目组织形式,特别适合学习阶段或小型测试项目。

单文件结构定义

        单文件结构是指将所有代码(包括主函数、外设控制、逻辑处理、宏定义、变量声明和延时函数等)集中编写在一个.c文件中,通常命名为main.c。

适用场景

  • 初学者练习:刚接触Keil C51时,推荐使用单文件练习LED控制、按键检测和延时等基础功能
  • 简单演示:适合开发小型demo,不建议堆砌过多功能
  • 过渡学习:掌握基本语法后,应及时转向模块化开发方式

典型工程结构

创建流程

1、新建工程

        在电脑上任意位置新建一个名为"51 单片机工程模板创建"的文件夹。接着打开KEIL C51软件,新建一个工程。建议使用英文命名工程文件(如template),避免使用中文名称可能导致的异常问题。将新建的工程直接保存在之前创建的"51 单片机工程模板创建"文件夹中。具体操作步骤如下:

2、选择 CPU 型号

        这个根据你所使用的开发板上使用的CPU型号选择对应芯片,我的开发板(普中A7)采用的是STC89C52芯片。在 KEIL C51 软件内找不到这种型号的单片机选项,但因为 51 内核单片机具有通用性,所以在这里可以任选一款89C52 进行开发。Keil软件的关键在于程序代码编写,硬件选择并非重点。本文以Atmel的89C52为例示范,具体操作步骤如下:

        点击 OK 键后,弹出如下对话框:

        该对话框提示是否要将8051启动文件添加到工程中。选择"否",因为KEIL C51已自动处理了启动过程,只需编写应用程序代码即可。选择"否"后的界面如下:

3、给工程添加文件

        选择“File->New...”或点击工具栏的图标新建一个文件后点击保存。保存时系统会自动跳转到工程目录,直接在文件名栏输入新文件名即可。请注意:51单片机工程必须包含且仅有一个 main 函数,因此建议将文件命名为 main.c(也可按个人习惯使用其他英文名称)。保存操作步骤如下:

        将新建的 main.c 文件添加到工程中,具体操作步骤如下:

  1. 右键点击工程组"Source Group1"
  2. 选择"Add Files to Group 'Source Group 1'..."
  3. 在弹出的窗口中选中对应的 xxx.c 文件
  4. 依次点击"Add"和"Close"按钮

        完成上述操作后,文件将显示在工程列表中。

4、配置魔术棒选项卡

        这一步的配置非常关键,许多用户在自行编译程序时遇到找不到.HEX文件的问题,或者使用51仿真器时出现仿真失败的情况,往往都是由于配置不当造成的。具体配置步骤如下:

        配置Output 选项。选择魔术棒工具的 Output 选项卡,勾选红色框3,即程序编译成功后会产生 HEX 文件。具体操作如下:

        51 仿真器配置(仅针对有仿真器的同学去配置)。当你购买了 51 仿真器,且你的仿真器已经安装好驱动,且已经连接好了电脑和开发板,便可开始配置工作。先安装安装51 仿真器,步骤如下:

  1. 将51仿真器插入单片机卡座
  2. 连接电脑端USB接口,此时仿真器会同时为开发板供电,因此无需额外连接电源线

        如果想要使用51仿真器进行在线程序调试,需在KEIL软件中进行相应配置,具体的配置如下(注意:以下配置基于普中51仿真器已连接开发板的情况):

        点击OK确认设置。完成以上图中 1 到 10 步的设置后,即可开始在线仿真调试了。双击工程组中的main.c文件,输入以下代码:

#include "reg52.h"
void main() {while(1) {}
}

        编译结果显示0错误0警告,说明51单片机工程创建完全正确,如下所示:

补充:上图红色方框 1 中三个按钮都可以对代码编译,但其功能不同:

  • 第一个:它是编译当前界面所在的一个 C 文件。
  • 第二个:联合编译整个工程,发生修改的文件重新编译,并生成可执行文件。
  • 第三个:联合编译整个工程,所有文件都重新编译,并生成可执行文件。

        从上面说明可以看出,一般情况下,我们不使用第三个编译按钮,第二个最常用。因为第三个每次都把所有的文件都重新编译,需要消耗大量的时间。当工程比较小的时候,感觉不到,但是工程较大的时候就不行了。

多文件结构工程模板的创建

        在嵌入式 C(以 Keil C51 为代表)开发中,很多初学者常常将所有代码写在 main.c 文件中,比如 LED 控制、按键扫描、数码管显示、定时器中断、串口通信等等。这种方式虽然简单直观,但一旦项目稍微复杂起来,就会陷入“代码越来越长、维护越来越难”的泥潭。

        为了解决这个问题,我们通常采用 “多文件工程结构Multi-file Structure来组织代码,也称为模块化设计,多文件结构通过将各个功能模块的代码独立存放,形成清晰的工程目录层级,以提高代码的可读性、可维护性与可移植性。

        下面将详细介绍如何在 Keil 项目中构建一套标准的多文件结构,并结合实际案例(本文以I2C-EEPROM 实验 为例)讲解其优点和实现方法。

多文件结构定义

        多文件结构是指将工程代码按功能或职责进行划分,分别存放在多个 .c 源文件和 .h 头文件中,常见模块包括主函数、外设驱动、公共函数、类型定义等,并通过模块化接口进行调用。每个功能模块通常拥有自己独立的一对 .c/.h 文件,主函数只负责调用这些模块接口。

适用场景

  • 项目逐渐复杂:适合功能较多的中大型嵌入式工程,如包含 LED、按键、数码管、串口通信、定时器等多个模块。
  • 团队协作开发:多人分模块协同开发时,模块隔离便于分工、测试和集成。
  • 功能复用需求:通用模块如延时函数、I2C 驱动等可直接在多个项目中重用。
  • 工程化管理:代码清晰、结构合理,方便调试、维护、版本控制及文档生成。
  • 向更高层次开发过渡:为后续学习 STM32、RTOS、裸机+模块化架构打下良好基础。

典型工程结构

        一个规范的 Keil 多文件项目结构大致如下:

        具体示例:I2C-EEPROM 实验项目源代码结构如下所示: 

创建流程

1、创建多文件工程

        首先在电脑上创建一个名为"I2C-EEPROM"的文件夹(与教程保持一致),然后在该文件夹内新建以下四个子目录:

  • App 文件夹:存放外设驱动程序,如LED、数码管、定时器等模块
  • Obj 文件夹:存放编译生成的文件,包括c/汇编/链接的列表清单、调试信息、hex文件等
  • Public 文件夹:存放51单片机公共文件,如延时函数、头文件、类型定义等
  • User 文件夹:存放用户主函数文件main.c

        采用这种多文件管理方式的原因在于:本章实验需要用到独立按键、数码管、EEPROM等多个功能模块。如果将所有代码都写在main.c中,会导致文件过于冗长,严重影响代码的可读性和可维护性。通过合理的目录划分,可以显著提升工程的组织性和可移植性。操作方法如下:

2、新建工程

        打开 KEIL 软件,新建一个工程,建议使用英文命名工程文件(如template),避免使用中文名称可能导致的异常问题,并保存在“I2C-EEPROM ”文件夹下,然后选择芯片类型为“AT89C52”,注意不要勾选系统创建启动文件的选项。具体操作如下图所示:

        上述操作与前面介绍的创建工程模板是一样的,下面才开始在工程中进行分组管理。

3、向工程添加文件

        按照需要将工程文件分组并添加相应文件。这里我们将工程分为3组:User、App和Public。建议 “KEIL 中的工程组的命名(User、App、Public)” 与 “电脑硬盘上源文件中的文件夹名称” 保持一致,便于快速定位文件位置。分组操作如下:

        分组后,在KEIL -> Project 框中就会出现刚才的分组列表,与电脑硬盘上源文件中的文件夹名称保持一致,如下所示:

        至于Obj文件夹则无需在工程中显示,因为它仅包含编译器生成的中间文件和.hex可执行文件,如下所示:

        然后就是给每个组新建对应的.c /.h 源文件,如下所示:

        在 App 文件夹中可以发现,驱动文件按外设类型分别存放在对应的子文件夹中,这种组织方式极大提升了程序的可移植性和可维护性。

        通常,在以文件形式存放对应功能的驱动程序时,会创建两个文件:一个.c 源文件用于存放外设驱动程序(如按键检测函数),另一个.h 头文件则用于定义管脚、声明变量和函数等。以 key.c 为例,其对应的头文件是 key.h。key.c 源文件会首先调用与其对应的头文件key.h,这样就能在源文件中直接使用头文件定义的内容。

        接着,需要在KEIL 中将新建的文件添加到之前新建的工程分组中,如下所示:

        也可以直接鼠标左键双击需要添加的.c 文件(红色标记 5)完成添加操作,从而免去了点击红色标记 6 这步。添加成功后,右侧区域Files会显示对应组中已添加的文件,如下图所示:

        同样的方法,将 App、Public 工程组中的文件也添加进去。如下所示:

        此时可以看到,在工程栏下每组都已经加入了刚才添加的源文件,如下所示:

        如果有遗漏的文件未添加,可按上述方法重新添加。此时若直接编译工程会出现大量错误,因为在KEIL中尚未指定头文件路径。

4、配置魔术棒选项卡

        这一步的配置至关重要。常见问题如编译后未生成HEX文件或编译报错找不到头文件,往往源于此处配置不当:
        在Output选项 中,将输出文件夹定位到源文件目录 I2C-EEPROM 下的Obj文件夹。如需生成hex文件,请勾选Create HEX File选项。具体配置如下:

        Listing 选项 中把输出文件夹也定位到我们实验目录下的Obj 文件夹。其它设置默认,配置如下:

        C51 选项 配置,此处目的是将我们前面添加到工程组中的文件路径包括进来,否则程序中调用其他文件夹的头文件则会报错找不到头文件路径,具体步骤如下:

        添加的头文件路径是指,在 I2C-EEPROM 实验文件夹下里面,哪些文件夹内含有.h 头文件,并且需要被调用到的,通常会把只要含有头文件的文件夹都选择进去。比如本例程中 App 内含有很多子文件夹,它们里面都含有头文件,因此要分别添加,Public 也含有头文件,所以也要添加。添加完成后如下:

5、 51 仿真器配置

        51 仿真器配置和上一节相关内容一致,此处不再重复。最后编译一下工程,编译后结果: 0 错误 0 警告,表明创建的多文件工程没有问题。如下:

        至此,我们就成功创建好一个多文件工程模板。凡是涉及到多个外设资源模块的都可以使用该工程模板的方法整理项目代码,尤其是对重复利用已编写过的外设驱动。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/91111.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/91111.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Git】实用Git操作指南:从入门到高效协作

目录 1. Git 工作流程图 2. 基本配置 3. 获取本地仓库 4. 基础操作 5. 分支 6. Git远程仓库 6.1 常用的托管服务[远程仓库] 6.2 注册码云 6.3创建远程仓库 6.4 配置SSH公钥 6.5 操作远程仓库 7. 在IDEA中使用Git 附:铁令 下载地址:Git - Downloads 安装&…

InstructBLIP:通过指令微调迈向通用视觉-语言模型

温馨提示: 本篇文章已同步至"AI专题精讲" InstructBLIP:通过指令微调迈向通用视觉-语言模型 摘要 大规模预训练和指令微调在构建通用语言模型方面取得了显著成功。然而,构建通用视觉-语言模型仍然面临挑战,这主要源于…

[python][flask]flask蓝图使用方法

在 Flask 中,蓝图(Blueprint)是一种用于组织和管理代码的机制,可以将应用分解为多个模块,每个模块专注于特定的功能。以下是使用蓝图的基本步骤和方法:1. 创建蓝图首先,需要创建一个蓝图对象。蓝…

学习dify:一个开源的 LLM 应用开发平台

Dify 是一个开源的 LLM 应用开发平台。其直观的界面结合了 AI 工作流、RAG 管道、Agent、模型管理、可观测性功能等,让您可以快速从原型到生产。以下是其核心功能列表: 1. 工作流: 在画布上构建和测试功能强大的 AI 工作流程,利用以下所有…

VEX实现物体沿线条流动

1. 效果如下:float offset fit01(rand(ptnum654),0.5,1)*Time*chf("speed") rand(ptnum547);int num nprimitives(1); vector pos primuv(1,"P",ptnum%num,offset%1);P pos;2.效果如下: float min detail(1,"min");…

puppeteer 系列模块的系统性、详细讲解

puppeteer 系列模块的系统性、详细讲解 🧩 一、核心模块介绍 1. puppeteer全功能 Puppeteer 包,默认包含 Chromium 浏览器npm install puppeteer包含内容:Puppeteer API Chromium 浏览器适合场景: 想直接运行,不关心浏…

golang实现一个规则引擎,功能包括实时增加、修改、删除规则

以下是一个用 Go 实现的轻量级规则引擎,支持实时增加、修改、删除规则,并基于表达式评估触发规则动作: package mainimport ("errors""fmt""sync" )// Rule 定义规则结构体 type Rule struct {ID string // 规则唯一标…

算法训练营day34 动态规划② 62.不同路径、63. 不同路径 II、343整数拆分、96.不同的二叉搜索树

动态规划的第二篇博客!进阶题目,有一说一,尤其最后一道题,真的难想到这种解法 找规律!!! 62.不同路径 注意本题是路径不是路程!!! 动态规划 确定dp数组&am…

Spring 5 事务详解

一、核心使用方式声明式事务(推荐)通过 Transactional 注解实现,需配合配置启用:Configuration EnableTransactionManagement public class AppConfig {Beanpublic PlatformTransactionManager txManager(DataSource dataSource) …

[ctfshow web入门]web99 in_array的弱比较漏洞

信息收集 array_push(array, value):向数组最后的位置插入value in_array(value, array, type):其中value是要查找的值,array是需要查找的的数组,type是查找的类型,如果没有指定类型,则以弱比较方式查找 i…

mysql5.6 常用查询sql

mysql5.6 常用查询sql 文章目录 mysql5.6 常用查询sql 1.查询版本 2.MySQL 运行状态(Ping) 3.慢查询数量 4.连接数 5.最大连接数 6.InnoDB 缓冲池命中率 7.表锁等待次数 8.二进制日志状态 9.表空间使用率 10.查询缓存效率 11.每次自动扩展空间大小 12.导入导出 ✅ 一、导出(…

【在Unity游戏开发中Dictionary、List介绍】

在Unity游戏开发中&#xff0c;Dictionary和List是最核心的两种数据结构&#xff0c;它们各自有优势和应用场景。以下是介绍&#xff1a;&#x1f9e0; 数据结构本质对比特性Dictionary<TKey, TValue>List底层结构哈希表&#xff08;Hash Table&#xff09;动态数组&…

windows平台计划任务批处理实现定时任务

无限循环加定时延时计划任务用户登录执行一次下文中300代表300秒执行一次第2,3,4行为vbs隐藏窗口C:\me\corn\test.batecho off if "%1""hide" goto CmdBegin start mshta vbscript:createobject("wscript.shell").run("""%~0&quo…

深入理解 TCP 协议:从原理到实践的技术解析

目录 一、TCP 协议的核心定位与特性 1.1 协议栈中的位置 1.2 五大核心特性 二、TCP 连接建立与终止的底层逻辑 2.1 三次握手&#xff08;连接建立&#xff09; 2.2 四次挥手&#xff08;连接终止&#xff09; 三、TCP 可靠传输的核心机制 3.1 序列号与确认机制 3.2 滑…

JAVA后端开发——“全量同步”和“增量同步”

“全量同步”和“增量同步”是数据处理、系统集成和数据库领域中两个基本概念。描述了两种截然不同的数据同步策略&#xff0c;理解它们的区别对于设计任何数据系统都至关重要。全量同步 核心思想&#xff1a;全部替换&#xff0c;一步到位。在技术上&#xff0c;全量同步通常意…

修改CentOS的SSH登录端口(22端口)

要修改CentOS系统的SSH服务默认端口(22端口)&#xff0c;请按照以下步骤操作&#xff1a; 备份SSH配置文件 sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak编辑SSH配置文件 sudo vi /etc/ssh/sshd_config查找并修改端口设置 找到以下行(大约在第13行左右)&#xff1a;…

python导包机制-更优方式

在学习某个大模型应用的后端时&#xff0c;发现&#xff1a; xxx |-----src |------\---modules |------\------\------b.py |-----app.py在app.py中可以使用src.modules.b来进行导入。之前我导入时是形如.modules.b这种形式&#xff08;前面有.&#xff09;&#xff0c;但是当…

检索召回率优化探究一:基于 LangChain 0.3集成 Milvus 2.5向量数据库构建的智能问答系统

背景 基于 LangChain 0.3集成 Milvus 2.5向量数据库构建的 NFRA&#xff08;National Financial Regulatory Administration&#xff0c;国家金融监督管理总局&#xff09;政策法规智能问答系统&#xff0c;第一个版本的检索召回率是 79.52%&#xff0c;尚未达到良好、甚至是优…

《整合Spring Cache:本地缓存、Redis与Caffeine对比实践》

&#x1f680; 整合Spring Cache&#xff1a;本地缓存、Redis与Caffeine对比实践 &#x1f4cc; 前言 在高并发、高性能的系统设计中&#xff0c;缓存始终扮演着不可替代的角色。Spring Cache 作为 Spring 框架原生提供的缓存抽象层&#xff0c;极大简化了缓存接入的复杂度。…