WEB
1
蓝桥杯国赛大模板搭建笔记
一、前言
- 适用人群:有编程基础,目标冲击蓝桥杯省赛、国赛的同学
- 核心价值:模块化封装工程利于后续嵌入式开发学习
- 校赛要求:掌握三大模板即可,无需强制掌握模块化封装
二、工程搭建步骤(共 12 步)
1. 创建工程文件夹(核心结构)
- 新建根文件夹「国赛大模板」
- 根目录下新增 2 个文件夹(缺一不可):
User:存放工程文件、main.c
Driver:存放底层驱动文件(如 Key、Seg 相关)
2. 使用 Keil5 新建工程
- 打开 Keil5,选择「Create New Project」
- 保存路径:
国赛大模板\User
- 工程名称:国赛大模板(保存类型默认 Project Files)
3. 配置工程「品」字工具栏
- 点击 Keil5 中「Manage Project Items」(工程项管理)
- 在「Groups」栏点击「Add Files」,新增「Driver」组(用于存放底层驱动)
- 确认当前目标为「国赛大模板」,点击「OK」
4. 魔术棒(Options for Target)配置(2 个关键配置)
配置 1:生成 Hex 文件
- 点击 Keil5 工具栏「魔术棒」图标
- 切换到「Output」选项卡
- 勾选「Create HEX File」(必须勾选,否则无法生成烧录文件)
- 点击「OK」
配置 2:添加头文件引用路径
- 魔术棒中切换到「C51」选项卡
- 点击「Include Paths」右侧的「…」(文件夹图标)
- 浏览并选中「国赛大模板 \Driver」文件夹,点击「确定」
- 点击「OK」保存配置
5. 新建 main.c 并编写主体框架
- 在「User」组内右键→「Add New Item」→选择「C Source File」
- 文件名:main.c,保存路径:
User文件夹
- 编写基础框架代码:
/*头文件声明区*/
#include <REGX52.H>
/*Main*/
void main()
{
while(1)
{
// 后续添加业务逻辑
}
}
6. 新建 Key 底层文件(Driver 文件夹)
- 打开 Keil5→「File」→「New」,新建 2 个空白文件
- 分别保存为:
- 文件名 1:Key.c,保存路径:
Driver文件夹
- 文件名 2:Key.h,保存路径:
Driver文件夹
- 保存类型均选择「All Files」
7. 编写 Key 底层代码
Key.c(按键底层实现)
#include <Key.h> // 底层.c文件必须引用自身.h文件
// 按键读取函数(检测P3_4~P3_7按键)
unsigned char Key_Read()
{
unsigned char temp = 0;
if(P3_4 == 0) temp = 1;
if(P3_5 == 0) temp = 2;
if(P3_6 == 0) temp = 3;
if(P3_7 == 0) temp = 4;
return temp;
}
Key.h(按键函数声明)
#include <REGX52.H> // 用到单片机寄存器,需引用51头文件
// 函数声明(结尾必须加分号)
unsigned char Key_Read();
8. 新建 Seg 底层文件(Driver 文件夹)
- 操作步骤同第 6 步,新建 2 个文件:
- Seg.c(数码管底层实现)
- Seg.h(数码管函数声明)
- 保存路径:
Driver文件夹
9. 编写 Seg 底层代码
Seg.c(数码管显示实现)
#include <Seg.h> // 引用自身头文件
// 数码管段码表(0~9)
unsigned char Seg_Dula[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};
// 数码管位选表(6个数码管)
unsigned char Seg_Wela[] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf};
// 数码管显示函数(wela:位选,dula:段码)
void Seg_Disp(unsigned char wela, unsigned char dula)
{
// 位选控制
P0 = 0x00; // 清空显示
P2_6 = 1;
P2_6 = 0;
// 段码控制
P0 = Seg_Wela[wela];
P2_7 = 1;
P2_7 = 0;
// 锁存显示
P0 = Seg_Dula[dula];
P2_6 = 1;
P2_6 = 0;
}
Seg.h(数码管函数声明)
#include <REGX52.H> // 引用51头文件
// 函数声明(结尾加分号)
void Seg_Disp(unsigned char wela, unsigned char dula);
10. 添加底层文件到工程
- 在 Keil5 左侧「Project」窗口,双击「Driver」组
- 弹出「Add Files to Group Driver」窗口,浏览到
Driver文件夹
- 选中「Key.c」和「Seg.c」(按住 Ctrl 全选)
- 点击「Add」→「Close」,完成添加
11. 测试工程框架正确性
- 点击 Keil5 工具栏「Build」(编译)按钮
- 查看底部「Build Output」:
- 显示「0 错误,2 警告」:工程创建正确
- 若有错误,检查文件路径、头文件引用、代码语法
12. 编写 main.c 完整国赛模板
/*头文件声明区*/
#include <REGX52.H>
#include <Key.h>
#include <Seg.h>
/*全局变量定义区*/
// 按键专用变量
unsigned char Key_Val, Key_Down, Key_Old;
unsigned char Key_Slow_Down; // 按键减速防抖
// 数码管专用变量
unsigned char Seg_Buf[6] = {10, 10, 10, 10, 10, 10}; // 显示数据缓存(10代表熄灭)
unsigned char Seg_Pos; // 扫描位置
unsigned int Seg_Slow_Down; // 数码管减速扫描
/*键盘处理函数(捕捉下降沿+防抖)*/
void Key_Proc()
{
if(Key_Slow_Down) return; // 启动防抖计时
Key_Slow_Down = 1;
/* 理解:当Key_Slow_Down被清零后,下一次执行Key_Proc时,不会触发return,(这中间隔了10ms,足以消抖)就能顺利执行Key_Val */
Key_Val = Key_Read(); // 实时读取键值
Key_Down = Key_Val & (Key_Old ^ Key_Val); // 捕捉按键下降沿
Key_Old = Key_Val; // 更新旧键值
}
/*数码管处理函数*/
void Seg_Proc()
{
if(Seg_Slow_Down) return;
Seg_Slow_Down = 1; // 启动扫描减速
// 此处可添加显示逻辑(如Seg_Buf赋值)
}
/*LED处理函数(可扩展)*/
void Led_Proc()
{
// 按需添加LED控制逻辑
}
/*定时器0初始化(1毫秒@12.000MHz)*/
void Timer0Init(void)
{
TMOD &= 0xF0; // 清除定时器0模式
TMOD |= 0x01; // 设置定时器0为模式1(16位自动重装)
TL0 = 0x18; // 定时初始值低位
TH0 = 0xFC; // 定时初始值高位
TF0 = 0; // 清除溢出标志
TR0 = 1; // 启动定时器0
ET0 = 1; // 使能定时器0中断
EA = 1; // 使能总中断
}
/*定时器0中断服务函数(处理减速计时+数码管扫描)*/
void Timer0Server() interrupt 1
{
TL0 = 0x18; // 重置定时初始值
TH0 = 0xFC;
// 按键防抖计时(10ms)
if(++Key_Slow_Down == 10) Key_Slow_Down = 0;
// 数码管扫描计时(500ms)
if(++Seg_Slow_Down == 500) Seg_Slow_Down = 0;
// 数码管循环扫描(6个位置)
Seg_Disp(Seg_Pos, Seg_Buf[Seg_Pos]);
if(++Seg_Pos == 6) Seg_Pos = 0;
}
/*主函数*/
void main()
{
Timer0Init(); // 初始化定时器0
while(1)
{
Key_Proc(); // 按键处理
Seg_Proc(); // 数码管处理
Led_Proc(); // LED处理
}
}
三、关键注意事项
- 文件夹结构:
User和Driver缺一不可,路径不能包含中文
- 头文件引用:
- 底层.c 文件必须引用自身.h 文件(如 Key.c→Key.h)
- 底层.h 文件若用到寄存器,需引用
REGX52.H
- 函数声明:.h 文件中函数声明结尾必须加分号
- 编译验证:0 错误 + 2 警告为正常(警告多为未使用变量,不影响功能)
- 熟练技巧:main.c 中的模板代码需多敲多练,形成肌肉记忆