51单片机秒表系统的设计 | 珊瑚贝

这个本来是帮同学做的期末设计,后来那位同学自己做出来了,因此就没用我这个……

为了便于同学读懂代码,里面几乎每一行都加了注释,依旧分享出来,希望对需要的人有所帮助。

这个设计的原题要求如下:

1.设计一个精度为0.1s的秒表系统。

2.设计启动按钮、暂停按钮及清零按钮。

3*.设计每到一秒钟有声音提醒功能,可通过按钮打开及关闭该提醒音。

运行图如下:

51单片机秒表系统的设计

程序代码如下:

代码太长,已被折叠。点击展开查看
  1. /************************************************************************************************** 
  2. 模块名称:51单片机简易秒表
  3. 模块功能:实现精确到毫秒的简易秒表 
  4. 编写人员:mengkun  (http://mkblog.cn) 
  5. 编写日期:2016/12/18 
  6. **************************************************************************************************/
  7. #include <reg51.h>
  8. #define false 0
  9. #define true 1
  10. #define uchar unsigned char  //0——255
  11. #define uint unsigned int           //0——65535
  12. #define ulong unsigned long //0——4294967295
  13. sbit start_key = P3^0;  //启动按钮
  14. sbit pause_key = P3^1;  //暂停按钮
  15. sbit reset_key = P3^2;  //重置按钮
  16. sbit beep_key = P3^3;   //声音按钮
  17. sbit start_led = P3^4;      //启动指示灯
  18. sbit pause_led = P3^5;      //暂停指示灯
  19. sbit beep_led = P3^6;       //喇叭指示灯
  20. sbit beep = P3^7;               //喇叭
  21. uchar disCode[10] = {0x03,0x9f,0x25,0x0d,0x99,0x49,0x41,0x1f,0x01,0x09}; //数码管段码 0~9
  22. uchar locCode[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};                   //位码
  23. void displayTime(void);  //刷新时间显示
  24. void disPlay(uchar num, uchar loc);  //数码管、led显示函数
  25. void Delay1ms(unsigned int n);  //延时1ms
  26. uchar state;    //状态:0-停止,1-启动,2-暂停
  27. ulong ms = 0;   //存储毫秒值
  28. uchar fen = 0;  //分钟数
  29. uchar miao; //秒数
  30. uchar ms2;  //毫秒数的10位
  31. bit isBeep = false//是否开启蜂鸣器
  32. /******************************************************************************* 
  33. * 函 数 名          : T0_INT
  34. * 函数功能         : T0定时器中断函数10ms
  35. * 输      入         : 无
  36. * 输      出         : 无 
  37. *******************************************************************************/
  38. void T0_INT(void)  interrupt 1
  39. {
  40.     //这里不是减去10000是因为在C51单片机中,每执行一条语句需要花费 1ms 时间。减去的是误差值。
  41.     //经过测试,大概每一分钟还是会有 0.8 s的误差……
  42.     //实际的秒表还是得专业的时钟芯片
  43.     TL0= (65536-9000)/256;
  44.     TH0= (65536-9000)%256;
  45.     ms ++;
  46. }
  47. /******************************************************************************* 
  48. * 函 数 名          : main
  49. * 函数功能         : 主函数
  50. * 输      入         : 无
  51. * 输      出         : 无 
  52. *******************************************************************************/
  53. void main(void)
  54. {
  55.     TMOD=0x61; //0110 0001  //方式一
  56.     TL0= (65536-10000)/256;     // 10ms
  57.     TH0= (65536-10000)%256;
  58.     TR0=1;      //开启T0
  59.     //ET0=1;        //T0中断允许(要在点击了启动按钮在开启,所以这里不需要开启)
  60.     EA=1;   //总中断开启
  61.     //以下指示灯一开始都应该是灭的
  62.     start_led = 0;      //启动指示灯
  63.     pause_led = 0;      //暂停指示灯
  64.     beep_led = 0;       //喇叭指示灯
  65.     while(1)
  66.     {
  67.         displayTime();   //刷新时间显示
  68.         //检测启动、停止按钮
  69.         if(start_key == 0)   //按下了启动、停止按钮
  70.         {
  71.             Delay1ms(10);   //延时消抖
  72.             if(start_key == 0)
  73.             {
  74.                 if(state == 0)//之前是未启动,按了按钮要变成已启动
  75.                 {
  76.                     state = 1;  //更新状态为已启动
  77.                     ms = 0;     //毫秒数归零
  78.                     fen = 0;    //分钟数归零
  79.                     ET0 = 1;        //T0中断允许打开,开始计时
  80.                     start_led = 1;  //启动led指示灯亮
  81.                 }else{
  82.                     state = 0;      //更新状态为未启动
  83.                     ET0 = 0;        //关闭T0中断,停止计时
  84.                     start_led = 0;  //启动led指示灯灭
  85.                     pause_led = 0;  //暂停指示灯灭
  86.                 }
  87.                 while(start_key == 0) displayTime();    //防止按键重复检测
  88.             }
  89.         }
  90.         //检测暂停按钮
  91.         if(state != 0 && pause_key == 0)    //已启动计时,并且暂停按钮按下
  92.         {
  93.             Delay1ms(10);   //延时消抖
  94.             if(pause_key == 0)
  95.             {
  96.                 if(state == 2)  //之前是暂停,现在要启动
  97.                 {
  98.                     state = 1;      //更新状态为已启动
  99.                     pause_led = 0;  //暂停指示灯灭
  100.                     ET0 = 1;        //打开T0中断允许,恢复计时
  101.                 }else{
  102.                     state = 2;
  103.                     pause_led = 1;  //暂停指示灯亮起
  104.                     ET0 = 0;        //关闭T0定时器,暂停计时
  105.                 }
  106.                 while(pause_key == 0) displayTime();    //防止按键重复检测
  107.             }
  108.         }
  109.         //检测归零按钮
  110.         if(state == 0 && reset_key == 0)    //已停止计时,并且归零按钮按下
  111.         {
  112.             Delay1ms(10);   //延时消抖
  113.             if(reset_key == 0)
  114.             {
  115.                 ms = 0;     //毫秒数归零
  116.                 fen = 0;    //分钟数归零
  117.                 while(reset_key == 0) displayTime();    //防止按键重复检测
  118.             }
  119.         }
  120.         //检测声音按钮
  121.         if(beep_key == 0)   //归零按钮按下
  122.         {
  123.             Delay1ms(10);   //延时消抖
  124.             if(beep_key == 0)
  125.             {
  126.                 isBeep = ~isBeep;   //取反,原来是开启的,变为关闭。原来是关闭的则变为开启
  127.                 beep_led = isBeep;  //更新声音指示灯
  128.                 while(beep_key == 0) displayTime(); //防止按键重复检测
  129.             }
  130.         }
  131.     }
  132. }
  133. void displayTime(void)   //刷新时间显示
  134. {
  135.     miao = ms/100 – fen*60; //秒数
  136.     ms2 = ms/10%10; //毫秒数的10位
  137.     //已启动计时,并且开启了声音     并且处于一秒刚开始的0.1秒内(即新的一秒刚刚开始)
  138.     if(state == 1 && isBeep == true && ms2 < 1)
  139.     {
  140.         beep = 0;       //蜂鸣器发出响声
  141.     }else{
  142.         beep = 1;       //关闭蜂鸣器
  143.     }
  144.     if(miao >= 60)  //秒数大于60
  145.     {
  146.         miao = 0;
  147.         fen++;      //分钟数加一
  148.     }
  149.     disPlay(fen/10, 0);     //显示分钟数的十位
  150.     disPlay(fen%10, 1);  //显示分钟数的个位
  151.     disPlay(miao/10, 2);     //显示秒数的十位
  152.     disPlay(miao%10, 3);     //显示秒数的个位
  153.     disPlay(ms2, 4);            //0.1s
  154.     disPlay(ms%10, 5);   //0.01s
  155. }
  156. void disPlay(uchar num, uchar loc)   //数码管、led显示函数
  157. {
  158.     P0 = 0xff;  //消除重影
  159.     P2 = locCode[loc];  //位码输出
  160.     P0 = disCode[num];  //段码输出
  161.     Delay1ms(1);    //增加显示时间,防止显示过暗
  162. }
  163. /******************************************************************************* 
  164. * 函 数 名          : Delay1ms (多个) 
  165. * 函数功能         : 延时函数,延时n*1ms 
  166. * 输      入         : n-延时次数 
  167. * 输      出         : 无 
  168. *******************************************************************************/
  169. void Delay1ms(unsigned int n)
  170. {
  171.     unsigned char i, j;
  172.     for (; n>0; n–)
  173.         for(i=0;i<10;i++)
  174.             for(j=0;j<33;j++);
  175. }

完整proteus仿真图如下:

51单片机秒表系统的设计

程序和仿真图打包下载:

下载地址

来源:https://mkblog.cn/497/

微信公众号
手机浏览(小程序)
0
分享到:
没有账号? 忘记密码?