找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4189|回复: 0
收起左侧

51单片机秒表Protues仿真+AD PCB文件和代码分享

[复制链接]
ID:387939 发表于 2018-12-2 13:25 | 显示全部楼层 |阅读模式
51单片机秒表仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
0.jpg

Altium Designer画的秒表电路原理图和PCB图如下:(51hei附件中可下载工程文件)
0.png 0.png

单片机源程序如下:
  1. #include<reg52.h>
  2. #include<intrins.h>
  3. //1602定义
  4. sbit RS = P2^7;   //定义端口
  5. sbit RW = P2^6;
  6. sbit EN = P2^5;

  7. #define RS_CLR RS=0 //状态量定义,方便读取代码
  8. #define RS_SET RS=1

  9. #define RW_CLR RW=0
  10. #define RW_SET RW=1

  11. #define EN_CLR EN=0
  12. #define EN_SET EN=1

  13. #define DataPort P0        //1602数据接口
  14. //按键定义
  15. sbit key1=P1^3;                        //Up
  16. sbit key2=P1^2;                        //Down
  17. sbit key3=P1^1;                        //Start/Stop
  18. sbit key4=P1^4;                        //Record
  19. //蜂鸣器定义,用于提示计时超时
  20. sbit Beep=P1^0;                        //1时不响,0时响
  21. //全局变量定义
  22. unsigned int         RecordTableH[11];                //保存分和秒
  23. unsigned char RecordTableL[11];                //保存毫秒
  24. unsigned int        CountTimeH;                                        //记录分、秒时间
  25. unsigned char        CountTimeL;                                        //记录毫秒时间
  26. unsigned char DataRecordFlag = 0;        //数据记录标志位,表示记录的数据量(记录了多少个数据)
  27. unsigned char DataFlag = 0;                                //保存数据标志,用于记录保存数据的个数

  28. code unsigned char NumTable[]="0123456789";

  29. bit Counting = 0;                                //计时标志0暂停/停止,1计时状态
  30. //函数声明
  31. void LCD1602_WriteCom(unsigned char com);                         //1602部分
  32. void LCD1602_WriteData(unsigned char Data);
  33. void LCD1602_Clear(void);
  34. void LCD1602_PutString(unsigned char x,unsigned char y,unsigned char *s);
  35. void LCD1602_PutChar(unsigned char x,unsigned char y,unsigned char Data);
  36. void LCD1602_Init(void);
  37. void LCD1602_Delay(unsigned int t);

  38. void delay_ms(unsigned int t);
  39. void IniTC0(void) ;                                                //初始化定时计数器0
  40. void KeyWork(void);                                                //按键扫描以及按键功能动作
  41. void DisplayCountTime(void);        //显示计时的时间

  42. void main()
  43. {
  44.         IniTC0();
  45.         LCD1602_Init();
  46.         Beep = 1;
  47.         
  48.         LCD1602_PutString(4,0,"Well Come");                        //开机欢迎可不要
  49.         LCD1602_PutString(2,1,"Time Counter");
  50.         delay_ms(1000);
  51.         LCD1602_Clear();
  52.         
  53.         while(1)
  54.         {
  55.                 DisplayCountTime();
  56.                 KeyWork();
  57.         }
  58. }
  59. /*------------------------------------------------
  60.               写入命令函数
  61. ------------------------------------------------*/
  62. void LCD1602_WriteCom(unsigned char com)
  63. {
  64.         LCD1602_Delay(5);
  65.         RS_CLR;
  66.         RW_CLR;
  67.         EN_SET;
  68.         DataPort= com;
  69.         _nop_();
  70.         EN_CLR;
  71. }
  72. /*------------------------------------------------
  73.               写入数据函数
  74. ------------------------------------------------*/
  75. void LCD1602_WriteData(unsigned char Data)
  76. {
  77.         LCD1602_Delay(5);
  78.         RS_SET;
  79.         RW_CLR;
  80.         EN_SET;
  81.         DataPort= Data;
  82.         _nop_();
  83.         EN_CLR;
  84. }
  85. /*------------------------------------------------
  86.                 清屏函数
  87. ------------------------------------------------*/
  88. void LCD1602_Clear(void)
  89. {
  90. LCD1602_WriteCom(0x01);
  91. LCD1602_Delay(5);
  92. }
  93. /*------------------------------------------------
  94.               写入字符串函数
  95. ------------------------------------------------*/
  96. void LCD1602_PutString(unsigned char x,unsigned char y,unsigned char *s)
  97. {     
  98.         if (y == 0)
  99.         {     
  100.                 LCD1602_WriteCom(0x80 + x);     //表示第一行
  101.         }
  102.         else
  103.         {      
  104.                 LCD1602_WriteCom(0xC0 + x);      //表示第二行
  105.         }        
  106.         while (*s)
  107.         {     
  108.                 LCD1602_WriteData( *s);     
  109.                 s ++;     
  110.         }
  111. }
  112. /*------------------------------------------------
  113.               写入字符函数
  114. ------------------------------------------------*/
  115. void LCD1602_PutChar(unsigned char x,unsigned char y,unsigned char Data)
  116. {     
  117.         if (y == 0)
  118.         {     
  119.                 LCD1602_WriteCom(0x80 + x);     
  120.         }else {     
  121.                 LCD1602_WriteCom(0xC0 + x);     
  122.         }        
  123.         LCD1602_WriteData( Data);  
  124. }
  125. /*------------------------------------------------
  126.               初始化函数
  127. ------------------------------------------------*/
  128. void LCD1602_Init(void)
  129. {
  130.         LCD1602_WriteCom(0x38);    /*显示模式设置*/
  131.         LCD1602_Delay(5);
  132.         LCD1602_WriteCom(0x38);
  133.         LCD1602_Delay(5);
  134.         LCD1602_WriteCom(0x38);
  135.         LCD1602_Delay(5);
  136.         LCD1602_WriteCom(0x38);  
  137.         LCD1602_WriteCom(0x08);    /*显示关闭*/
  138.         LCD1602_WriteCom(0x01);    /*显示清屏*/
  139.         LCD1602_WriteCom(0x06);    /*显示光标移动设置*/
  140.         LCD1602_Delay(5);
  141.         LCD1602_WriteCom(0x0C);    /*显示开及光标设置*/
  142.         LCD1602_Clear();
  143. }
  144. /*------------------------------------------------
  145.                                                         1602延时函数
  146. ------------------------------------------------*/
  147. void LCD1602_Delay(unsigned int t)
  148. {
  149.         unsigned char c;
  150.         while(t--)
  151.         {
  152.                 for(c = 50; c > 0; c--);
  153.         }
  154. }
  155. void delay_ms(unsigned int t)
  156. {
  157.         unsigned char c;
  158.         while(t--)
  159.         {
  160.                 for(c = 50; c > 0; c--);
  161.         }
  162. }
  163. void IniTC0(void)        
  164. {
  165.         TMOD=0x01;                //设置定时计数器的工作模式
  166.         TR0 = 0;                        //关闭定时计数器
  167.         TF0 = 0;                        //清空定时计数器标志位
  168.         
  169.         TH0=0xFC;                                 //定时1ms,当计时时间不准在这修改
  170.         TL0=0x18;
  171.         
  172.         ET0 = 1;                        //开启定时计数器0中断
  173.         EA=1;                                 //开总中断
  174. }
  175. void KeyWork(void)                                        //判断按键按下就动作,提高实时性
  176. {
  177.         if(key1 == 0)                                                                        //显示上一条记录,只有在不计时时有效
  178.         {
  179.                 if(!Counting && DataRecordFlag != 0)//只有不在计时,并且有数据时才能察看(DataRecordFlag表示记录的数据条数)
  180.                 {
  181.                         DataFlag++;
  182.                         if(DataFlag >= DataRecordFlag)
  183.                         {
  184.                                 DataFlag = DataRecordFlag;
  185.                         }
  186.                         if(DataFlag >= 10)
  187.                         {               
  188.                                 LCD1602_PutString(0,1,"10:             ");//显示条数并且把后面的显示清空
  189.                         }else {
  190.                                 LCD1602_PutChar(0, 1, NumTable[DataFlag]);
  191.                                 LCD1602_PutString(1,1,":              ");
  192.                         }
  193.                         LCD1602_PutChar(4, 1, NumTable[(RecordTableH[DataFlag]/60)/10]);                //显示记录的时间
  194.                         LCD1602_PutChar(5, 1, NumTable[(RecordTableH[DataFlag]/60)%10]);
  195.                         LCD1602_PutChar(6, 1, ':');
  196.                         LCD1602_PutChar(7, 1, NumTable[(RecordTableH[DataFlag]%60)/10]);
  197.                         LCD1602_PutChar(8, 1, NumTable[(RecordTableH[DataFlag]%60)%10]);
  198.                         LCD1602_PutChar(9, 1, ':');
  199.                         LCD1602_PutChar(10, 1, NumTable[RecordTableL[DataFlag]/10]);
  200.                         LCD1602_PutChar(11, 1, NumTable[RecordTableL[DataFlag]%10]);
  201.                 }
  202.                 delay_ms(5);                                                //避开抖动防止多次触发,期间继续显示计数时间
  203.                 while(!key1)
  204.                         DisplayCountTime();                                        //等待按键释放,避开抖动防止多次触发,期间继续显示计数时间
  205.         }
  206.         if(key2 == 0)                                                                        //显示下一条记录,只有在不计时时有效
  207.         {
  208.                 if(!Counting && DataRecordFlag != 0)//只有不在计时,并且有数据时才能察看(DataRecordFlag表示记录的数据条数)
  209.                 {
  210.                         DataFlag--;
  211.                         if(DataFlag == 0)
  212.                         {
  213.                                 DataFlag = 1;
  214.                         }
  215.                         LCD1602_PutChar(0, 1, NumTable[DataFlag]);//显示条数并且把后面的显示清空
  216.                         LCD1602_PutString(1,1,":              ");
  217.                         
  218.                         LCD1602_PutChar(4, 1, NumTable[(RecordTableH[DataFlag]/60)/10]);                //显示记录的时间
  219.                         LCD1602_PutChar(5, 1, NumTable[(RecordTableH[DataFlag]/60)%10]);
  220.                         LCD1602_PutChar(6, 1, ':');
  221.                         LCD1602_PutChar(7, 1, NumTable[(RecordTableH[DataFlag]%60)/10]);
  222.                         LCD1602_PutChar(8, 1, NumTable[(RecordTableH[DataFlag]%60)%10]);
  223.                         LCD1602_PutChar(9, 1, ':');
  224.                         LCD1602_PutChar(10, 1, NumTable[RecordTableL[DataFlag]/10]);
  225.                         LCD1602_PutChar(11, 1, NumTable[RecordTableL[DataFlag]%10]);
  226.                 }
  227.                 delay_ms(5);                                                //避开抖动防止多次触发,期间继续显示计数时间
  228.                 while(!key2)
  229.                         DisplayCountTime();                                        //等待按键释放,避开抖动防止多次触发,期间继续显示计数时间
  230.         }
  231.         if(key3 == 0)                                                //开始/停止计时
  232.         {
  233.                 Counting = !Counting;                //切换计时状态并进行相应地动作
  234.                 if(Counting)
  235.                 {
  236.                         TR0 = 1;                        //开启定时器计数,开始计时
  237.                 }else {
  238.                         TR0 = 0;                        //关闭定时几计数,停止计时
  239.                 }
  240.                 delay_ms(5);                                                //避开抖动防止多次触发,期间继续显示计数时间
  241.                 while(!key3)
  242.                         DisplayCountTime();                                        //等待按键释放,避开抖动防止多次触发,期间继续显示计数时间
  243.         }
  244.         if(key4 == 0)                                                                        //记录时间
  245.         {
  246.                 if(Counting)                        //在计时时才有用
  247.                 {
  248.                         DataRecordFlag++;
  249.                         DataFlag = DataRecordFlag;
  250.                         if(DataRecordFlag > 10)                //判断是否为第十条,第十条数据时进行记录,超过第十条时无动作需要复位
  251.                         {
  252.                                 DataRecordFlag = 10;
  253.                                 DataFlag = 10;
  254.                         }else {
  255.                                 if(DataRecordFlag == 10)
  256.                                 {
  257.                                         RecordTableH[DataFlag] = CountTimeH;
  258.                                         RecordTableL[DataFlag] = CountTimeL;
  259.                                         LCD1602_PutString(0,1,"10:             ");
  260.                                 }else {
  261.                                         LCD1602_PutChar(0, 1, NumTable[DataRecordFlag]);
  262.                                         LCD1602_PutString(1,1,":              ");
  263.                                         RecordTableH[DataFlag] = CountTimeH;
  264.                                         RecordTableL[DataFlag] = CountTimeL;
  265.                                 }
  266.                         }
  267.                         
  268.                         LCD1602_PutChar(4, 1, NumTable[(RecordTableH[DataRecordFlag]/60)/10]);                //显示记录的时间
  269.                         LCD1602_PutChar(5, 1, NumTable[(RecordTableH[DataRecordFlag]/60)%10]);
  270.                         LCD1602_PutChar(6, 1, ':');
  271.                         LCD1602_PutChar(7, 1, NumTable[(RecordTableH[DataRecordFlag]%60)/10]);
  272.                         LCD1602_PutChar(8, 1, NumTable[(RecordTableH[DataRecordFlag]%60)%10]);
  273.                         LCD1602_PutChar(9, 1, ':');
  274.                         LCD1602_PutChar(10, 1, NumTable[RecordTableL[DataRecordFlag]/10]);
  275.                         LCD1602_PutChar(11, 1, NumTable[RecordTableL[DataRecordFlag]%10]);
  276.                 }
  277.                 delay_ms(5);                                                //避开抖动防止多次触发,期间继续显示计数时间
  278.                 while(!key4)
  279.                         DisplayCountTime();                                        //等待按键释放,避开抖动防止多次触发,期间继续显示计数时间
  280.         }
  281. }
  282. void DisplayCountTime(void)
  283. {
  284.                 LCD1602_PutChar(4, 0, NumTable[(CountTimeH/60)/10]);                //显示计时的时间
  285.                 LCD1602_PutChar(5, 0, NumTable[(CountTimeH/60)%10]);
  286.                 LCD1602_PutChar(6, 0, ':');
  287.                 LCD1602_PutChar(7, 0, NumTable[(CountTimeH%60)/10]);
  288.                 LCD1602_PutChar(8, 0, NumTable[(CountTimeH%60)%10]);
  289.                 LCD1602_PutChar(9, 0, ':');
  290.                 LCD1602_PutChar(10, 0, NumTable[CountTimeL/10]);
  291.                 LCD1602_PutChar(11, 0, NumTable[CountTimeL%10]);
  292. }
  293. void timer0() interrupt 1
  294. {
  295.         TH0=0xFC;                                 //定时1ms
  296.         TL0=0x18;
  297.         
  298.         if(!(CountTimeL == 99 && CountTimeH == 3599))//判断是否到达计时最大值,到达59:59:99时无动作并且退出计时状态(毫秒的进制为100)
  299.         {
  300.                 CountTimeL++;
  301.                 if(CountTimeL > 99)                //毫秒的计数时间到达100时进1到秒
  302.                 {
  303.                         CountTimeL = 0;
  304.                         CountTimeH++;
  305.                         if(CountTimeH > 3599)                //设定计时最大值,计算方法为59*60+59(到达59分59秒时为最大值)
  306.                         {
  307.                                 CountTimeH = 3599;
  308.                                 Counting = 0;
  309.                         }
  310.                 }
  311.         }else {
  312.                 Counting = 0;                //计时标志位,为1时才开始计时
  313.                 Beep = 0;                                //蜂鸣器响一下
  314.                 delay_ms(5);
  315.                 Beep = 0;
  316.         }
  317. }
复制代码

所有资料51hei提供下载:
秒表+Protues+ADPCB.rar (674.47 KB, 下载次数: 81)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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