news 2026/7/2 9:43:16

手把手玩转C51定时器三连击

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
手把手玩转C51定时器三连击

C51定时器实验Proteus仿真C语言 一共三个程序 1. 实现0-59s的计时,每隔1S秒值加1并通过S1、S0两片数码管显示出来,当计时数据加到60时数值变为00,重新计时。 2. 定时器控制单只LED灯闪烁,点亮2s,再熄灭0.5s。 要求:采用查询法和中断法两种编程方式实现。 3. 编写0-99的手动计数程序,按下P3.5引脚上所接的负脉冲按钮,在S1和S0两片数码管上显示计数值,加到数值100则清零,继续从0加到99重复显示。

最近在折腾51单片机定时器的几个经典实验,用Proteus跑仿真的时候发现有些小坑。今天咱们直接上代码,边撸代码边聊实现细节,三个实验打包带走!


一、数码管60秒轮回计时

先来搞个基础款——0-59秒循环计时。核心思路是用定时器做1秒基准,配合数码管动态扫描。这里用定时器0模式1实现:

#include <reg51.h> #define uint unsigned int #define uchar unsigned char uchar code segment[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //共阳段码 uchar count = 0, sec = 0; void timer0_init() { TMOD = 0x01; //模式1 TH0 = 0xFC; //1ms定时 TL0 = 0x66; ET0 = 1; EA = 1; TR0 = 1; } void display() { P2 = 0x01; //开个位 P0 = segment[sec%10]; for(uint i=0;i<500;i++); P2 = 0x02; //开十位 P0 = segment[sec/10]; for(uint i=0;i<500;i++); } void main() { timer0_init(); while(1) { display(); if(count >= 1000) { //累计1秒 sec++; count = 0; if(sec >= 60) sec = 0; } } } void timer0_isr() interrupt 1 { TH0 = 0xFC; //重装初值 TL0 = 0x66; count++; }

关键点解析

  1. 定时器中断里只做累加,主循环判断是否满1秒,避免在中断里处理复杂逻辑
  2. 动态扫描加了简单延时,实际项目建议用定时器控制刷新频率
  3. 段码表要根据实际数码管类型调整(共阳/共阴)

二、LED呼吸灯:两种姿势玩定时

姿势A:中断法(推荐)
#include <reg51.h> sbit LED = P1^0; uint flash_cnt = 0; bit state = 0; void timer0_init() { TMOD |= 0x01; TH0 = 0x3C; //50ms定时 TL0 = 0xB0; ET0 = 1; EA = 1; TR0 = 1; } void main() { timer0_init(); while(1); } void timer0_isr() interrupt 1 { TH0 = 0x3C; TL0 = 0xB0; if(++flash_cnt >= (state ? 40 : 10)) { //2s/0.5s state = !state; LED = ~state; flash_cnt = 0; } }
姿势B:查询法(适合简单场景)
void main() { TMOD = 0x01; while(1) { TH0 = 0x3C; TL0 = 0xB0; TR0 = 1; while(!TF0); //死等标志位 TF0 = 0; //...类似中断内的计数逻辑 } }

对比分析

  • 中断法CPU利用率高,适合多任务
  • 查询法会阻塞主程序,适合简单场景
  • 时间计算注意:50ms×40次=2s,50ms×10次=0.5s

三、手动计数器:按键的艺术

#include <reg51.h> sbit KEY = P3^5; uchar num = 0; void delay(uint i) { while(i--); } void check_key() { if(KEY == 0) { delay(1000); //消抖 if(KEY == 0) { num++; if(num >= 100) num = 0; while(!KEY); //等待松手 } } } void display() { //显示逻辑同实验一 } void main() { while(1) { check_key(); display(); } }

防抖秘籍

  1. 检测到低电平后延时10ms左右
  2. 再次确认按键状态
  3. 松手检测避免连击
  4. 实际项目建议用外部中断+定时器消抖

Proteus仿真Tips

  1. 数码管记得接限流电阻
  2. 按键加10k上拉电阻
  3. LED电流设置2-5mA
  4. 定时器初值可用工具计算(如STC-ISP)

这三个实验涵盖了定时器的基本玩法,搞明白之后可以衍生出各种定时应用。下次试试把这三个功能整合到一个系统里,加上模式切换按键,立马变身多功能电子表!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/26 14:58:38

Kamailio 严格路由 vs 松散路由

严格路由比较 $rd 是不是 myself松散路由比较 $route 是不是 myselfrr 模块有 2 个函数&#xff1a;loose_route() 先测试严格路由&#xff0c;如果失败再测试松散路由loose_route_mode(0) 完全等于 loose_route()loose_route_mode(1) 不测试严格路由&#xff0c;只测试松散路由…

作者头像 李华
网站建设 2026/6/26 14:58:37

深度测评8个AI论文网站,助本科生轻松搞定毕业论文!

深度测评8个AI论文网站&#xff0c;助本科生轻松搞定毕业论文&#xff01; AI 工具如何助力论文写作&#xff0c;让毕业不再焦虑 对于大多数本科生来说&#xff0c;撰写毕业论文是一项既重要又充满挑战的任务。从选题到开题&#xff0c;从初稿到修改&#xff0c;每一个环节都可…

作者头像 李华
网站建设 2026/7/1 20:22:27

网络密集性(频繁网络通信)、并发性(支持多用户同时操作)、负载不可预测性(流量波动大)、数据驱动(依赖数据库交互)

一、软件类型及特点Web 应用&#xff08;WebApp&#xff09; 以互联网为核心&#xff0c;用户通过浏览器访问。特点&#xff1a;网络密集性&#xff08;频繁网络通信&#xff09;、并发性&#xff08;支持多用户同时操作&#xff09;、负载不可预测性&#xff08;流量波动大&am…

作者头像 李华
网站建设 2026/6/25 19:59:39

【git】

问题&#xff1a;推送代码提示下面信息&#xff1a;16:22:54.422: [C:\git\yang-teambition] git -c credential.helper -c core.quotepathfalse -c log.showSignaturefalse push --progress --porcelain origin refs/heads/dev_tianzhi:dev_tianzhi ** WARNING: connection is…

作者头像 李华
网站建设 2026/7/1 17:43:30

借助AI技术轻松实现学术范儿的开题报告PPT自动生成方案

AI工具开题报告生成能力对比速览 工具名称 生成速度 内容完整度 参考文献质量 适用场景 AIbiye ⚡⚡⚡⚡ ⭐⭐⭐⭐ 15真实文献 理工科开题 AICheck ⚡⚡⚡ ⭐⭐⭐⭐⭐ 自动匹配领域 人文社科类 秒篇 ⚡⚡⚡⚡⚡ ⭐⭐⭐ 基础文献支持 紧急需求 AskPaper ⚡…

作者头像 李华
网站建设 2026/6/26 14:58:42

如何给AI提问:让机器高效理解你的需求

在人工智能&#xff08;AI&#xff09;快速发展的今天&#xff0c;无论是ChatGPT、Claude、文心一言还是其他大语言模型&#xff0c;提问的质量直接决定了回答的准确性。许多人抱怨AI“答非所问”&#xff0c;其实往往是因为问题本身不够清晰、结构混乱或缺乏关键信息。 本文将…

作者头像 李华