找回密码
 立即注册

QQ登录

只需一步,快速开始

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

基于51的单片机的七人多数表决器程序仿真(14个表决按键)

[复制链接]
跳转到指定楼层
楼主
本帖最后由 1979759100Ls 于 2022-5-20 02:40 编辑

原创!!!全网没有找到,所以自己做了一个51单片机七人多数表决器!!
规定的要求如下:

用时两天,创作不易,请留下点赞,myQ制作736142345,纯粹个人兴趣,现在分享给大家,还参考别人的文档做了一个WORD说明书(文档),也一并上传了,在附件里,自取。
文件全部放在附件中了,自行下载,包含仿真、程序+详细注释,原理图和PCB,非常详细。实际测试仿真是完全没问题的,实物没来的及做,数码管显示可能会出现驱动不足的问题,增加控制端口的驱动即可,猜测是这样,感兴趣的可以试一试!欢迎积极留言讨论。

  1. 单片机源程序如下:
  2. #include<reg51.h>
  3. #include<intrins.h>
  4. sbit smg1=P2^0;      //定义数码管第一位
  5. sbit smg2=P2^1;      //定义数码管第二位
  6. sbit smg3=P2^2;      //定义数码管第三位
  7. sbit smg4=P2^3;      //定义数码管第四位
  8. sbit smg5=P2^4;      //定义数码管第五位
  9. sbit smg6=P2^5;      //定义数码管第六位
  10. sbit keyks=P3^7;  //定义开始按键
  11. sbit spk=P3^2;       //定义蜂鸣器
  12. int djs,js=0;    //djs和js是初始倒计时时间
  13. int buzzbiaozhi=1;   //10S倒计时结束后蜂鸣器响一下的标志位
  14. //int buzzbiaozhi1=1;    //开始投票按键按下标志位//矩阵
  15. int flag1=0,flag2=0,flag3=0,flag4=0,flag5=0,flag6=0,flag7=0,flag8=0,flag9=0,
  16. flag10=0,flag11=0,flag12=0,flag13=0,flag14=0,flagD=0,bjs=0;bjs1;bjs2;
  17. //flag1~14用来保证在同意和反对的唯一性 ,  flagD用来控制是否显示倒计时, bjs表决总计数,bjs1同意计数,bjs2反对计数
  18. unsigned char key_num;   //按键键值返回值
  19. int table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40,0x77,0x5c,0X73,0X71};    /// 共阴   cc    数码管段码
  20. //      //    0    1   2    3    4    5    6     7    8    9   -     A   o     P f ///

  21. //******延时程序****//
  22. void delayms(unsigned z)
  23. {
  24.     unsigned x,y;
  25.     for(x=z;x>0;x--)
  26.       for(y=110;y>0;y--);   
  27. }

  28. ////****矩阵按键判键程序*****///
  29. unsigned char key_scan()          //有返回值
  30. {
  31.         unsigned char key_temp0,key_temp1;
  32.         unsigned char key_num=0;
  33.         P1=0x0f;
  34.         key_temp0=P1;                                   //读取P1端口的值
  35.         if(key_temp0!=0x0f)
  36.         {
  37.                 delayms(5);                            //延时去抖动
  38.                 key_temp0=P1;                           //再次读取P1端口的值
  39.                 if(key_temp0!=0x0f)
  40.                 {
  41.                     P1=0xf0;
  42.                     key_temp1=P1;
  43.                     if(key_temp0==0x0e)                    //判断第一行
  44.                   {
  45.                       switch(key_temp1)
  46.                      {
  47.                        case 0xe0: key_num=4;break;          //检测到第一行第四个键按下
  48.                        case 0xd0: key_num=3;break;          //检测到第一行第三个键按下
  49.                        case 0xb0: key_num=2;break;          //检测到第一行第二个键按下
  50.                        case 0x70: key_num=1;break;          //检测到第一行第一个键按下
  51.                        default:key_num=0;break;
  52.                      }
  53.                     }
  54.                        else if(key_temp0==0x0d)                  //判断第二行
  55.                         {
  56.                            switch(key_temp1)
  57.                                 {
  58.                                  case 0xe0: key_num=8;break;       //检测到第二行第四个键按下
  59.                                  case 0xd0: key_num=7;break;       //检测到第二行第三个键按下
  60.                                  case 0xb0: key_num=6;break;       //检测到第二行第二个键按下
  61.                                  case 0x70: key_num=5;break;       //检测到第二行第一个键按下
  62.                                  default:key_num=0;break;
  63.                                 }
  64.                         }
  65.                         else if(key_temp0==0x0b)                   //判断第三行
  66.                         {
  67.                                 switch(key_temp1)
  68.                                 {
  69.                                  case 0xe0: key_num=12;break;         //检测到第三行第四个键按下
  70.                                  case 0xd0: key_num=11;break;         //检测到第三行第三个键按下
  71.                                  case 0xb0: key_num=10;break;         //检测到第三行第二个键按下
  72.                                  case 0x70: key_num=9;break;         //检测到第三行第一个键按下
  73.                                  default:key_num=0;break;
  74.                                 }
  75.                         }
  76.                         else if(key_temp0==0x07)                  //判断第四行
  77.                         {
  78.                                 switch(key_temp1)
  79.                                 {
  80.                                  case 0xe0: key_num=16;break;        //检测到第四行第四个键按下
  81.                                  case 0xd0: key_num=15;break;        //检测到第四行第三个键按下
  82.                                  case 0xb0: key_num=14;break;        //检测到第四行第二个键按下
  83.                                  case 0x70: key_num=13;break;         //检测到第四行第一个键按下
  84.                                  default:key_num=0;break;
  85.                                 }
  86.                         }
  87.                 }
  88.         }
  89. return key_num;
  90. }



  91. void Timer0_init()          //定时器0初始化
  92. {
  93.     js=0;
  94.     TMOD=0x01;           //设置定时器0为工作方式1(M1M0为01)
  95.     TH0=(65536-50000)/256;   //装初值12M晶振定时50ms数为50000,1US是1000初始值,所以50ms是5万
  96.     TL0=(65536-50000)%256;      
  97.     ET0=1;                   //开定时器0中断
  98.     EA=1;                    //开总中断
  99. }

  100. void timer0() interrupt 1 using 1  //定时器0中断服务函数
  101. {
  102.     TH0=(65536-50000)/256;      //装初值12M晶振定时50ms数为50000
  103.     TL0=(65536-50000)%256;   
  104.     js++;                    //叠加20次
  105.     if(js==20)
  106.     {
  107.       js=0;                     //清空
  108.       djs--;                 //产生1s的倒计时
  109.      }
  110. }
  111. ///倒计时函数////
  112. void djsxs()   //第一位,第二位显示倒计时函数
  113. {   
  114.     int b1,b2;
  115.     b1=djs/10;
  116.     b2=djs%10;             //将倒计时时间分成高低位
  117.     P0=table[b1];         
  118.     smg1=0;                     //第1位显示十位
  119.     delayms(3);
  120.     smg1=1;                  //显示十位数字
  121.     P0=table[b2];
  122.     smg2=0;                     //第2位显示各位
  123.     delayms(3);              //显示个位数字
  124.     smg2=1;
  125. }



  126. //**显示P通过,显示F没通过**//
  127. void djsxs01() //第一位数码管显示 P表示通过
  128. {                                 
  129.     P0=0X73;          //第一位数码管显示P
  130.     smg1=0;
  131.     delayms(3);
  132.     smg1=1;
  133. }
  134. void djsxs10() //第一位数码管显示F 表示没通过
  135. {
  136.     P0=0X71;          //第一位数码管显示F
  137.     smg1=0;
  138.     delayms(3);
  139.     smg1=1;
  140. }
  141. //**第三位显示A,第五位显示0**//  
  142. void djsxs20() //第三位数码管显示 A
  143. {
  144.     P0=0X77;          //第三位数码管显示A
  145.     smg3=0;
  146.     delayms(3);            
  147.     smg3=1;
  148. }
  149. void djsxs30() //第五位数码管显示 -
  150. {
  151.     P0=0x5c;          //第五位数码管显示0
  152.     smg5=0;
  153.     delayms(3);            
  154.     smg5=1;
  155. }
  156. ////*****计数显示,第四位显示同意人数 *********///////
  157. void djsxs0()  //第四位数码管显示0
  158. {
  159.     P0=table[0];
  160.     smg4=0;
  161.     delayms(3);
  162.     smg4=1;       //第四位数码管显示0
  163. }
  164. void djsxs1()  //第四位数码管显示1
  165. {
  166.     P0=table[1];      //第四位数码管显示1
  167.     smg4=0;
  168.     delayms(3);
  169.     smg4=1;               
  170. }
  171. void djsxs2()  //第四位数码管显示2
  172. {
  173.     P0=table[2];
  174.     smg4=0;
  175.     delayms(3);
  176.     smg4=1;              //第四位数码管显示2
  177. }
  178. void djsxs3()  //第四位数码管显示3
  179. {
  180.     P0=table[3];
  181.     smg4=0;
  182.     delayms(3);
  183.     smg4=1;            //第四位数码管显示3
  184. }
  185. void djsxs4()  //第四位数码管显示4
  186. {
  187.     P0=table[4];
  188.     smg4=0;
  189.     delayms(3);
  190.     smg4=1;          //第四位数码管显示4
  191. }
  192. void djsxs5()  //第四位数码管显示5
  193. {
  194.     P0=table[5];
  195.     smg4=0;
  196.     delayms(3);
  197.     smg4=1;          //第四位数码管显示5
  198. }
  199. void djsxs6()  //第四位数码管显示6
  200. {
  201.     P0=table[6];
  202.     smg4=0;
  203.     delayms(3);
  204.     smg4=1;          //第四位数码管显示6
  205. }
  206. void djsxs7()  //第四位数码管显示7
  207. {
  208.     P0=table[7];
  209.     smg4=0;
  210.     delayms(3);
  211.     smg4=1;         //第四位数码管显示7
  212. }
  213. ////*****计数显示,第六位显示不同意人数 *********///////
  214. void djsxs00()  //第六位数码管显示0
  215. {
  216.     P0=table[0];
  217.     smg6=0;
  218.     delayms(3);
  219.     smg6=1;       //第六位数码管显示0
  220. }
  221. void djsxs11()  //第六位数码管显示1
  222. {
  223.     P0=table[1];      //第六位数码管显示1
  224.     smg6=0;
  225.     delayms(3);
  226.     smg6=1;               
  227. }
  228. void djsxs22()  //第六位数码管显示2
  229. {
  230.     P0=table[2];
  231.     smg6=0;
  232.     delayms(3);
  233.     smg6=1;              //第六位数码管显示2

  234. }
  235. void djsxs33()  //第六位数码管显示3
  236. {
  237.     P0=table[3];
  238.     smg6=0;
  239.     delayms(3);
  240.     smg6=1;            //第六位数码管显示3
  241. }
  242. void djsxs44()  //第六位数码管显示4
  243. {
  244.     P0=table[4];
  245.     smg6=0;
  246.     delayms(3);
  247.     smg6=1;          //第六位数码管显示4
  248. }
  249. void djsxs55()  //第六位数码管显示5
  250. {
  251.     P0=table[5];
  252.     smg6=0;
  253.     delayms(3);
  254.     smg6=1;          //第六位数码管显示5
  255. }
  256. void djsxs66()  //第六位数码管显示6
  257. {
  258.     P0=table[6];
  259.     smg6=0;
  260.     delayms(3);
  261.     smg6=1;          //第六位数码管显示6
  262. }
  263. void djsxs77()  //第六位数码管显示7
  264. {
  265.     P0=table[7];
  266.     smg6=0;
  267.     delayms(3);
  268.     smg6=1;         //第六位数码管显示7
  269. }
  270. void main()
  271. {
  272.     //buzzbiaozhi1=0;          //开始按键标志位//矩阵
  273.     bjs=0;                      //总表决计数
  274.      bjs1=0;                 //同意票数统计
  275.      bjs2=0;                 //反对票数统计
  276.      djs=10;                  //修改倒计时初始值
  277.      Timer0_init();             //初始化定时器中断
  278.     while(1)
  279.     {
  280.       key_num=key_scan();
  281. //////    if(key_num==16)             ///测试按键位置   横着按键排布为1 2 3 4第二排5 6 7 8,顺延9 10 11 12,13 14 15 16//
  282. //////       { djsxs0();
  283. //////       }                                                               
  284. ////////////////////////////////////////////////////////////////////////////////////////////////                        
  285.      if(djs<=0)             //倒计时10s时间到
  286.      {
  287. //    buzzbiaozhi1=0;
  288.       flagD=0;                  //不再显示时间
  289.       TR0=0;                //关闭定时器
  290.       flag1=0,flag2=0,flag3=0,flag4=0,flag5=0,flag6=0,flag7=0;flag8=0,flag9=0,flag10=0,flag11=0,flag12=0,flag13=0,flag14=0;    //关闭选手的按键                                                                        
  291. //    switch(bjs) //显示结果,此处显示 1或0(通不通过) --   同意人数
  292. //    {
  293. //     case 0:    djsxs10();break;
  294. //     case 1: djsxs10();break;      
  295. //     case 2:    djsxs10();break;                          //老方法太麻烦那
  296. //     case 3: djsxs10();break;
  297. //     case 4:    djsxs11();break;
  298. //     case 5: djsxs11();break;      
  299. //     case 6:    djsxs11();break;
  300. //     case 7: djsxs11();break;               
  301. //     default:  ;
  302. //       }
  303.        /////*****判断是否通过******///////       //新方法好用
  304.        if(bjs1>=4) djsxs01();
  305.        if(bjs1<4) djsxs10();       //大于四票显示通过,P代表通过 ,否则不通过 ,F表示

  306.    附件里下载哈
复制代码

%C(1WJ}V[U77240T}2QU5}N.png (24.07 KB, 下载次数: 48)

原理图

原理图

_~V9I[DR{FVS{WV([T)G0L2.png (49.59 KB, 下载次数: 35)

PCB

PCB

0O66Q3~28H]IHXK51WR54R6.png (70.21 KB, 下载次数: 109)

主流程图

主流程图

WJ84](1LIAQF73`1D0@E1UE.png (180.96 KB, 下载次数: 123)

Proteus仿真效果图

Proteus仿真效果图

表决器程序 注释.rar

42.85 KB, 下载次数: 44, 下载积分: 黑币 -5

程序

7人多数表决器设计嘿嘿嘿.docx

1.74 MB, 下载次数: 26, 下载积分: 黑币 -5

文档

表决器仿真.rar

172.45 KB, 下载次数: 34, 下载积分: 黑币 -5

仿真

biaojueqi-yuanlitu -原理图-模块化.rar

3.57 MB, 下载次数: 15, 下载积分: 黑币 -5

pcb+原理图

评分

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

查看全部评分

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

使用道具 举报

沙发
ID:262 发表于 2022-5-15 05:25 | 只看该作者
难的一见的好作品,描述清楚,程序注释详细
PCB其实只要吧history目录给删掉再用7z货rar压缩就很小了,一般也就几兆
回复

使用道具 举报

板凳
ID:312929 发表于 2022-5-15 11:33 | 只看该作者
heicad 发表于 2022-5-15 05:25
难的一见的好作品,描述清楚,程序注释详细
PCB其实只要吧history目录给删掉再用7z货rar压缩就很小了,一般也 ...

那这样他们就没有封装了吧,我试试哈
回复

使用道具 举报

地板
ID:161164 发表于 2022-5-16 11:19 | 只看该作者
键盘扫描代码不能扫到同时按键的情况
如第一行第二个键按下
key_temp1 = 0xB0
key_num = 2
这时第一行第一个键按下
key_temp1 = 0x30
switch 中没有这 case
key_num = 0
然后第一行第一个键放开
key_temp1 = 0xB0
key_num = 2
第一行第一个键按下的情况被屏蔽了
就是说只要有人按着不放
那一行就会只有一个投票
回复

使用道具 举报

5#
ID:312929 发表于 2022-5-16 11:23 | 只看该作者
lkc8210 发表于 2022-5-16 11:19
键盘扫描代码不能扫到同时按键的情况
如第一行第二个键按下
key_temp1 = 0xB0

非常有道理,但是呢在表决过程中这个小细节我个人认为是可以忽略的,到谁表决了再按键,表决完了下一个人,我是这样理解的
回复

使用道具 举报

6#
ID:161164 发表于 2022-5-16 11:56 | 只看该作者
本帖最后由 lkc8210 于 2022-5-16 12:00 编辑
1979759100Ls 发表于 2022-5-16 11:23
非常有道理,但是呢在表决过程中这个小细节我个人认为是可以忽略的,到谁表决了再按键,表决完了下一个人 ...

还以为是10秒内所有人一起表决
那还要啥矩阵键盘
只要三个按键接口:开始, 同意和反对
同意和反对键要多少并多少

回复

使用道具 举报

7#
ID:312929 发表于 2022-5-16 14:59 | 只看该作者
lkc8210 发表于 2022-5-16 11:56
还以为是10秒内所有人一起表决
那还要啥矩阵键盘
只要三个按键接口:开始, 同意和反对

那不是有要求的么老师故意布置的任务,为了增加难度吧应该
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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