基于51单片机设计带AT24C02掉电存储的传送带产品计数器,proteus仿真+keil程序,矩阵键盘设定、光电计数、数码管显示,附设计报告与视频讲解。

01 设计任务
功能介绍:
使用51单片机设计一个带存储功能的传送带产品计数器,在 H30 的基础上增加 AT24C02 掉电存储,要求如下:
1、设定值写入 EEPROM,掉电不丢:矩阵键盘设定目标数量(1~9999),按"确定"后写入 AT24C02——断电重启后设定值还在,不用重新输;
2、上电自动读取设定值:开机第一件事就是从 EEPROM 地址 0~3 把设定值读回来直接用,并做了脏数据校验(首次使用存储区是乱值,程序识别后自动清零初始化);
3、独立按键"启动/停止/设置":启动清零计数开跑,停止随时停机,设置键进入设定模式(设定中当前输入位闪烁定位);
4、光电传感器单脉冲捕捉计数(T0 计数器初值 0xFFFF),计数值四位数码管实时显示,达到设定值电机自动停机,绿灯=运行、红灯=停止;
5、停止时连计数中断一起关掉(EA=0)——不是"电机停了但还在数",而是彻底停账,和 H30 的常开计数形成对照。
特别注意:这一期的主角不是计数(那是 H30 讲过的),是那片AT24C02——单片机掉电就失忆,生产线上的目标数量总不能天天重设,所以挂一片 EEPROM 把设定值存起来。更值钱的是程序里那套手写的 I2C 时序(起始、停止、应答、读字节、写字节,一个函数都不省):I2C 是嵌入式第一大通信接口,OLED、传感器、RTC 时钟芯片全是它,这套时序代码抄走就是万能钥匙,02 节逐拍拆解。
02 手写 I2C:一条总线怎么"说话"
I2C 用两根线:SCL(时钟,P1.6)+ SDA(数据,P1.7),谁也不能自己抢着说话——SCL 高电平期间 SDA 的跳变是协议信号,SCL 低电平期间 SDA 才能换数据。整个程序的通信全靠五个时序函数:
起始与停止:起始(START)是 SCL 还保持高电平时,SDA 从高跳到低;停止(STOP)反过来,SCL 保持高电平,SDA 从低升到高。两个动作靠的是两条线的先后顺序,不是电平高低——所以 I2C 里 SDA 只允许在 SCL 低电平期间变化,SCL 拉高时必须稳住,这是整个协议的地基。
写字节(高位在前,逐位送):一个字节 8 位,从最高位开始往 SDA 上送——先摆好 SDA,再拉高 SCL 让 EEPROM 在这一刻采样,然后拉低 SCL 换下一位,重复 8 次。8 位送完后主机释放 SDA,等 EEPROM 把 SDA 拉低表示“收到了”。这个应答位(ACK)是判断写成功的唯一依据,等不到 ACK,多半是器件地址写错或者接线没通。
读字节 + 应答:读时 SCL 拉高读 SDA 逐位拼装 k=(k<<1)|SDA;应答(ACK)是接收方在第 9 个时钟把 SDA 拉低说"收到了"。
一次完整的写入流程串起来就是:起始 → 发器件地址 0xA0(写命令)→ 等应答 → 发存储地址 → 应答 → 发数据 → 应答 → 停止;读取类似,只是器件地址换成 0xA1(读命令)且最后不用应答(no_ack)。0xA0/0xA1 这对数字是 AT24Cxx 的固定身份编号(引脚 A2A1A0 全接地时),写 0xA0 读 0xA1,八个字节地址系列的芯片通用。
还有个工程化的设计:程序用 #define AT24CXX AT24C02 一个宏切换器件型号——24C02 地址是单字节、24C16 要双字节(先发高 8 位再发低 8 位),read_rom/write_rom 里的 if(AT24CXX>AT24C16) 自动分流。换芯片只改一行宏,驱动代码不动,这是器件驱动通用化的标准做法。
03 掉电存储的两端:上电读回 + 确认写入
EEPROM 在这个系统里只存一件事——设定值,4 个字节对应 4 位数字。两端的使用很有代表性:
上电读回(主函数第一件事):从地址 0 开始连续读 4 个字节,分别对应千位、百位、十位、个位。读完立刻校验——只要有一位不是 0~9 的数字,就判为脏数据,把 4 个字节全部清零再写回去。也就是说“读回、校验、不合法则重写”是一套连着做的动作,缺一步设定值就是废的。
注意这个脏数据校验:EEPROM 新片上读出来全是 0xFF,不校验的话"设定值"会是一个 168430 的怪物。程序逐位检查读回值是否 ≤9,有一位不合法就整体清零重写——"读回 → 校验 → 不合法则初始化"三步走,是所有掉电存储的第一课。
确认写入:设定模式按"确定"退出时,Write_set_num() 把 4 个字节逐个写入 EEPROM——注意写 EEPROM 是有寿命的(10 万~100 万次),只在用户确认的一刻写,绝不反复写,这是延长存储寿命的基本纪律。
04 计数与控制:单脉冲捕捉 + 三键状态
计数部分沿用 H30 讲过的单脉冲捕捉:T0 计数器初值 0xFFFF,光电传感器每出一个脉冲立刻溢出进中断,counter_num++ 配四位 BCD 进位链显示,计数值 >=set_num 一行比较自动停机。
这一期值得看的是三独立键 + 关中断暂停的细节:
· 启动:计数清零 → 电机转 → 绿灯亮 → EA=1 打开计数中断——从零开始这批;
· 停止:电机停 → 红灯亮 → EA=0 关闭计数中断——产品再过传感器也不计,"停止"是物理意义上的停账,不是暂停显示;
对比 H30 的常开计数(电机停了计数器还醒着),用 EA 开关中断来定义"停止"的语义——一行代码说清业务规则。中断开关(EA/ET0/EX0)不只是技术开关,也是业务开关,这个用法在需要"暂停计数"的场景(分批装货)特别好用。
按键扫描这一版也升级了:矩阵键盘(0~9/清除/确定)和三个独立键在一个 KEY_Scan 里合并扫描,统一返回键值(0~11 矩阵键、12/13/14 独立键),主循环一个 switch 分拣——两套键盘一套接口,比 H30 分开扫干净。
05 显示:双缓冲 + 闪烁光标(继承与微调)
显示沿用 H30 的双缓冲方案:正常模式显示计数值 counter_buf,设定模式显示设定值 dis_data_buf 且当前输入位按 50/100 周期闪烁。扫描周期从 5ms 微调到 2ms(四位一轮 8ms≈125Hz),闪烁节奏不变。位选经 PNP 三极管驱动、段码共阳表——和 H30 同一套硬件话术,不再展开。
06 资料清单


