一、代码模块化编写笔记
1. 模块化核心思想
将程序按功能拆分为独立的模块,每个模块负责特定功能,通过接口(函数声明)交互,降低代码耦合度,提高可维护性和复用性。
2. 模块划分原则
-
按功能划分:如示例中拆分为 “按键模块”(key.c/key.h)和 “数码管显示模块”(seg.c/seg.h),分别负责按键读取和数码管驱动。
-
单一职责:每个模块只做一件事(如 key 模块仅处理按键读取,不涉及显示逻辑)。
3. 模块文件组成(以 key 模块为例)
-
头文件(.h):声明模块对外暴露的接口(函数、全局变量),供其他模块调用。
示例(key.h):
#include "REGX52.h" unsigned char Key_Read(); // 声明按键读取函数,供外部调用 -
源文件(.c):实现头文件中声明的接口,包含模块内部逻辑(隐藏实现细节)。
示例(key.c):
#include "key.h" // 实现按键读取逻辑,具体引脚判断仅在模块内部可见 unsigned char Key_Read(){ unsigned char temp = 0; if(P2_4 == 0) temp = 1; if(P2_5 == 0) temp = 2; // ... 其他按键判断 return temp; }
4. 模块间交互规则
-
其他模块通过
#include "模块名.h"使用该模块的功能(如 main.c 通过#include "key.h"调用Key_Read())。 -
模块内部变量 / 函数(仅模块内使用)应声明为
static,避免外部访问(示例中未体现,可优化)。 -
全局变量需在头文件中声明(加
extern),源文件中定义(示例中 main.c 的全局变量为整个程序共享,未拆分到模块)。
5. 优势
-
可维护性:修改某功能只需改对应模块(如改按键引脚只需改 key.c)。
-
可复用性:模块可直接移植到其他项目(如 seg 模块可复用在其他需要数码管显示的程序)。
-
逻辑清晰:主程序(main.c)只需关注业务流程,无需关心硬件细节。
二、main.c 大模板笔记
示例 main.c 是典型的 51 单片机程序框架,核心是 “定时器中断 + 主循环” 结构,适用于需要定时刷新(如按键消抖、数码管动态扫描)的场景。
1. 结构组成
(1)头文件与全局变量定义
-
包含所需模块的头文件(
#include "key.h"、#include "seg.h")。 -
定义全局变量:存储系统状态(如按键值
Key_Val、数码管显示缓存Seg_Buf)、定时计数器(如Key_Slow用于按键消抖计时)。// 全局变量示例 unsigned char Key_Val, Key_Down, Key_Old; // 按键状态变量 unsigned char Seg_Slow; // 数码管刷新定时器(500ms) unsigned char Seg_Buf[]={10,10,10,10,10,10}; // 数码管显示缓存
(2)功能处理函数
按功能拆分的业务逻辑函数,在主循环中轮询调用:
-
Key_proc():处理按键逻辑(读取按键、判断按键按下事件)。 -
Seg_proc():处理数码管显示逻辑(更新显示缓存)。 -
Led_proc():预留 LED 处理函数(可扩展 LED 控制逻辑)。
(3)定时器初始化与中断服务
-
定时器初始化:配置定时器(如
Timer0Init()配置 1ms 定时,用于定时刷新)。 -
中断服务程序:定时触发(如 1ms 一次),处理周期性任务:
-
计时(
Key_Slow、Seg_Slow计数,实现延时)。 -
硬件刷新(如
Seg_Disp()动态扫描数码管,避免闪烁)。
void Timer0server() interrupt 1{ TL0 = 0x18; TH0 = 0xFC; // 重装载定时值(1ms) if(++Key_Slow == 10) Key_Slow = 0; // 10ms按键消抖计时 if(++Seg_Slow == 500) Seg_Slow =0; // 500ms数码管刷新计时 Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos]); // 动态扫描数码管 } -
(4)主函数(main)
-
初始化硬件(如
Timer0Init()初始化定时器)。 -
死循环中轮询调用功能处理函数,实现业务逻辑:
void main(){ Timer0Init(); // 初始化定时器 while(1){ Key_proc(); // 按键处理 Seg_proc(); // 显示处理 Led_proc(); // LED处理 } }
2. 模板优势
-
实时性:定时器中断保证周期性任务(如数码管扫描)准时执行。
-
逻辑分离:主循环处理业务逻辑,中断处理硬件定时任务,分工明确。
-
可扩展性:新增功能只需添加对应处理函数(如
Buzzer_proc()蜂鸣器处理),并在主循环调用。
3. 适用场景
-
需定时刷新的嵌入式系统(如数码管显示、按键消抖、传感器采样)。
-
多任务简单处理(通过主循环轮询实现 “伪多任务”)