历史上的今天
返回首页

历史上的今天

今天是:2025年04月17日(星期四)

正在发生

2020年04月17日 | 利用51单片机制作一个秒表的详细过程

2020-04-17 来源:eefocus

前面的话:

和很多朋友一样,在学51单片机的过程中我们肯定会涉及到制作一个秒表,牵涉到把单片机的多个部分组合起来使用,这对于我们初学者来说可能显得有些困难,我同大家一样,百思不得其解,最后头都弄大了才把这个秒表制作出来,为了给以后的朋友们一些思路,一些参考,所以在这里我把自己制作的整个详细过程整理出来供大家参考。我调试出来是没有问题的,各方面都稳定运行,由于我水平有限,中间可能会有不对的地方,欢迎大家指正,我们一起学习,一起进步!


我将分为三个部分来介绍:1.整体思路,2.硬件电路方面,3.软件编程方面。


1.整体思路

利用51单片机制作秒表时,我介绍精确到十分位(即0.1s)的制作,并让其拥有启动,暂停,复位三个功能。


用到的单片机部分:定时器部分,独立按键的检测与应用,数码管的显示,并结合一些简单的程序即可实现。


用5位数码管来进行显示,分别显示秒的十分位,秒的个位,秒的十位,分的个位,分的十位。用定时器定时50ms,2个定时器中断即是0.1s,即秒的十分位,20个定时器中断即是1s,60个1s即是1分钟,通过程序将5位数码管的值分离出来,并进行显示。这就是我在数码管显示方面的思路,如果不是太清楚,结合我下面软件编程方面的程序来看你可能就会明白,我会在那部分做详细介绍,看完了可能你就懂了。


利用独立按键设置启动/暂停键和清零键,利用独立按键的检测,若启动/暂停按键按下,秒表则启动或者暂停,按下复位键,秒表清零复位。我在程序后面全都有注释,不用担心。看完你就会明白了。


这是我制作的的流程图:



“ms100”表示秒的十分位,"s"表示秒的个位,“s1”表示秒的十位,“min”表示分的个位,“min1”表示分的十位。


“cnt”表示秒的计数位,即多少个一秒,定时满一秒加1,“minu”表示分的计数位,即多少个一分钟,一分钟加1,这个流程图提供了大致思路,要结合下面的程序部分一起看。可能有些简陋,请多多包涵!


看起来是不是好简单?有木有?请继续往下看。


2.硬件电路方面

每个人的硬件可能都不一样,(哪些控制数码管的位选,哪些控制数码管的段选,哪些控制独立按键等等),大家在自己制作过程中都要仔细考虑,我在这里就用我自己的硬件进行介绍。


这是我的数码管的电路图:(将J12用杜邦线接到对应的P0口,将J16用杜邦线接到对应的P1口)

位选端我用P1口控制,段选端我用P0口控制。在图中我已标明秒的个位s,秒的十位s1,分的个位min,分的十位min1所对应的数码管。该数码管是共阴极。


秒的十分位我用的是另一个共阳数码管。我用P3口控制该数码管的段选,其图如下:

而独立按键我用的P2^7控制“启动/暂停键”,P2^6控制复位键:电路图如下:(将JP5通过杜邦线接到P3口)

硬件电路基本上就是这些,由于分和秒之间要用小数点分隔开,所以分的个位对应的数码管的段码要用带小数点的段码,其余的数码管则不用。


硬件方面是为看懂软件程序做准备,下面我们就开始我们的软件程序方面吧!  


3.软件程序方面


#include

#define uchar unsigned char

#define uint unsigned int


#define PIN0 P0  //数码管段选端

#define PIN1 P1  //数码管位选端

#define PIN3 P3 //十分位数码管的段码端


sbit start=P2^7;  //启动/暂停按钮

sbit reset=P2^6;  //复位按钮


uint cnt=0;   //1s的次数的计数值

uint num=0;     //进入中断次数的计数值(一次50ms)

