找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机人员计数器+时钟程序设计

[复制链接]
跳转到指定楼层
楼主
设计要求:
1、实现0―9999范围计数。
2、要求使用红外发光二极管、光电管检测;
3、12864显示:进门人数,出门人数,房间里人数;
4、要求光电发射管与接收管有1米以上的间距

程序已通过清翔电子开发板完美测试    (可采用光敏、红外、热释电红外计数)

液晶端口
     DATA:P0.0~P0.7
         RS:P3.5
        RW:P3.6
         EN:P3.4
       PSB:P3.7

1302端口
     DAT:P1.1
     CLK:P1.0
     RST:P1.2

独立按键端口:P3.0~P3.3


单片机源程序如下:
  1. /******************************************************************
  2. /
  3. /  名称:人员计数器+时钟(12864显示)
  4. /
  5. ******************************************************************/

  6. #include <reg52.h>                       //调用单片机头文件
  7. #include <intrins.h>
  8. #include "12864.c"               
  9. #define uchar unsigned char  //无符号字符型 宏定义   变量范围0~255
  10. #define uint  unsigned int   //无符号整型 宏定义     变量范围0~65535

  11. sbit hw_jin=P1^0;   //红外传感器IO口定义
  12. sbit hw_chu=P1^1;   //红外传感器IO口定义

  13. sbit sda=P1^3;             //数据线
  14. sbit clk=P1^4;             //时钟线
  15. sbit rst=P1^2;             //使能

  16. sbit mode=P3^0;      //设置键
  17. sbit s1  =P3^1;      //加键
  18. sbit s2  =P3^2;      //减键
  19. sbit yes =P3^3;             //调整确认键
  20. sbit speak=P2^3;

  21. sbit ACC0=ACC^0;         //累加器A低位
  22. sbit ACC7=ACC^7;         //累加器A高位

  23. uchar dis,temp,a,h,m,n;       //设置参数用
  24. uchar set_num=80;             //设置倒计时数的启始值
  25. uint num;                     //总数
  26. uint jin,chu;                              //进   出
  27. uchar sec,min,hour,day,mouth,year,week;
  28. bit flag;

  29. /***************写数据********************/
  30. void write_byte(uchar dat)
  31. {
  32.         ACC=dat;
  33.         rst=1;
  34.         for(a=8;a>0;a--)
  35.         {
  36.          sda=ACC0;
  37.          clk=0;
  38.          clk=1;
  39.          ACC=ACC>>1;
  40.         }
  41. }

  42. /******************读数据********************/
  43. uchar read_byte()
  44. {
  45.         rst=1;
  46.         for(a=8;a>0;a--)
  47.         {
  48.          ACC7=sda;
  49.          clk=1;
  50.          clk=0;
  51.          ACC=ACC>>1;
  52.         }
  53.         return (ACC);
  54. }

  55. /*********向1302芯片写函数,指定写入地址,数据*********/
  56. void write_1302(uchar add,uchar dat)
  57. {
  58.         rst=0;
  59.         clk=0;
  60.         rst=1;
  61.         write_byte(add);
  62.         write_byte(dat);
  63.         clk=1;
  64.         rst=0;
  65. }

  66. /*********从1302读数据函数,指定读取数据来源地址*******/
  67. uchar read_1302(uchar add)
  68. {
  69.         uchar temp;
  70.         rst=0;
  71.         clk=0;
  72.         rst=1;
  73.         write_byte(add);
  74.         temp=read_byte();
  75.         clk=1;
  76.         rst=0;
  77.         return(temp);
  78. }

  79. /****************BCD码转十进制函数,输入BCD,返回十进制*******/
  80. uchar BCD(uchar m)
  81. {
  82. uchar x;
  83. x=m>>4;
  84. return(x=x*10+(m&=0x0f));
  85. }

  86. /********1302芯片初始化子函数********/
  87. void ds1302_init()
  88. {
  89. rst=0;
  90. clk=0;
  91. write_1302(0x8e,0x00); //允许写,禁止写保护
  92. delay(30);
  93. write_1302(0x8e,0x80); //打开写保护
  94. }

  95. /***********************1ms延时函数*****************************/
  96. void delayms(uint q)
  97. {
  98.         uint i,j;
  99.         for(i=0;i<q;i++)
  100.                 for(j=0;j<120;j++);
  101. }

  102. /*************定时器0初始化程序***************/
  103. void time_init()         
  104. {
  105.         EA  =1;                  //开总中断
  106.         TMOD=0X01;               //定时器0、工作方式1
  107.         ET0 =1;                  //开定时器0中断
  108.         TR0 =1;                  //允许定时器0定时
  109. }

  110. /******************红外计数**********************/           
  111. void hw_jin_dis()                   //红外计数
  112. {
  113.   if(hw_jin==0)                     //计数
  114. {
  115.    delayms(1);                     //消抖动
  116.     if(hw_jin==1)                                   //仿真时修改hw_jin==0 可以直观看到计数
  117.     {                              //确认
  118.           jin++;              
  119.          if(jin>=9999)  jin=9999; //最大计9999
  120.          num=jin-chu;             //计算总人数
  121.           if(dis==0)
  122.          {
  123.                    lcd_pos(0,2);
  124.                lcd_wdat(table[jin%10000/1000]);
  125.                lcd_wdat(table[jin%1000/100]);
  126.                lcd_wdat(table[jin%100/10]);
  127.                lcd_wdat(table[jin%10]);                                                                 
  128.            lcd_pos(2,2);
  129.                lcd_wdat(table[num%10000/1000]);
  130.                lcd_wdat(table[num%1000/100]);
  131.                lcd_wdat(table[num%100/10]);
  132.                lcd_wdat(table[num%10]);
  133.          }
  134.     }                        
  135. }
  136. }

  137. /******************红外计数**********************/           
  138. void hw_chu_dis()                //红外计数
  139. {
  140.   if(hw_chu==0)                 //计数
  141. {
  142.    delayms(1);                  //消抖动
  143.    if(hw_chu==1)                                //仿真时修改hw_chu==0 可以直观看到计数
  144.     {                           //确认
  145.       if(jin>chu)          chu++;
  146.       if(chu>=9999) chu=9999;
  147.       num=jin-chu;             //计算总人数
  148.        if(dis==0)
  149.       {
  150.             lcd_pos(1,2);
  151.             lcd_wdat(table[chu%10000/1000]);
  152.             lcd_wdat(table[chu%1000/100]);
  153.             lcd_wdat(table[chu%100/10]);
  154.             lcd_wdat(table[chu%10]);
  155.         lcd_pos(2,2);
  156.             lcd_wdat(table[num%10000/1000]);
  157.             lcd_wdat(table[num%1000/100]);
  158.             lcd_wdat(table[num%100/10]);
  159.             lcd_wdat(table[num%10]);
  160.       }
  161.     }                        
  162. }
  163. }

  164. void time_display()
  165. {
  166.   lcd_pos(2,6);
  167.   lcd_wdat(table[sec/10]);
  168.   lcd_wdat(table[sec%10]);
  169.   lcd_pos(1,6);
  170.   lcd_wdat(table[min/10]);
  171.   lcd_wdat(table[min%10]);
  172.   lcd_pos(0,6);
  173.   lcd_wdat(table[hour/10]);
  174.   lcd_wdat(table[hour%10]);
  175.   lcd_pos(3,1);
  176.   lcd_wdat(table[year/10]);
  177.   lcd_wdat(table[year%10]);
  178.   lcd_pos(3,3);
  179.   lcd_wdat(table[mouth/10]);
  180.   lcd_wdat(table[mouth%10]);
  181.   lcd_pos(3,5);
  182.   lcd_wdat(table[day/10]);
  183.   lcd_wdat(table[day%10]);
  184. }
  185. void key()
  186. {
  187. if(mode==0)                           //第一次判断"模式"按键按下
  188. {
  189.   delay(5);                            //延时消抖
  190.   if(mode==0){TR0=0;n++;}while(!mode);}                                                           
  191.   if(n>6) {TR0=1;n=0;}

  192. if(n!=0)
  193. {
  194.    if(s1==0)                            //调整+键
  195. {
  196.         delay(30);
  197. if(s1==0)
  198. {
  199.   TR0=0;
  200.    switch(n)
  201.   {
  202.         case 1:sec++;                          //设置键按动1次,调秒
  203.                    if(sec==60)        sec=0;                   //秒超过59,再加1,就归零               
  204.                     lcd_pos(2,6);
  205.            lcd_wdat(table[sec/10]);
  206.            lcd_wdat(table[sec%10]);
  207.                    temp=(sec)/10*16+(sec)%10;      //十进制转换成DS1302要求的DCB码
  208.                    write_1302(0x8e,0x00);          //允许写,禁止写保护
  209.                    write_1302(0x80,temp);          //向DS1302内写秒寄存器80H写入调整后的秒数据BCD码
  210.                    write_1302(0x8e,0x80);          //打开写保护
  211.                    break;
  212.   case 2:min++;                                                   //设置键按动2次,调分
  213.                    if(min==60)        min=0;                           //分数据加到60时自动变成0
  214.                    lcd_pos(1,6);
  215.            lcd_wdat(table[min/10]);
  216.            lcd_wdat(table[min%10]);
  217.                    temp=(min)/10*16+(min)%10;      //十进制转换成DS1302要求的DCB码
  218.                    write_1302(0x8e,0x00);          //允许写,禁止写保护
  219.                    write_1302(0x82,temp);          //向DS1302内写分寄存器82H写入调整后的分数据BCD码
  220.                    write_1302(0x8e,0x80);          //打开写保护
  221.                    break;
  222.         case 3:hour++;
  223.                    if(hour==24) hour=0;                           //时数据加到24时自动变成0
  224.                    lcd_pos(0,6);
  225.            lcd_wdat(table[hour/10]);
  226.            lcd_wdat(table[hour%10]);
  227.                    temp=(hour)/10*16+(hour)%10;    //十进制转换成DS1302要求的DCB码
  228.                    write_1302(0x8e,0x00);          //允许写,禁止写保护
  229.                    write_1302(0x84,temp);          //向DS1302内写小时寄存器84H写入调整后的小时数据BCD码
  230.                    write_1302(0x8e,0x80);          //打开写保护
  231.                       break;
  232.         case 4:day++;                                                   //设置键按动5次,调天
  233.                    if(day==32)        day=1;                           //天数据加到32时自动变成1
  234.                    if(mouth==2){if(day==30)        day=1;}
  235.                    if(mouth==4){if(day==31)        day=1;}
  236.                    if(mouth==6){if(day==31)        day=1;}
  237.                    if(mouth==9){if(day==31)        day=1;}
  238.                    if(mouth==11){if(day==31)day=1;}
  239.                      lcd_pos(3,5);
  240.            lcd_wdat(table[day/10]);
  241.            lcd_wdat(table[day%10]);
  242.                    temp=(day)/10*16+(day)%10;      //十进制转换成DS1302要求的DCB码
  243.                    write_1302(0x8e,0x00);          //允许写,禁止写保护
  244.                    write_1302(0x86,temp);          //向DS1302内写日期寄存器86H写入调整后的日期数据BCD码
  245.                    write_1302(0x8e,0x80);          //打开写保护                   write_1602com(yh+10);
  246.                    break;
  247.         case 5:mouth++;                                                   //设置键按动6次,调月
  248.                    if(mouth>=13)        mouth=1;           //月数据加到12时自动变成1
  249.            lcd_pos(3,3);
  250.            lcd_wdat(table[mouth/10]);
  251.            lcd_wdat(table[mouth%10]);                  
  252.                    temp=(mouth)/10*16+(mouth)%10;  //十进制转换成DS1302要求的DCB码
  253.                    write_1302(0x8e,0x00);          //允许写,禁止写保护
  254.                    write_1302(0x88,temp);          //向DS1302内写月份寄存器88H写入调整后的月份数据BCD码
  255.                    write_1302(0x8e,0x80);          //打开写保护
  256.                    break;
  257.         case 6:year++;                                                   //设置键按动7次,调年
  258.                    if(year==100)         year=0;           //年数据加到100时自动变成0
  259.                    lcd_pos(3,1);
  260.            lcd_wdat(table[year/10]);
  261.            lcd_wdat(table[year%10]);
  262.            temp=(year)/10*16+(year)%10;    //十进制转换成DS1302要求的DCB码
  263.                    write_1302(0x8e,0x00);          //允许写,禁止写保护
  264.                    write_1302(0x8c,temp);          //向DS1302内写年份寄存器8cH写入调整后的年份数据BCD码
  265.                    write_1302(0x8e,0x80);          //打开写保护
  266.                    break;
  267.    }
  268. }
  269. while(!s1);
  270. }
  271. }

  272. if(n!=0)
  273. {
  274. if(s2==0)                            //调整+键
  275. {
  276.         delay(30);
  277. if(s2==0)
  278. {
  279.   TR0=0;
  280.    switch(n)
  281.   {
  282.         case 1:sec--;                          //设置键按动1次,调秒
  283.                    if(sec==-1)        sec=59;                   //秒减到0时就归59               
  284.                     lcd_pos(2,6);
  285.            lcd_wdat(table[sec/10]);
  286.            lcd_wdat(table[sec%10]);
  287.                    temp=(sec)/10*16+(sec)%10;      //十进制转换成DS1302要求的DCB码
  288.                    write_1302(0x8e,0x00);          //允许写,禁止写保护
  289.                    write_1302(0x80,temp);          //向DS1302内写秒寄存器80H写入调整后的秒数据BCD码
  290.                    write_1302(0x8e,0x80);          //打开写保护
  291.                    break;
  292.   case 2:min--;                                                   //设置键按动2次,调分
  293.                    if(min==-1)        min=59;                           //分数据减到0时自动变成59
  294.                    lcd_pos(1,6);
  295.            lcd_wdat(table[min/10]);
  296.            lcd_wdat(table[min%10]);
  297.                    temp=(min)/10*16+(min)%10;      //十进制转换成DS1302要求的DCB码
  298.                    write_1302(0x8e,0x00);          //允许写,禁止写保护
  299.                    write_1302(0x82,temp);          //向DS1302内写分寄存器82H写入调整后的分数据BCD码
  300.                    write_1302(0x8e,0x80);          //打开写保护
  301.                    break;
  302.         case 3:hour--;
  303.                    if(hour==-1) hour=23;                           //时数据减到0时自动变成23
  304.                    lcd_pos(0,6);
  305.            lcd_wdat(table[hour/10]);
  306.            lcd_wdat(table[hour%10]);
  307.                    temp=(hour)/10*16+(hour)%10;    //十进制转换成DS1302要求的DCB码
  308.                    write_1302(0x8e,0x00);          //允许写,禁止写保护
  309.                    write_1302(0x84,temp);          //向DS1302内写小时寄存器84H写入调整后的小时数据BCD码
  310.                    write_1302(0x8e,0x80);          //打开写保护
  311.                       break;
  312.         case 4:day--;                                                   //设置键按动5次,调天
  313.                    if(day==0)        day=31;                           //天数据减到0时自动变成31
  314.                    if(mouth==2){if(day==-1)        day=29;}
  315.                    if(mouth==4){if(day==-1)        day=30;}
  316.                    if(mouth==6){if(day==-1)        day=30;}
  317.                    if(mouth==9){if(day==-1)        day=30;}
  318.                    if(mouth==11){if(day==-1)day=30;}
  319.                      lcd_pos(3,5);
  320.            lcd_wdat(table[day/10]);
  321.            lcd_wdat(table[day%10]);
  322.                    temp=(day)/10*16+(day)%10;      //十进制转换成DS1302要求的DCB码
  323.                    write_1302(0x8e,0x00);          //允许写,禁止写保护
  324.                    write_1302(0x86,temp);          //向DS1302内写日期寄存器86H写入调整后的日期数据BCD码
  325.                    write_1302(0x8e,0x80);          //打开写保护                   write_1602com(yh+10);
  326.                    break;
  327.         case 5:mouth--;                                                   //设置键按动6次,调月
  328.                    if(mouth==0)        mouth=12;           //月数据减到0时自动变成12
  329.            lcd_pos(3,3);
  330.            lcd_wdat(table[mouth/10]);
  331.            lcd_wdat(table[mouth%10]);                  
  332.                    temp=(mouth)/10*16+(mouth)%10;  //十进制转换成DS1302要求的DCB码
  333.                    write_1302(0x8e,0x00);          //允许写,禁止写保护
  334.                    write_1302(0x88,temp);          //向DS1302内写月份寄存器88H写入调整后的月份数据BCD码
  335.                    write_1302(0x8e,0x80);          //打开写保护
  336.                    break;
  337.         case 6:year--;                                                   //设置键按动7次,调年
  338.                    if(year==-1)         year=99;           //年数据减到0时自动变成99
  339.                    lcd_pos(3,1);
  340.            lcd_wdat(table[year/10]);
  341.            lcd_wdat(table[year%10]);
  342.            temp=(year)/10*16+(year)%10;    //十进制转换成DS1302要求的DCB码
  343.                    write_1302(0x8e,0x00);          //允许写,禁止写保护
  344.                    write_1302(0x8c,temp);          //向DS1302内写年份寄存器8cH写入调整后的年份数据BCD码
  345.                    write_1302(0x8e,0x80);          //打开写保护
  346.                    break;
  347.   }
  348. }
  349. while(!s2);
  350. }
  351. }

  352. if(n!=0)
  353. {
  354.   if(yes==0)                        //调整值确认键按下,保存设置的参数,直接退出调整状态,进入走时。
  355. {
  356.         delay(30);
  357.   if(yes==0)
  358.   {
  359.      n=0;
  360.          TR0=1;                      //打开定时器
  361.          temp=(sec)/10*16+(sec)%10;
  362.          write_1302(0x8e,0x00);
  363.          write_1302(0x80,0x00|temp); //秒数据写入DS1302
  364.          write_1302(0x8e,0x80);
  365.          delay(100);
  366.          time_display();       
  367.   }
  368.   while(!yes);                                   //松开按键检测
  369. }
  370. }
  371. ……………………

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

所有资料51hei提供下载:
计数器 时钟.rar (26.66 KB, 下载次数: 32)

评分

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

查看全部评分

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

使用道具 举报

沙发
ID:578583 发表于 2019-7-28 10:12 | 只看该作者
谢谢楼主分享,收藏先
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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