找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3311|回复: 5
打印 上一主题 下一主题
收起左侧

单片机智能秒表的制作与调试课程设计论文与资料下载

[复制链接]
跳转到指定楼层
楼主

单片机课程设计项目:智能秒表的设计与制作
一、项目任务:智能秒表的设计与制作

用四位LED数码管制作带小数显示的秒表,前两位显示整数部分(秒),后两位显示小数部分(百分之一秒)。

所设计的秒表最大计时时间为99秒99。

开始时,数码管显示“00. 00”,表明从0开始计时。

本智能秒表有两种时间计时模式。(注意:模式1与模式2用同一个程序实现,即当程序下载至单片机芯片后,只需要按下相应按键,该秒表可工作在任意一种模式下)

(一)基本部分:

1、模式1累积计时模式

(1)按按键1可实现秒表开始、停止、再开始、再停止计时(时间累计);

(2)计时完毕,按按键2计时归零。

2、模式2间隔计时模式

(1) 按按键1开始计时;

(2) 按按键2一次暂停秒表并显示当前时间。间隔时间显示2秒后秒表将持续计时。(例如在3秒钟时秒表被暂停,2秒钟后秒表从5秒开始继续计时。显示2秒是为了方便记录当前时间);

(3) 在下一点终止时再按按键2记录此时相关信息,如此重复;

(4) 当计时停止时按按键1;

(5)可通过按键3查看前面操作所记录的时间,最多可查看10个记录;

(6) 计时完毕,按按键2键计时归零。

(二)发挥部分

(1)用电脑时间校准秒表的时间,保证秒表走时的准确性(100秒的误差小于0.1秒),思考如何修改程序?

(2)利用内部E2PROM存储器(STC89C52自带),使智能秒表具有掉电数据不丢失的功能,思考如何修改程序?

(3)仿真无误后,购买元件制作该智能秒表,从商业价值考虑该智能秒表的美观性和实用性。

二、硬件电路及仿真效果图
三、STC90C52RC单片机引脚排列图
四、四位共阴极数码管引脚排列图
五、元器件清单
序号
元件名称
规格型号
数量
单价
合计
1
单片机
STC90C52RC
1
6
6
2
四位共阴数码管
3641AS
1
2
2
3
轻触按键
45*45mm
6
0.2
1.2
4
晶振
12MHz
1
0.5
0.5
5
瓷片电容
20pF
2
0.1
0.2
6
电解电容
10uF/10V
1
0.3
0.3
7
电阻
10KΩ
1
0.1
0.1
8
排电阻
1KΩ
1
0.5
0.5
9
单片机插座
40PIN
1
0.5
0.5
10
电路板
7cm×9cm
1
3
3
11
电池
+5V
1
3
3
12
外部存储器
AT24C04
1
2
2
共计


18