uint num1=0; //0.1s的次数的计数值


uchar code table[]={0x3f,0x06,0x5b,

0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f};

//不带小数点的共阴极数码管段码0-9


uchar code table1[]={0xbf,0x86,

0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};

//带小数点的共阴极数码管段码0-9

char code table2[]={0xc0,0xf9,0xa4,

0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

//不带小数点的共阳极数码管段码0-9


void Display(uint w,uint a,uint b,uint c,uint d);  //声明显示函数

void InitTimer0();  //声明定时器初始化函数

void Delayms(uint x);  //声明延时函数


void main()

{

uint ms100=0; //秒的十分位

uint s,s1,min,min1,minu=0; 

//依次是秒的个位,秒的十位,分的个位,分的十位

InitTimer0();   //初始化定时器

while(1) //进入死循环

{

if(start==0)   //检测启动/暂停键是否按下

Delayms(20); //延时消抖

{

if(start==0)  //消抖之后再次检测

{

TR0=!TR0; //定时器的控制位取反

while(!start);  //等待按键释放

}

}

if(reset==0)  //检测复位键是否按下

{

Delayms(20); //延时消抖

if(reset==0)  //消抖之后再次检测

{

num=0;

num1=0; //进入中断次数值清0

ms100=0; //十分位的计数值清0

cnt=0; //秒的计数值清0

minu=0; //分的计数值清0

while(!reset); //等待按键释放

}

}

if(num1>=2) //检测是否达到0.1s,(两个50ms)

{

num1=0;  //进入中断次数值清零

ms100++; //秒的十分位的计数值加1

if(ms100>=10)  //若秒的十分位计数值达到10

{

ms100=0;  //清零秒的十分位的计数值

num1=0; //进入中断次数值置0

}

}

if(num>=20)  //判断计时时间是否达到1s(20个50ms)

{

num=0;     //进入中断次数值置0

cnt++; //秒的计数值加1

if(cnt>=60) //判断是否达到60s

{

cnt=0; //若达到60s,将秒的计数值置零

minu++; //分的计数值加1

if(minu>=60)  //判断是否达到60分钟,一般秒表是用不到60分的,这是为了程序的严谨性


{

TR0=!TR0; //达到60分钟则关闭定时器并清零所有的计数值

num1=0;

num=0;

ms100=0;

cnt=0;

minu=0;

}

}

}

s=cnt%10;  //从秒的计数值里面分离秒的个位

s1=cnt/10; //从秒的计数值里面分离秒的十位

min=minu%10; //从分的计数值里面分离分的个位

min1=minu/10; //从分的计数值里面分离分的十位

Display(ms100,s,s1,min,min1);  //显示这5个数

}

}


void InitTimer0() //定时器初始化函数

{

TMOD=0x01; //选择定时器0的工作方式1

TH0=(65536-45872)/256;  //装初值(定时50ms),晶振11.0592MHz

TL0=(65536-45872)%256;

EA=1; //打开总中断

ET0=1; //打开定时器中断

TR0=0; //先不要启动定时器

}


void TIMER0()  interrupt 1  //定时器中断服务函数

{

TH0=(65536-45872)/256;  //重装初值

TL0=(65536-45872)%256;

num++; //让进入中断次数值加1,用于判断是否达到1s

num1++; //让进入中断次数值加1,用于判断是否达到0.1s

}


void Delayms(uint x)   //延时xms

{

uint i,j;

for(i=x;i>0;i--)

for(j=110;j>0;j--);

}


void Display(uint w,uint a,uint b,uint c,uint d) //定义显示函数

{

PIN3=table2[w]; //秒的十分位的段选

Delayms(5);

PIN0=table[a]; //秒的个位的段选

PIN1=0x7f; //秒的个位的位选

Delayms(5);

PIN0=table[b];  //秒的十位的段选

PIN1=0xbf; //秒的十位的位选

Delayms(5);

PIN0=table1[c];  //分的个位的段选(带小数点)

PIN1=0xdf; //分的个位的位选

Delayms(5);

PIN0=table[d]; //分的十位的段选

PIN1=0xef; //分的十位的位选

Delayms(5);

}


由于在打字时可能不小心会弄错一丁点程序,我都是一个字母一个字母手打的,所以请大家理解思路即可,根据这个思路自己去写,这样得到的知识才是属于自己的。毕竟 “读别人的故事,悟自己的人生”。


下面来几张实物图给大家看一下我这个秒表的实际效果。


编译结果:

烧写进单片机的效果:(没有按启动按钮之前)

按了启动按钮之后,秒表将会自动开始计时,由于无法演示动态过程,只能在中间按下暂停键给大家看看效果:







按下复位键后:

由于我用的是一个比较完整的51开发板,所以里面有很多部分,大家只需要注意观察数码管部分就好。


下面再来一个完整的图:

结束语

至此,利用51单片机制作的秒表就已经完成了!若是文章中有什么不懂的地方或者是自己在制作过程中遇到什么问题都可以联系我,或者给我留言,我一定竭尽全力帮助大家!我们一起学习,一起进步!希望大家都能在看完这篇文章后自己动手成功制作出一个秒表,祝愿大家学好单片机!当然,由于自身水平有限,文章中肯定会存在错误或者是考虑不周的的地方,恳请不吝赐教!谢谢大家!

推荐阅读

史海拾趣

EMBEST公司的发展小趣事

XXXX年,ARM公司投资了EMBEST,双方建立了紧密的战略合作关系。这一合作不仅为EMBEST带来了更多的技术支持和资源,也进一步巩固了其在ARM开发工具领域的领先地位。通过与ARM的紧密合作,EMBEST不断推出创新产品,满足市场的多样化需求。

安美通(APPCON)公司的发展小趣事

为了进一步扩大市场份额,安美通积极开展市场推广和品牌建设。公司参加了多个国内外知名展会和技术交流会议,与众多客户建立了良好的合作关系。同时,安美通还加大了对营销网络的投入,建立了完善的销售体系和客户服务体系,提高了客户满意度和忠诚度。

迦美信芯(CanaanTek)公司的发展小趣事

迦美信芯一直致力于技术创新和产品升级。公司推出的面向手机终端和物联网的2G/3G/4G/5G全系列的射频开关、天线调谐器、低噪声放大器等产品,在行业内具有较高的知名度和美誉度。特别是在天线调谐器领域,迦美信芯已成为国内设计出天线调谐器芯片并大量量产的厂家之一。

Compact公司的发展小趣事

在快速发展的过程中,Compact公司始终注重品牌建设和文化传承。公司通过不断提升产品质量和服务水平,树立了良好的品牌形象。同时,公司还注重培养员工的归属感和忠诚度,形成了独特的企业文化。这种文化传承不仅为公司的发展提供了强大的精神动力,还使公司在激烈的市场竞争中保持了独特的竞争力。

Agere System(LSI Logic)公司的发展小趣事

随着全球环保意识的提高,电子行业对环保和可持续发展的要求也越来越高。Compact公司积极响应这一趋势,加大环保投入,采用环保材料和工艺,降低生产过程中的能耗和排放。同时,公司还致力于推动循环经济的发展,通过回收和再利用废旧电子产品,减少资源浪费和环境污染。这一举措不仅提升了公司的社会形象,还为公司的可持续发展奠定了坚实基础。

请注意,以上故事仅为示例,并不代表任何真实存在的企业情况。如果需要关于特定企业(如Compact公司)的准确信息,建议查阅相关公司的官方资料、行业报告或新闻报道。

Dytran Instruments Inc公司的发展小趣事

随着技术的不断成熟和产品线的不断完善,Dytran开始积极拓展市场。公司不仅在美国本土取得了良好的销售业绩,还通过参加国际展览和建立海外办事处等方式,将产品推向全球。在这个过程中,Dytran的传感器产品得到了众多行业客户的认可,广泛应用于航空航天、工业和汽车行业的产品开发测试和嵌入式监控解决方案。

为了更好地服务全球客户,Dytran在成立两年后将其总部迁至美国加利福尼亚州的查茨沃思市。这里地理位置优越,交通便利,有利于公司进一步拓展北美市场。同时,公司还加强了与全球合作伙伴的合作,共同推动传感器技术的发展和应用。

问答坊 | AI 解惑

请教:模拟电路故障的智能诊断

请问有哪位大侠了解“模拟电路故障的智能诊断”这个方面的知识,讲解一下,越具体越好,谢谢~急用~大侠!…

查看全部问答>

fuse的分类及其功能参数

什么是 quick-acting fuse,non-time delay fuse和time delay fuse? 它们的区别在哪?是不是反应时间不一样啊(假如都是20A的 ,那么他们的工作条件有什么不同) 有谁知道相关的资料,中英文的都可以,谢谢!~!…

查看全部问答>

一种带辅助变压器的Flyback变换器ZVS软开关实现方案

摘要:提出了一种新颖的 FLYBACK 变换器ZVS软开关实现方案。 一个较小的辅助变压器与主 变压器串联,通过使辅助变压器原边激磁电感电流双向来达到主开关管的ZVS软开关条件。该方 案实现了主辅开关管的 ZVS软开关,限制了输出整流二极管关断时的 d ...…

查看全部问答>

求DSP读取BMP源码

我正在用dsp (TMS320C6211)做BMP文件的读取和存储,本人对dsp也是刚接触不久,处于学习阶段 但任务不等人,要读出BMP文件头信息,像素等,是个非压缩的图像, 谢谢各位大侠,给个源码,最好最好在指点一下小的 万分感谢 great18@sina.com…

查看全部问答>

max1641充电电路设计问题

    焊好元件以后, max16832的驱动电路不错,HDLED点亮了, 用外接100k电位器可以调整亮度。 就是不能充电。测量发现LDOH输出只有1.5V左右。       马上换一块PCB板,单独焊上MAX1641以及外围电路,这下LDOH输 ...…

查看全部问答>

哪位大侠知道啥芯片可以替代TPIC6C595N?

我们厂里给客人打样,用到TI的TPIC6C595N,DIP16脚的。这款芯片国内很难买,官网上买差不多8块钱,从国外发来。每片板子上要5个6C595N,所以相当贵。哪位DX知道,市面上常见的芯片中,有哪款可以替代这个6C595N?有知道的DX麻烦告诉一声,谢谢啦!& ...…

查看全部问答>

ADI活动样片申请第一次!

ADI申请样片一次申请4种,现在升级了好象是说可以申请8种 第一次申请经过十几天的等待终于寄到4种!还要等待14天后才可以再次申请!由于器件封装问题,还要想办法! [ 本帖最后由 蓝雨夜 于 2012-11-12 14:26 编辑 ]…

查看全部问答>

关于RTL8019AS发送数据包时寄存器设置问题

想问一下,用rtl8019as发送数据包时,怎么设置RBCR,TBCR寄存器的值?即怎么判断发送的数据包的大小?…

查看全部问答>

UAF42通用有源滤波器软件

请问有没有大神会用UAF42的软件设计滤波电路…

查看全部问答>

看了“新完美3D PCB,有3D PCB库下载 Buffalo”,忍不住发几个EAGLE3D的图

EAGLE不是什么高端PCB软件,甚至连某些中端的都比不上。不过呢,软件够用即可,方便最好。 EAGLE3D 是用POV-RAY渲染的2D图。嗯,可以说是3D建模,2D渲染。以俺见过的PCB 3D效果图来看,EAGLE3D是最漂亮的。 这里有更多的3D图:http:/ ...…

查看全部问答>