当前位置:首页 > 单片机 > 单片机
[导读]结合前几天来写过的文章, 今天总算写了一个功能较多的应用 - 多功能时钟, 集时钟, 秒表, 温度计一体.基础文章:1.单片机练习 - DS18B20温度转换与显示2.用C51编写单片机延时函数3.单片机练习 - 定时器4.单片机练习 -

结合前几天来写过的文章, 今天总算写了一个功能较多的应用 - 多功能时钟, 集时钟, 秒表, 温度计一体.

基础文章:
1.单片机练习 - DS18B20温度转换与显示
2.用C51编写单片机延时函数
3.单片机练习 - 定时器
4.单片机练习 - 计时器

实验板:TX-1B实验板

6位数码管与单片机的连接电路图


按键S2, S3与单片机的连接电路图: 其中S2与P3.4连, S3与P3.5连接...


DS18B20与单片机连接电路图:


具体按键功能分配请看源代码注释部分:


1//多功能时钟,精确到小数0.01秒,即10ms
2//功能:时钟,秒表,温度计
3
4/*
5S5键为功能选择键,上电默认使用时钟功能
6功能顺序为:时钟,温度计,秒表
7
8mode=1.时钟(每次掉电后都要重新设置时间)
91)当选中时钟功能时,具体按键功能如下:
10
112)可设置时分秒,时利用发光二极管显示,分秒用数码管显示
12
133)时钟:采用定时器0计时,工作方式1
14
15mode=2.时钟设置模式
16当选中时钟设置模式
17S2为位选,S3为增加选中位的值
18S4确定更改,S5放弃更改,进入秒表模式
19
20mode=3.秒表
211)当选中秒表功能时,具体按键功能如下:
22S2为开始/暂停,S3为清零
23
242)采用定时器1计时,工作方式1
25
26mode=4.温度计
271)利用DS18B20检测环境温度;
282)最小温度值为0.01℃,可表示温度范围:-55℃~+125℃
29
30*/
31
32#include
33#include
34#include
35
36//0-F数码管的编码(共阴极)
37unsignedcharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,
380x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
39//0-9数码管的编码(共阴极),带小数点
40unsignedcharcodetableWidthDot[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,
410x87,0xff,0xef};
42
43sbitwela=P2^7;//数码管位选
44sbitdula=P2^6;//数码管段选
45sbitds=P2^2;
46unsignedcharth,tl,mode=1;//mode存放功能模式,默认在模式1时钟
47unsignedcharclockPosition=0;//时钟设置模式下,光标所在的位置;默认在0
48unsignedcharclockTmp=0;//用于时钟模式下临时计数
49bitclockTmpBit=0;//用于时钟模式下临时标志位
50
51//秒4字节,分2字节,时1字节
52unsignedchardatas[]={0,0,0,0,0,0,0};//保存计时器数据
53unsignedcharclockDatas[]={0,0,0,0,0,0,0};//保存时钟数据
54unsignedchar*values=clockDatas;//根据mode选择适当的数据数组指针
55inttempValue;//存放温度值
56unsignedchartempCount=0;//用于记录显示了多少次温度值,用于定时
57
58sbitS2=P3^4;//键S2,作开始/暂停
59sbitS3=P3^5;//键S3,清零
60sbitS4=P3^6;//键S4
61sbitS5=P3^7;//键S5
62unsignedchartmpDatas[]={0,0,0,0,0,0,0};//存放临时设置值
63unsignedcharicount;
64
65//延时函数,对于11.0592MHz时钟,例i=5,则大概延时5ms.
66voiddelay(unsignedinti)
67{
68unsignedintj;
69while(i--)
70{
71for(j=0;j<125;j++);
72}
73}
74
75/***********************温度计模式******************************/
76
77//初始化DS18B20
78//让DS18B20一段相对长时间低电平,然后一段相对非常短时间高电平,即可启动
79voiddsInit()
80{
81//对于11.0592MHz时钟,unsignedint型的i,作一个i++操作的时间大于为8us
82unsignedinti;
83ds=0;
84i=100;//拉低约800us,符合协议要求的480us以上
85while(i>0)i--;
86ds=1;//产生一个上升沿,进入等待应答状态
87i=4;
88while(i>0)i--;
89}
90
91voiddsWait()
92{
93unsignedinti;
94while(ds);
95while(~ds);//检测到应答脉冲
96i=4;
97while(i>0)i--;
98}
99
100//向DS18B20读取一位数据
101//读一位,让DS18B20一小周期低电平,然后两小周期高电平,
102//之后DS18B20则会输出持续一段时间的一位数据
103bitreadBit()
104{
105unsignedinti;
106bitb;
107ds=0;
108i++;//延时约8us,符合协议要求至少保持1us
109ds=1;
110i++;i++;//延时约16us,符合协议要求的至少延时15us以上
111b=ds;
112i=8;
113while(i>0)i--;//延时约64us,符合读时隙不低于60us要求
114returnb;
115}
116
117//读取一字节数据,通过调用readBit()来实现
118unsignedcharreadByte()
119{
120unsignedinti;
121unsignedcharj,dat;
122dat=0;
123for(i=0;i<8;i++)
124{
125j=readBit();
126//最先读出的是最低位数据
127dat=(j<<7)|(dat>>1);
128}
129returndat;
130}
131
132//向DS18B20写入一字节数据
133voidwriteByte(unsignedchardat)
134{
135unsignedinti;
136unsignedcharj;
137bitb;
138for(j=0;j<8;j++)
139{
140b=dat&0x01;
141dat>>=1;
142//写"1",将DQ拉低15us后,在15us~60us内将DQ拉高,即完成写1
143if(b)
144{
145ds=0;
146i++;i++;//拉低约16us,符号要求15~60us内
147ds=1;
148i=8;while(i>0)i--;//延时约64us,符合写时隙不低于60us要求
149}
150else//写"0",将DQ拉低60us~120us
151{
152ds=0;
153i=8;while(i>0)i--;//拉低约64us,符号要求
154ds=1;
155i++;i++;//整个写0时隙过程已经超过60us,这里就不用像写1那样,再延时64us了
156}
157}
158}
159
160//向DS18B20发送温度转换命令
161voidsendChangeCmd()
162{
163dsInit();//初始化DS18B20,无论什么命令,首先都要发起初始化
164dsWait();//等待DS18B20应答
165delay(1);//延时1ms,因为DS18B20会拉低DQ60~240us作为应答信号
166writeByte(0xcc);//写入跳过序列号命令字SkipRom
167writeByte(0x44);//写入温度转换命令字ConvertT
168}
169
170//向DS18B20发送读取数据命令
171voidsendReadCmd()
172{
173dsInit();
174dsWait();
175delay(1);
176writeByte(0xcc);//写入跳过序列号命令字SkipRom
177writeByte(0xbe);//写入读取数据令字ReadScratchpad
178}
179
180//获取当前温度值
181voidgetTempValue()
182{
183unsignedinttmpvalue;
184floatt;
185unsignedcharlow,high;
186sendReadCmd();
187//连续读取两个字节数据
188low=readByte();
189high=readByte();
190//将高低两个字节合成一个整形变量
191//计算机中对于负数是利用补码来表示的
192//若是负值,读取出来的数值是用补码表示的,可直接赋值给int型的value
193tmpvalue=high;
194tmpvalue<<=8;
195tmpvalue|=low;
196tempValue=tmpvalue;
197
198//使用DS18B20的默认分辨率12位,精确度为0.0625度,即读回数据的最低位代表0.0625度
199t=tempValue*0.0625;
200//将它放大100倍,使显示时可显示小数点后两位,并对小数点后第三进行4舍5入
201//如t=11.0625,进行计数后,得到value=1106,即11.06度
202//如t=-11.0625,进行计数后,得到value=-1106,即-11.06度
203tempValue=t*100+(tempValue>0?0.5:-0.5);//大于0加0.5,小于0减0.5
204}
205
206//显示当前温度值,精确到小数点后一位
207//若先位选再段选,由于IO口默认输出高电平,所以当先位选会使数码管出现乱码
208voiddisplayTemp()
209{
210unsignedchari;
211unsignedinttmp=abs(tempValue);
212tmpDatas[0]=tmp/10000;
213tmpDatas[1]=tmp%10000/1000;
214tmpDatas[2]=tmp%1000/100;
215tmpDatas[3]=tmp%100/10;
216tmpDatas[4]=tmp%10;
217if(tempValue<0)
218{
219//关位选,去除对上一位的影响
220P0=0xff;
221wela=1;//打开锁存,给它一个下降沿量
222wela=0;
223//段选
224P0=0x40;//显示"-"号
225dula=1;//打开锁存,给它一个下降沿量
226dula=0;
227
228//位选
229P0=0xfe;
230wela=1;//打开锁存,给它一个下降沿量
231wela=0;
232delay(1);
233}
234for(i=0;i!=5;i++)
235{
236//关位选,去除对上一位的影响
237P0=0xff;
238wela=1;//打开锁存,给它一个下降沿量
239wela=0;
240//段选
241if(i!=2)
242{
243P0=table[tmpDatas[i]];//显示数字
244}
245else
246{
247P0=tableWidthDot[tmpDatas[i]];//显示带小数点数字
248}
249dula=1;//打开锁存,给它一个下降沿量
250dula=0;
251
252//位选
253P0=_crol_(0xfd,i);//选择第(i+1)个数码管
254wela=1;//打开锁存,给它一个下降沿量
255wela=0;
256delay(1);
257}
258tempCount++;
259if(tempCount==100)
260{
261tempCount=0;
262getTempValue();
263sendChangeCmd();
264}
265}
266
267//显示时钟和秒表的结果
268voiddisplay()
269{
270unsignedchari;
271if(mode==4)//显示温度
272{
273displayTemp();
274}
275else{//显示时间
276for(i=0;i<6;i++)
277{
278//关位选,去除对上一位的影响
279P0=0xff;
280wela=1;//打开锁存,给它一个下降沿量
281wela=0;
282//段选
283if(i==2||i==4)
284{
285P0=tableWidthDot[values[i]];//显示带小数点数字,作为分秒,秒与毫秒的分隔
286}
287else
288{
289P0=table[values[i]];//显示数字
290}
291if(mode==2&&i==clockPosition)//时钟设置模式下,光标所在位置,闪烁
292{
293clockTmp++;
294if(clockTmp==20)
295{
296clockTmpBit=~clockTmpBit;
297clockTmp=0;
298}
299if(clockTmpBit)
300P0=0x00;
301}
302dula=1;//打开锁存,给它一个下降沿量
303dula=0;
304
305//位选
306P0=_cror_(0xdf,i);//选择第(i+1)个数码管
307wela=1;//打开锁存,给它一个下降沿量
308wela=0;
309delay(1);
310}
311if(mode==2&&6==clockPosition)//时钟设置模式下,光标所在位置,闪烁
312{
313clockTmp++;
314if(clockTmp==20)
315{
316clockTmpBit=~clockTmpBit;
317clockTmp=0;
318}
319if(clockTmpBit)
320{
321if(values[6]==0)
322{
323P1=0x0f;
324}
325else
326{
327P1=~values[6];
328}
329}
330else
331{
332P1=0xff;
333}
334}
335else
336{
337P1=~values[6];
338}
339}
340}
341
342//检测功能模式键是否被按下
343voidcheckModeKey()
344{
345if(!S5)
346{
347delay(7);
348if(!S5)
349{
350mode++;
351switch(mode)
352{
353case2://定时器0是不会关闭的,即使在设置模式下
354for(icount=0;icount<7;icount++)
355{
356tmpDatas[icount]=clockDatas[icount];//将设置之前的值暂存到临时数组
357}
358values=tmpDatas;
359break;
360case3://秒表模式
361values=datas;
362break;
363case4://温度计模式
364//启动温度转换
365sendChangeCmd();
366getTempValue();
367break;
368default:
369values=clockDatas;
370mode=1;
371TR0=1;
372}
373while(!S5)//等待释放键
374{
375display();
376}
377}
378}
379}
380
381//选中位数值增1,用于时钟模式的设置状态下
382voidadd()
383{
384values[clockPosition]++;
385switch(clockPosition)
386{
387case3:
388case5:
389if(values[clockPosition]>5)
390values[clockPosition]=0;
391break;
392case6:
393if(values[clockPosition]>23)
394values[clockPosition]=0;
395break;
396default:
397if(values[clockPosition]>9)
398values[clockPosition]=0;
399}
400}
401
402//检测是否有键按下,并执行相应功能
403voidcheckKey()
404{
405checkModeKey();
406switch(mode)
407{
408case2:
409if(!S2)//左移光标位
410{
411delay(7);
412if(!S2)
413{
414clockPosition++;
415if(clockPosition>6)
416{
417clockPosition=0;
418}
419}
420}
421elseif(!S3)//选中位增1
422{
423delay(7);
424if(!S3)
425{
426add();
427}
428}
429elseif(!S4)//选中确定更改
430{
431delay(7);
432if(!S4)
433{
434for(icount=0;icount<7;icount++)
435{
436clockDatas[icount]=tmpDatas[icount];//将设置的值存到clockDatas[]
437}
438values=clockDatas;
439mode=1;//将模式变成时钟模式
440}
441}
442break;
443case3:
444if(!S2)
445{
446delay(7);//延时大约10ms,去抖动
447if(!S2)//开始/暂停键按下
448{
449TR1=~TR1;
450}
451}
452
453elseif(!S3)
454{
455delay(7);//延时大约10ms,去抖动
456if(!S3)//清零键按下
457{
458TR1=0;
459TH1=th;
460TL1=tl;
461for(icount=0;icount<7;icount++)
462{
463datas[icount]=0;
464}
465}
466}
467break;
468}
469//等待键被释放
470while(!S2||!S3||!S4)
471{
472display();//等待期间要显示
473}
474}
475
476voidmain()
477{
478delay(1);
479th=0xdb;//(65536-10000/1.085)/256;//定时10ms
480tl=0xff;//(65536-10000/1.085)-th*256;
481TH1=TH0=th;//初始化定时器1,0
482TL1=TL0=tl;
483EA=1;//开中断
484ET1=ET0=1;//允许定时器1,0中断请求
485TMOD=0x11;//定时器1,0都工作方式1
486TR1=0;
487TR0=1;//开始显示时间
488while(1)
489{
490checkKey();//检测是否就键按下
491display();//显示计时值
492}
493}
494
495//定时器0中断响应函数,用于时钟计时
496voidtime0()interrupt1
497{
498TH0=th;//重置计数值
499TL0=tl;
500
501clockDatas[0]++;//0.01秒
502if(clockDatas[0]==10)
503{
504clockDatas[0]=0;
505clockDatas[1]++;//0.1秒
506if(clockDatas[1]==10)
507{
508clockDatas[1]=0;
509clockDatas[2]++;//秒
510if(clockDatas[2]==10)
511{
512clockDatas[2]=0;
513clockDatas[3]++;//10秒
514if(clockDatas[3]==6)
515{
516clockDatas[3]=0;
517clockDatas[4]++;//分
518if(clockDatas[4]==10)
519{
520clockDatas[4]=0;
521clockDatas[5]++;//10分
522if(clockDatas[5]==6)
523{
524clockDatas[5]=0;
525clockDatas[6]++;//时
526if(clockDatas[6]==24)
527{
528clockDatas[6]=0;
529}
530}
531}
532}
533}
534}
535}
536}
537
538//定时器1中断响应函数,用于秒表计时
539voidtime1()interrupt3
540{
541TH1=th;//重置计数值
542TL1=tl;
543
544datas[0]++;//0.01秒
545if(datas[0]==10)
546{
547datas[0]=0;
548datas[1]++;//0.1秒
549if(datas[1]==10)
550{
551datas[1]=0;
552datas[2]++;//秒
553if(datas[2]==10)
554{
555datas[2]=0;
556datas[3]++;//10秒
557if(datas[3]==6)
558{
559datas[3]=0;
560datas[4]++;//分
561if(datas[4]==10)
562{
563datas[4]=0;
564datas[5]++;//10分
565if(datas[5]==6)
566{
567datas[5]=0;
568datas[6]++;//时
569if(datas[6]==24)
570{
571datas[6]=0;
572}
573}
574}
575}
576}
577}
578}
579}

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