找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机设计秒表计时器,proteus仿真程序

[复制链接]
跳转到指定楼层
楼主
27,28两个按键用于控制时间的暂停和重新计数
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


单片机源程序如下:
  1. #include <reg51.h>
  2. #include <absacc.h>
  3. #include <intrins.h>

  4. #define BIT0  0x01
  5. #define BIT1  0x02
  6. #define BIT2  0x04
  7. #define BIT3  0x08
  8. #define BIT4  0x10
  9. #define BIT5  0x20
  10. #define BIT6  0x40
  11. #define BIT7  0x80

  12. #define KeyInPort   XBYTE[0xE800]
  13. #define KeyOutPort  XBYTE[0xEC00]  

  14. typedef unsigned int u16;          //对数据类型进行声明定义
  15. typedef unsigned char u8;

  16. u16 Timer0_flag = 0;
  17. u16 time100ms_cnt = 0;//100ms计数变量
  18.        
  19. u8 xdata smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,//0x00全灭
  20.                                         0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71, 0x00};//显示0~F的值,18不显示
  21. u8 xdata smgduan_num[] = { 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0xff};//0xff选中所有数码管

  22. u8 code KeyOutTAB[] = {

  23.      0xFF, // 凑数的
  24.     ~BIT0,
  25.     ~BIT1,
  26.     ~BIT2,
  27.     ~BIT3,
  28.     ~BIT4,
  29.     ~BIT5,
  30.           ~BIT6,
  31.     ~BIT7,   
  32. };

  33. u8 code conKeyFunCode[] = {
  34.    3, // 凑数
  35.    0x81,// 0
  36.          0x22,// 1
  37.    0x42,// 2
  38.    0x82,// 3
  39.    0x83,// 4
  40.    0x43,// 5
  41.    0x23,// 6
  42.    0x84,// 7
  43.    0x44,// 8
  44.    0x24,// 9
  45.    0x14,// A
  46.    0x13,// B
  47.    0x12,// C
  48.    0x11,// D
  49.    0x21,// E
  50.    0x41,// F
  51.    0x00,// 空键 16
  52.    0x85,// 17
  53.    0x45,// 18
  54.    0x25,// 19
  55.    0x15,// 20
  56.    0x86,// 21
  57.    0x46,// 22
  58.    0x26,// 23
  59.    0x16,// 24
  60.    0x0C,// 25
  61.    0x0B,// 26
  62.    0x0A,// 27
  63.    0x09,// 28

  64. };
  65. u16 smgduan_addr     = 0XE3FF;   //E3FF是PS0的地址,段码的8位数据
  66. u16 smgduan_num_addr = 0XE7FF;   //E7FF是PS1的地址,选择那一个数码管亮
  67. u16 key_out_addr     = 0XEFFF;   //EFFF是PS3的地址,矩阵按键输出地址
  68. u16 key_in_addr      = 0XEBFF;   //EBFF是PS2的地址,矩阵按键读地址


  69. u8 Key_Flag = 0;
  70. u8 Sys_Key = 0; // 键值存放在这里
  71. u8 duanma_mode = 0;
  72. u8 preKey = 0;
  73. u8 curKey = 0;
  74. u8 SameKeyNum = 0;

  75.           bit Flag_1ms = 0;
  76. unsigned char Cnt_1ms  = 0;

  77.           bit Flag_10ms = 0;
  78. unsigned char Cnt_10ms  = 0;

  79.           bit Flag_100ms = 0;
  80. unsigned char Cnt_100ms  = 0;

  81.           bit Flag_1s = 0;
  82. unsigned char Cnt_1s  = 0;         
  83.          

  84. void Fun_KeyScan( void ){
  85.    
  86.     unsigned char Temp = 0;
  87.     unsigned char LineNum = 0;
  88.    
  89.     // 1、获取键值
  90.      for( LineNum = 6; LineNum > 0; LineNum-- ){
  91.         KeyOutPort = KeyOutTAB[LineNum];  // 输出
  92.         Temp  = KeyInPort;           // 读取
  93.         Temp  = ~Temp;               // 取反,有按下的是低电平
  94.         Temp &= 0x1F;                // 屏蔽,0001 1111
  95.         if( Temp ){                  // 如果有键按下
  96.             break;                   // 则跳出循环
  97.         }                            // 否则继续扫描
  98.     }
  99.    
  100.     // 2、拼合键值
  101.     Temp <<= 3;//左移3位
  102.     Temp |= LineNum;//6 = 110B
  103.    
  104.     // 3、获取功能码               
  105.     for( LineNum = 29; LineNum > 0; LineNum-- ){//一共30个数,但是第一个数是无效数,从29扫描到1
  106.         if( Temp == conKeyFunCode[ LineNum ] ){
  107.             break;
  108.         }
  109.     }
  110.    
  111.     if( LineNum > 0 ){ LineNum--; }
  112.    
  113.     // 4、数字滤波
  114.     curKey = LineNum;
  115.     if( curKey != preKey ){//判断下一次扫描的是不是还是上一个按键
  116.         preKey = curKey;
  117.         SameKeyNum = 0;
  118.     }
  119.     else{
  120.         SameKeyNum++;
  121.         if( SameKeyNum == 30 ){ Key_Flag = 1; Sys_Key = curKey; }
  122.         if( SameKeyNum == 80 ){ Key_Flag = 1; Sys_Key = curKey; }
  123.         if( SameKeyNum >= 100 ){ Key_Flag = 1; Sys_Key = curKey; SameKeyNum = 80; }
  124.     }
  125.    
  126. }
  127. bit key28_down = 0;
  128. bit key28_up = 0;
  129. bit key27_down = 0;
  130. bit key27_up = 0;
  131. bit time_start = 1;

  132. void InitTimer0(void)
  133. {
  134.     TMOD = 0x01;
  135.     TH0 = 0x0FC;
  136.     TL0 = 0x18;
  137.     EA = 1;
  138.     ET0 = 1;
  139.     TR0 = 1;
  140. }

  141. void delay1ms(void)   //误差 0us
  142. {
  143.     unsigned char a,b,c;
  144.     for(c=1;c>0;c--)
  145.         for(b=142;b>0;b--)
  146.             for(a=2;a>0;a--);
  147. }


  148. void main(void)
  149. {
  150.     InitTimer0();
  151.           while(1)
  152.                 {
  153.                         Fun_KeyScan();
  154.                         if (Sys_Key == 28)//当28号键按下去然后在松开,key28_up == 1
  155.                         {
  156.                                         key28_down = 1;                          
  157.                         }
  158.                         if(key28_down == 1 && Sys_Key == 16)
  159.                         {
  160.                                         key28_down = 0;
  161.                                         key28_up = 1;                          
  162.                         }
  163.                         if(key28_up == 1)
  164.                         {
  165.                                         key28_up = 0;
  166.                                   time_start = ~time_start;
  167.                         }
  168.                        
  169.                         if (Sys_Key == 27)//当27号键按下去然后在松开,key27_up == 1
  170.                         {
  171.                                         key27_down = 1;                          
  172.                         }
  173.                         if(key27_down == 1 && Sys_Key == 16)
  174.                         {
  175.                                         key27_down = 0;
  176.                                         key27_up = 1;                          
  177.                         }
  178.                         if((key27_up == 1) && (time_start == 0))
  179.                         {
  180.                                         key27_up = 0;
  181.                                   duanma_mode++;
  182. //          if(duanma_mode >= 3)
  183. //                                        {
  184. //                                            duanma_mode = 0;
  185. //                                        }                                               
  186.                         }
  187.                        
  188.                         if(duanma_mode == 1)
  189.                         {
  190.                                   time100ms_cnt = 0;
  191.                         }
  192.                         if(duanma_mode == 2)
  193.                         {
  194.                                   duanma_mode = 0;
  195.                                   time_start = 1;
  196.                         }
  197.                   XBYTE[smgduan_num_addr] = smgduan_num[1];       
  198. ……………………

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

所有资料51hei提供下载:
51.zip (69.18 KB, 下载次数: 19)

评分

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

查看全部评分

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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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