19.30元
七、调试方法和步骤
1、通电前先用万用表欧姆档(1KΩ档)测量电源两端正反向电阻,正向电阻约80KΩ,反向电阻约6.5KΩ。如果电阻很小,则说明有短路性故障,不能通电,排除短路故障后才能通电,如果电阻为无穷大,则有开路性故障。
2、通电后,测量单片机40脚与20脚之间的电压应该有5V左右,如果电压不正常,则说明单片机供电不正常,应重点检查单片机供电电路。
3、测量单片机晶振引脚18和19脚电压,应该在1.9~2.3V左右,两个引脚电压相差0.2V左右,如果这两个引脚电压不正常,说明晶振电路没有起振,重点检查晶振和补偿电容是否焊接好。
4、测量单片机复位引脚9脚,正常工作时电压为0V,按复位键时为5V,松开手后由5V逐渐降至0V。如果该脚电压不正常,说明复位电路有故障,需要检查该脚的电阻、电容的连接和焊接是否正确。
5、以上步骤的测量如果正常,则多数是单片机的软件问题,可以通过编写几个小程序单独调试I/O口、按键、数码管和存储器的功能,测试到底是软件问题还是硬件问题。
六、C语言程序
  1. /********************************/
  2. /* 智能秒表(使用内部EEPROM)*/
  3. /*--------------------------------------------*/
  4. /**(1)启动/停止功能         **/
  5. /**(2)复位/间隔功能          **/
  6. /**(3)两种工作模式           **/
  7. /**(4)查看数据功能           **/
  8. /**(5)断电记忆功能           **/
  9. /********************************/
  10. #include <reg52.h>
  11. #include <intrins.h>
  12. #define uint unsigned int
  13. #define uchar unsigned char

  14. #define RdCommand 0x01                             //定义内部EEPROM存储器部分
  15. #define PrgCommand 0x02
  16. #define EraseCommand 0x03
  17. #define Error 1
  18. #define Ok 0
  19. #define WaitTime 0x01
  20. sfr ISP_DATA=0xe2;
  21. sfr ISP_ADDRH=0xe3;
  22. sfr ISP_ADDRL=0xe4;
  23. sfr ISP_CMD=0xe5;
  24. sfr ISP_TRIG=0xe6;
  25. sfr ISP_CONTR=0xe7;

  26. sbit key1=P2^0;                //定义"启动/暂停"按钮
  27. sbit key2=P2^1;                //定义"复位"按钮
  28. sbit key3=P2^2;                                                        //定义"模式"按钮
  29. sbit key4=P2^3;                                                        //定义"查看"按钮
  30. sbit key5=P1^5;                                                        //定义"清除"按钮

  31. sbit wei1=P2^4;                                                        //定义位选
  32. sbit wei2=P2^5;
  33. sbit wei3=P2^6;              
  34. sbit wei4=P2^7;

  35. bit flag_start,flag_mode,flag_2sec,flag_CLR;
  36. uchar temp,temp1,aa,aa1,shi,ge,shifen,baifen,num,i=0;
  37. uchar time_data1[11],time_data2[11];
  38. uchar code table[]={                              //共阴极数码管编码
  39. 0x3f,0x06,0x5b,0x4f,
  40. 0x66,0x6d,0x7d,0x07,
  41. 0x7f,0x6f,0x77,0x7c,
  42. 0x39,0x5e,0x79,0x71,0x40};      

  43. void display(uchar shi,uchar ge,uchar shifen,uchar baifen);  //声明显示子函数
  44. void delay(uint z);           //声明延时子函数
  45. void init();                  //声明初始化函数
  46. void key();                                                          //声明键扫描函数
  47. void display_process();                              //声明显示处理函数
  48. void delayus();                                            //声明延时微秒函数                                          
  49. void data_read();                                            //声明内部EEPROM数据读出函数
  50. void clear();                                                          //声明清除EEPROM数据函数

  51. void ISP_IAP_enable(void);                //声明EEPROM操作函数
  52. void ISP_IAP_disable(void);
  53. void ISPgoon(void);
  54. uchar byte_read(uint byte_addr);
  55. void SectorErase(uint sector_addr);
  56. void byte_write(uint byte_addr, uchar original_data);
  57. void memory_read();                                            //声明EEPROM读函数
  58. void memory_write();                                   //声明EEPROM写函数

  59. void main()                                                                        //主函数
  60. {            
  61.               init();                                //调用初始化子程序
  62.               while(1)
  63.               {                           
  64.                 key();                                                                                       //调用按键扫描函数
  65.                 if(num==0&&i!=0)                                             //如果一开机就按查看键
  66.                   memory_read();                                             //调用EEPROM数据读出函数
  67.                 if(flag_CLR==1)                                                           //如果按了清除键
  68.                             clear();                                                                         //调用清除EEPROM数据函数
  69.                 display_process();                                             //调用显示处理函数
  70.                 display(shi,ge,shifen,baifen);      //调用显示函数   
  71.               }
  72. }

  73. void delay(uint z)                     //延时毫秒函数
  74. {
  75.               uint x,y;
  76.               for(x=z;x>0;x--)
  77.                             for(y=110;y>0;y--);
  78. }

  79. void display(uchar shi,uchar ge,uchar shifen,uchar baifen)   //显示程序
  80. {            
  81.                             P0=table[shi];        //使用动态扫描的方法实现数码管显示
  82.                             wei1=0;
  83.                             delay(1);
  84.                             wei1=1;

  85.                             if(flag_CLR==0)                              //正常显示时,第二位显示小数点
  86.                               P0=table[ge]|0x80;
  87.                             else                                                              //按清除键时,不显示小数点
  88.                               P0=table[ge];
  89.                             wei2=0;
  90.                             delay(1);            
  91.                             wei2=1;

  92.         P0=table[shifen];      //使用动态扫描的方法实现数码管显示
  93.                             wei3=0;
  94.                             delay(1);
  95.                             wei3=1;

  96.                             P0=table[baifen];
  97.                             wei4=0;
  98.                             delay(1);            
  99.                             wei4=1;            
  100. }

  101. void init()                        //初始化子程序
  102. {            
  103.               temp=0;
  104.               TMOD=0x01;                //使用定时器T0的方式1
  105.               TH0=(65536-10000)/256;
  106.               TL0=(65536-10000)%256;      //定时10ms中断一次
  107.               EA=1;                       //中断总允许
  108.               ET0=1;                      //允许定时器T0中断            
  109. }

  110. void key()                                                                                    //按键扫描函数
  111. {
  112.               uchar j;
  113.               if(key1==0)                 //检测"启动"按钮是否按下
  114.               {
  115.                             delay(5);                 //延时去抖动
  116.                             if(key1==0)             //再次检测"启动"按钮是否按下
  117.                             {            
  118.            while(!key1)         //松手检测(按下时数码管不灭)
  119.                                 {
  120.                                             display_process();                                          //调用显示处理函数
  121.                         display(shi,ge,shifen,baifen);  //调用显示函数
  122.                                           }
  123.                                flag_start=~flag_start;
  124.                                if(flag_start==1)
  125.                                           TR0=1;                    //启动定时器开始工作
  126.                                else
  127.                                           TR0=0;
  128.                             }
  129.               }
  130.                             if(key2==0)                    //检测"间隔"按钮是否按下  
  131.                             {
  132.                                           delay(5);        
  133.                                           if(key2==0)      
  134.                                           {            
  135.                                                         while(!key2)                                                                      //松手检测
  136.                                                         {
  137.                                                         display_process();                                              //调用显示处理函数
  138.                            display(shi,ge,shifen,baifen);   //调用显示函数
  139.                                                         }
  140.                                                         if(flag_mode==0||i!=0)
  141.                                                         {
  142.                                                           shi=0;            
  143.                                                           ge=0;
  144.                                                           shifen=0;
  145.                                                           baifen=0;
  146.                                                           aa=0;
  147.                                                           temp=0;
  148.                                                           TR0=0;
  149.                                                           i=0;
  150.                                                           num=0;
  151.                                                           for(j=0;j<=10;j++)
  152.                                                           {
  153.                                                             time_data1[j]=0;
  154.                                                             time_data2[j]=0;
  155.                                                           }
  156.                                                         }
  157.                                               else
  158.                                                {
  159.                                                            num++;
  160.                                                            if(num==11)
  161.                                                              num=1;
  162.                                                            memory_write();
  163.                                                         }
  164.                                           }
  165.                             }
  166.                             if(key3==0)
  167.                             {
  168.                               delay(5);
  169.                               if(key3==0)
  170.                                {
  171.                                  while(!key3)                                                                          //松手检测
  172.                                             {
  173.                                                         display_process();                                              //调用显示处理函数
  174.                           display(shi,ge,shifen,baifen);    //调用显示函数
  175.                                             }
  176.                                           flag_mode=~flag_mode;
  177.                                }
  178.                             }
  179.                  if(key4==0)
  180.                             {
  181.                               delay(5);
  182.                               if(key4==0)
  183.                                {
  184.                                  while(!key4)                                                                          //松手检测
  185.                                             {
  186.                                               display_process();                                              //调用显示处理函数
  187.                           display(shi,ge,shifen,baifen);    //调用显示函数
  188.                                             }
  189.                                           TR0=0;
  190.                                           i++;
  191.                                           if(i==11)
  192.                                             i=1;
  193.                                           data_read();
  194.                                }
  195.                             }
  196.                  if(key5==0)
  197.                             {
  198.                               delay(5);
  199.                               if(key5==0)
  200.                                {
  201.                                  while(!key5)                                                                          //松手检测
  202.                                             {
  203.                                               display_process();                                              //调用显示处理函数
  204.                           display(shi,ge,shifen,baifen);    //调用显示函数
  205.                                             }
  206.                                           flag_CLR=~flag_CLR;
  207.                                }
  208.                             }
  209. }                           

  210. void display_process()                                  //显示处理函数
  211. {
  212.   shifen=aa%100/10;                                                                                    //正常走秒的处理
  213.   baifen=aa%10;
  214.   shi=temp%100/10;
  215.   ge=temp%10;
  216.   if(flag_mode==1&&num!=0&&flag_2sec==0)              //间隔2秒停顿的处理
  217.    {
  218.               shi=time_data2[num]/10;
  219.      ge=time_data2[num]%10;
  220.               shifen=time_data1[num]/10;
  221.               baifen=time_data1[num]%10;
  222.               if(temp-time_data2[num]==2)
  223.                  flag_2sec=~flag_2sec;
  224.    }
  225.   if(i!=0)                                                                                                                    //查看存储数据的处理
  226.               {
  227.                 shi=time_data2[i]/10;
  228.                 ge=time_data2[i]%10;
  229.                 shifen=time_data1[i]/10;
  230.                 baifen=time_data1[i]%10;
  231.     }
  232. }

  233. void timer0() interrupt 1                      //定时器T0中断服务函数
  234. {
  235.               TH0=(65536-10000)/256;   //重新赋初值
  236.               TL0=(65536-10000)%256;
  237.               aa++;                    //中断一次10ms变量aa的值加1
  238.               if(aa==100)              //中断100次后,定时时间100*10ms=1000ms=1s,变量temp的值加1
  239.               {
  240.                 aa=0;
  241.                 temp++;
  242.                 if(temp==100)          //秒表到达100s后回零
  243.                             temp=0;
  244.               }            
  245. }

  246. /* EEPROM存储器操作函数 */
  247. /* ================================= */
  248. void ISP_IAP_enable(void)
  249. {
  250. EA = 0;     
  251. ISP_CONTR = ISP_CONTR & 0x18;      
  252. ISP_CONTR = ISP_CONTR | WaitTime;
  253. ISP_CONTR = ISP_CONTR | 0x80;      
  254. }
  255. /* ================================= */
  256. void ISP_IAP_disable(void)
  257. {
  258. ISP_CONTR=ISP_CONTR&0x7f;
  259. ISP_TRIG=0x00;
  260. EA=1;  
  261. }
  262. /* ==================================== */
  263. void ISPgoon(void)
  264. {
  265. ISP_IAP_enable();  
  266. ISP_TRIG = 0x46;
  267. ISP_TRIG = 0xb9;
  268. _nop_();
  269. }
  270. /* ============================================ */
  271. uchar byte_read(uint byte_addr)
  272. {
  273. ISP_ADDRH = (uchar)(byte_addr >> 8);
  274. ISP_ADDRL = (uchar)(byte_addr & 0x00ff);
  275. ISP_CMD   = ISP_CMD & 0xf8;  
  276. ISP_CMD   = ISP_CMD | RdCommand;
  277. ISPgoon();      
  278. ISP_IAP_disable();  
  279. return (ISP_DATA);  
  280. }
  281. /* ========================================== */
  282. void SectorErase(uint sector_addr)
  283. {
  284. uint iSectorAddr;
  285. iSectorAddr = (sector_addr & 0xfe00);
  286. ISP_ADDRH   = (uchar)(iSectorAddr >> 8);
  287. ISP_ADDRL   = 0x00;
  288. ISP_CMD     = ISP_CMD & 0xf8;  
  289. ISP_CMD     = ISP_CMD | EraseCommand;
  290. ISPgoon();      
  291. ISP_IAP_disable();  
  292. }
  293. /* ============================================ */
  294. void byte_write(uint byte_addr, uchar original_data)
  295. {
  296. ISP_ADDRH = (uchar)(byte_addr >> 8);
  297. ISP_ADDRL = (uchar)(byte_addr & 0x00ff);
  298. ISP_CMD   = ISP_CMD & 0xf8;   
  299. ISP_CMD   = ISP_CMD | PrgCommand;
  300. ISP_DATA  = original_data;
  301. ISPgoon();     
  302. ISP_IAP_disable();   
  303. }

  304. void data_read()                                                                      //读数组数据函数
  305. {
  306.   aa=time_data1[i];
  307.   temp=time_data2[i];
  308. }

  309. void memory_write()                                                                        //写EEPROM数据函数
  310. {
  311.   aa1=aa;
  312.   temp1=temp;
  313.   time_data1[num]=aa1;
  314.   time_data2[num]=temp1;
  315.   if(num==1)
  316.     SectorErase(0x2000);              //擦除扇区
  317.   byte_write(0x2000+num,aa1);         //重新写入数据
  318.   byte_write(0x2000+num+10,temp1);    //重新写入数据   
  319.   flag_2sec=0;


  320. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码


完整论文下载(word格式 可编辑)还带仿真和源码:



评分

参与人数 1黑币 +10 收起 理由
话梅 + 10 很给力!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏4 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:569720 发表于 2019-6-22 21:25 | 只看该作者
厉害,很有用,收获很多
回复

使用道具 举报

板凳
ID:757221 发表于 2020-6-17 15:26 | 只看该作者
作者说的模式二,大家知道怎么运行吗?
回复

使用道具 举报

地板
ID:757221 发表于 2020-6-17 15:31 | 只看该作者
作者说的模式二,大家有知道怎么运行的吗?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表