新学期伊始,不忘助力国产替代初心,手头没有试验箱,先用“擎天柱”带领大一同学,跟随冲哥视频,学用STC AI8051U 芯片讲义。
第四节,自动生成多文件项目代码,温习C/C++语言
本节课任务是学用AICube 自动生成程序,温习 c 语言变量作用域
一、更新STC 烧录工具和 USB 库,自动生成项目文件
1. 下载资料。STC 烧录工具最新版是 AiCube-ISP-V6.96C , USB 最新库文件是 20250716 版;
2. 更新更新keil 头文件。解压运行烧录工具( AiCube-ISP-V6.96C.exe ),按下图顺序操作找到 keil 安装目录( keil_v5 ),更新头文件。
3. 打开AiCube 自动生成项目代码。参考下图顺序,点击启动烧录工具 AiCube. 设置好单片机型号、项目名称、保存路径,这里项目类型设置为多代码文件项目。
点击确定后,勾选USB ,通用串行总线和 TIMER0 ,定时器 0 选相框, USB 库函数设置“与 printf 函数关联”为是。
定时器0 开启中断使能,如下图,点击自动生成代码按钮弹出提示项目创建成功提示,再点确定后会关联启动 keil 打开所生成的项目文件。
AiCube 自动生成的项目包含三个 c 文件和 usb 库,查看各个文件内容,发现大量注释,分门别类提示放置用户的变量、函数,包含头文件等等,点击编译,编译器提示 0 错误 0 警告。足见 AiCube 功能强大方便。在看代码时,遇到不清楚函数、变量等,可鼠标右键点击追溯函数、变量定义,具体操作参考下图。
二、温习验证c 语言变量生命周期
1. 移植AI8051U 实验箱多任务代码。个人觉得官方推荐的实验箱代码: 27- 通过定时器周期性调度任务综合例程相当好。先拷贝其中 Sources\src\Task.c 和 Sources\inc\Task.h 到 demo 项目相应目录下。对照我刚才 AiCube 自动生成的项目, Task.c 拷贝到 G:\STCproject\AI8051U_PROJECT\demo\Sources\ 目录下, Task.h 拷贝到 G:\STCproject\AI8051U_PROJECT\demo\Sources\inc 目录,下,路径可参考下图。
2. 将Task.c 添加到项目中。展开 demo ,鼠标右键点击 AiCube 添加现存文件 task.c ,参考下图操作。
3. 主函数添加代码。main.c 文件要在 13 行 #include "config.h" 下面添加一句, #include "Task.h" ,即包含了 Task.c 的头文件,在第 49 行“在此添加主函数中用户主循环代码”下一行添加任务处理回调函数 Task_Pro_Handler_Callback(); 备注: Task.c 任务函数功能请参考上一节课解析。
4. 添加任务函数和变量。task.c 文件添加一个数组变量 , 这里就拷贝 27- 通过定时器周期性调度任务综合例程 app_Display.c 文件的 t_dispiay[] 标准字库数组,定义一个用于验证变量 display_index ,再定义一个任务函数 Test_Demo() 驱动擎天柱 p2 端口 led 灯。 task.h 文件申明一下任务函数 Test_Demo() ; timer.c 文件第 13 行 #include "config.h" 下面添加一句, #include "Task.h" ;在第 61 行 下面添加一句任务标记回调函数:Task_Marks_Handler_Callback();
5. 烧录验证。编译烧录看到擎天柱LED 在闪烁,说明 task.c 文件 display_index 变量是全局变量,生命周期是程序运行到结束。
三、分析理解Keil 多文件项目中变量生命周期
在 C/C++语言中,变量的作用域和链接性是两个独立但相互关联的概念 。变量display_index 在 task.c 文件 中定义为全局变量,具有外部链接性,只要通过适当的声明 ,可以在程序的任何地方被访问 。
1. 作用域 (Scope):决定变量在源代码中可见的范围 。全局变量在文件顶层定义,作用域为整个文件 ,函数内部定义的变量作用域仅限于该函数内 。
2. 链接性 (Storage Class):决定变量在不同编译单元间的可见性 ,外部链接 (external linkage):默认情况下,未使用 static 关键字修饰的全局变量具有外部链接性,可在程序各处访问 。
3. 内部链接 internal linkage:使用 static 关键字修饰的全局变量仅在当前文件内可见 。
task.c 文件 中的全局变量 display_index 没有使用 static关键字修饰,因此它具有外部链接性。这使得即使 主函数main.c 文件未在头文件中声明 extern int display_index ,也能通过调用 task.c 文件中的函数 Test_Demo() 间接访问和修改 display_index 的值。因为函数 Test_Demo() 在定义时已经能够访问 task.c 文件中的全局变量 display_index ,且函数 Test_Demo() 的实现代码与 display_index 的存储位置已建立直接关联。
函数 Test_Demo() 作为 task.c 文件的接口,封装了对全局变量 display_index 的操作 。其核心机制在于函数封装作用 ,当 主函数main.c 文件调用 Test_Demo() 时,实际执行的是 task.c 文件中已绑定 display_index 变量 地址的函数代码。函数 Test_Demo() 的作用域包含 task.c 文件的所有全局变量,因此可以直接访问和修改 display_index 的值,无需额外声明。这种机制是 C/C++语言设计的基本特性之一,它允许通过函数封装实现对全局状态的修改,同时保持代码的模块化和可维护性。
附件内容:课件讲义、程序源代码、擎天柱验证视频
Your browser does not support video tags.