这份 H 系列资料是全套的:
· Proteus 仿真:整机图含 AT24C02、矩阵键盘、独立按键、继电器驱动,两个版本(7.8 / 8.6);
· Keil 程序:C 语言,单文件 main.c,注释齐全,编译 0 错误 0 警告(code=1919):

· 设计报告:Word 版设计报告一份,含原理分析和流程图;
· 视频讲解:原理图讲解 + 程序讲解两段 mp4。
需要的朋友公众号后台回复关键词获取,也可以到 51mcu.top 看更多设计。
07 常见问题排查
1、设定值重启后丢失:确认按过"确定"——只有确定键触发 Write_set_num() 写 EEPROM,设置中途断电当然不存;再查 AT24C02 的 SCL/SDA 是否接 P1.6/P1.7,两根线都要上拉;
2、上电显示一个巨大数字:EEPROM 首次使用是 0xFF 脏数据——程序的校验逻辑会自动清零初始化,如果没生效,检查 dis_data_buf[i]>9 的判断是否还在;
3、停止后再启动,计数从上次的数继续:正常——"启动"键里带清零(counter_num=0),如果你改过启动逻辑把清零删了就会出现这个现象;想要"暂停续计"的效果,把清零那几行挪走即可;
4、I2C 读写无反应:delay_us 里是 _nop_() 空转,别改成大延时(I2C 时序有速率上限以外的下限约束不大但过慢浪费);24C16 以上的芯片要确认 AT24CXX 宏改成对应型号(双字节地址);
5、到值不停机:set_num 是每次主循环从显示缓冲实时拼装的,设定模式没退出(光标还在闪)时比较的是旧值——按"确定"退出设定模式才生效。
08 总结
这一期在 H30 的计数骨架上加了一片 EEPROM,补齐了"设定值掉电保存"这块工业设备的最后一块拼图,顺手交付了全套手写 I2C 驱动——起始/停止/应答/读写字节五个函数 + 0xA0/0xA1 器件寻址 + 单双字节地址自适应宏,这套代码换到 OLED、DS1307、任何 I2C 传感器上都能直接用。还有两个软件设计点值得带走:上电"读回→校验→初始化"三步走防脏数据、用 EA 开关中断定义"停止"的业务语义。加上 H30 的单脉冲捕捉和定值控制,"带存储的产线计数器"完整闭环,工业计数类课设可以放心收工了。
09 文件日期修改
如果你想把文件修改为最新的日期,又不想新建工程,那么你可以参考下面的文章。
"如何不打开程序的情况下更改proteus和keil程序的日期?"
工具和仿真文件在一起,见下面的下载链接。
10 资料下载
全套资料包含 Keil 工程(C 语言源码 + hex 文件)、Proteus 仿真工程、设计报告、程序流程图、讲解视频,以及编译截图和仿真截图。下载后可直接打开运行,也可用于课程设计、毕业设计参考。
也可以关注公众号「单片机仿真」,回复 H31 获取下载入口。公众号内还有 A / T / H 全系列 400 多个单片机仿真实例,回复「目录」可查看完整清单。

