当前位置:   article > 正文

基于C语言的单片机八路抢答器课程设计_抢答器单片机c语言代码

抢答器单片机c语言代码

一、任务说明 

(一)系统总体方案设计与实现

1、系统总体方案设计

本系统由硬件系统和软件系统组成。

硬件系统包括按键控制模块、中央处理AT89C51系统、指示灯显示模块、LED数码管显示模块和扬声器提示模块。

软件系统包括主程序、定时器0中断服务程序、定时器1中断服务程序、延时程序、按键程序和显示程序。

为方便理解,系统框图如下图所示:

图1 系统框图

2、系统总体方案实现

本次单片机课程设计选题是《八路抢答器》。本次课程设计是以八位选手抢答和主持人的控制为出发点。

①只有一个最先抢答有效,其余抢答无效。

②在主持人的控制下,10秒内抢答有效,用数码管显示抢答10秒倒计时,若有抢答直接结束,显示哪个编号抢到,并进入10秒的答题时间。

③若有提前抢答,则犯规,用蜂鸣器响1秒警示。

④有复位按键,用于复位作用,开始新的一轮。

⑤可以设置抢答时间和答题时间,可调范围是0到99秒,超出或低出范围会返回第10秒。

⑥LED警示灯、LED显示屏和蜂鸣器进行倒计时警示,三重的警示,带来极致的紧迫感。

⑦答题时间暂停,可以确定选手最后的答案耗时多长时间,促进选手的公平。

⑧如果选手在规定时间内或违规抢到第一位,不仅屏幕会显示号码,而且对应选手的LED灯会亮起。

(二)硬件电路设计

1、硬件电路图:

时钟电路模块:

图2 时钟电路

复位电路模块:

图3 复位电路

LED显示屏模块:

图4 LED显示屏

选手抢答按键模块:

图5 选手抢答按键

选手点灯模块:

图6 选手点灯

蜂鸣器提示模块:

图7 蜂鸣器提示

LED灯倒计时警示模块:

图8 LED灯倒计时警示

主持人控制按键模块:

图9 主持人控制按键

2、硬件说明:

本次硬件设计简单来说由:AT89C51最小系统、显示模块、按键模块LED灯和蜂鸣器模块组成。

(三)软件设计

当接通电源开始工作后,单片机中的程序开始运行,将对程序进行初始化。完成初始化后,将进行键盘扫描,同时判断开始按键、调节按键是否按下。最后完成倒计时和选手号码的显示等功能。

软件流程图如下图所示:

图10 软件流程图

二、电路原理图与结果

1、选手违规抢答:以第1位选手违规抢答为例,对应选手的LED灯亮起,LED显示屏显示对应违规选手号码,蜂鸣器先响起1秒警示,如果未进行复位操作,则蜂鸣器将再会响起,同时倒计时警示LED灯会闪烁提示。(第1-8位选手都是如此)

2、抢答时间调整:如果按下抢答时间加键或抢答时间减键,LED显示屏显示对应的调整时间,时间调整范围为0-99秒,超过99秒或低出0秒则返回去10秒。本次将抢答时间增加到15秒。

3、答题时间调整:如果按下答题时间加键或答题时间减键,LED显示屏显示对应的调整时间,时间调整范围为0-99秒,超过99秒或低出0秒则返回去10秒。本次将答题时间减少到8秒。

4、主持人按下开始键:抢答时间开始倒计时,最后几秒抢答时间倒计时警示LED灯将闪烁,要是选手没有选择抢答,则蜂鸣器会不断响起,LED显示屏熄屏,除非按下复位键开启新的一轮。

5、主持人按下开始键:抢答时间开始倒计时,最后几秒抢答时间倒计时警示LED灯将闪烁,要是选手选择抢答,则对应选手的LED灯会亮起。

6、要是选手在抢答时间按下抢答键,进入答题时间:答题时间最后几秒倒计时LED灯亮起,蜂鸣器不断响起,提示按下复位键,开始新的一轮。

6、要是选手在抢答时间按下抢答键,进入答题时间:答题时间内主持人可以按下答题时间暂停键,则显示屏时间暂停,按下答题时间暂停键的第一瞬间LED显示屏熄屏,倒计时LED警示灯亮起,松下答题时间暂停键的第一瞬间LED显示屏显示暂停的时间,倒计时LED警示灯熄灭,除非按下复位键,开始新的一轮。

三、代码说明

代码部分主要由四个模块组成,分别为主程序、显示子程序、时间按键调整子程序、选手按键子程序、开始键子程序、延迟子程序、定时器T0初始化子程序和蜂鸣器和LED灯子程序。

1、主程序:

主程序完成定时器0的初始化、74LS138芯片的初始化和扫描主持人按键,进行对应的操作。

2、显示子程序:

此函数大方向分为开始键按下和开始键没有按下的两种情况。同时两个大方向又各自细分两个小方向。当开始键按下,则有选手在抢答时间按下显示选手号码在LED显示屏上,要是没有则不显示号码。同时显示屏上显示抢答和答题的倒计时。当开始键没有按下,如果有人违规抢答,则显示屏显示违规号码。如果按下答题时间或抢答时间调整键,则对应显示屏进行更新数据操作。

3、时间按键调整子程序:

此函数很简单,要是按下抢答时间或答题时间调整键,则对应时间将进行操作,调整范围为0-99秒,超出99秒或低于0秒,则返回到10秒。

4、选手按键子程序:

以K1为例,程序一直判断按键引脚电压,按下按键电压为0。按键会产生抖动,需要进行消抖处理,先进行消抖延迟10ms,如果按键电压还是0,确定没问题K1进行操作,令按键数目num为1,供主函数处理按键消息。同时将74LS138的对应输入口赋值,数码管显示工作,定时器1和0也进行对应工作。K1-K8功能都是一样的操作。

5、开始键子程序:

如果按下开始键,程序一直判断按键引脚电压,按下按键电压为0。按键会产生抖动,需要进行消抖处理,先进行消抖延迟10ms,如果按键电压还是0,确定没问题K0进行操作.将对应的标志位进行开始工作,将清除违规标志位、开始抢答时间调整键标志位和答题计时时间调整键标志位停止运行。

6、延迟子程序:

确定51单片机为12MHz频率,以此确定ms的延迟子函数。

7、定时器T0初始化子程序:

将定时器T0进行初始化,运用方式1,即16位计数器。取高八位和第八位寄存器进行定时操作。

8、蜂鸣器和LED灯子程序:

用定时器0和定时器1确定蜂鸣器响多久和LED灯亮。

四、源代码

  1. #include<reg51.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. char s;
  5. uchar num=0;//谁抢到的号码,初始化为0
  6. char snaptime=10;//抢答时间
  7. char answertime=10;//答题时间
  8. uint t0,t1; //T0,T1定时器
  9. bit flag,s_flag=1,b_flag,fall_flag;//标志位
  10. bit K_snaptimeflag,K_answertimeflag;//时间调整标志位
  11. sbit K0=P3^0;
  12. sbit beep=P3^7;//蜂鸣器输出口
  13. sbit led=P2^4;//指示灯输出口
  14. sbit K1=P1^0;
  15. sbit K2=P1^1;
  16. sbit K3=P1^2;
  17. sbit K4=P1^3;
  18. sbit K5=P1^4;
  19. sbit K6=P1^5;
  20. sbit K7=P1^6;
  21. sbit K8=P1^7;
  22. sbit K_Time=P2^5;//答题暂停键
  23. sbit K_startcount=P2^6;//开始抢答时间+调整键
  24. sbit K_timecount=P3^4;//答题计时时间+调整键
  25. sbit K_startcount0=P2^7;//开始抢答时间-调整键
  26. sbit K_timecount0=P3^5;//答题计时时间-调整键
  27. sbit G=P3^1;
  28. sbit H=P3^2;
  29. sbit I=P3^3;
  30. sbit J=P3^6;
  31. uchar code tabledu[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
  32. uchar code tablewe[]={0XFE,0XFD,0XFB,0XF7};
  33. void delay(uint n)//延时n毫秒
  34. {
  35. uint i=0,j=0;
  36. for(i=0;i<n;i++)
  37. for(j=0;j<123;j++);
  38. }
  39. void T0_Init(void)//定时器T0初始化
  40. {
  41. TMOD=0X01;//使用定时器T0的模式1
  42. TH0=(65536-2000)/256;
  43. TL0=(65536-2000)%256;
  44. TH1=(65536-2000)/256;
  45. TL1=(65536-2000)%256;
  46. ET0=1;
  47. ET1=1;
  48. EA=1;
  49. P0=0;
  50. }
  51. void Start_Scan(void) //开始键扫描
  52. {
  53. if(K0==0)
  54. {
  55. delay(10);
  56. if(K0==0)
  57. {
  58. while(!K0);
  59. TR0=1;//启动定时器0工作
  60. s=snaptime;
  61. t0=0;
  62. flag=1;
  63. s_flag=1;
  64. b_flag=1;
  65. num=0;
  66. beep=1;
  67. led=1;
  68. fall_flag=0;//清除违规标志位
  69. K_snaptimeflag=0;//开始抢答时间调整键停止运行
  70. K_answertimeflag=0;//答题计时时间调整键停止运行
  71. }
  72. }
  73. }
  74. void Select_Scan(void)//八路选择键扫描(哪个键先按下,哪个优先级最高)
  75. {
  76. if(K1==0)
  77. {
  78. delay(10);
  79. if(K1==0)
  80. {
  81. while(!K1);
  82. {
  83. G=0;
  84. H=0;
  85. I=0;
  86. J=1;
  87. num=1;//数码管显示第1
  88. TR0=0;//关闭定时器0工作,时间停止
  89. TR1=1;//打开定时器1工作 。使扬声器响一声
  90. s_flag=0;//关闭开始键标志位,使再按其他七个键不会响应
  91. delay(10);
  92. }
  93. while(!K_Time);
  94. {
  95. s=answertime;
  96. TR0=1;
  97. t0=0;
  98. TR1=1;
  99. }
  100. }
  101. }
  102. if(K2==0)
  103. {
  104. delay(10);
  105. if(K2==0)
  106. {
  107. while(!K2);
  108. {
  109. G=1;
  110. H=0;
  111. I=0;
  112. J=1;
  113. num=2;
  114. TR0=0;
  115. TR1=1;
  116. s_flag=0;
  117. delay(10);
  118. }
  119. while(!K_Time);
  120. {
  121. s=answertime;
  122. TR0=1;
  123. t0=0;
  124. TR1=1;
  125. }
  126. }
  127. }
  128. if(K3==0)
  129. {
  130. delay(10);
  131. if(K3==0)
  132. {
  133. while(!K3);
  134. {
  135. G=0;
  136. H=1;
  137. I=0;
  138. J=1;
  139. num=3;
  140. TR0=0;
  141. TR0=0;
  142. TR1=1;
  143. s_flag=0;
  144. delay(10);
  145. }
  146. while(!K_Time);
  147. {
  148. s=answertime;
  149. TR0=1;
  150. t0=0;
  151. TR1=1;
  152. }
  153. }
  154. }
  155. if(K4==0)
  156. {
  157. delay(10);
  158. if(K4==0)
  159. {
  160. while(!K4);
  161. {
  162. G=1;
  163. H=1;
  164. I=0;
  165. J=1;
  166. num=4;
  167. TR0=0;
  168. TR1=1;
  169. s_flag=0;
  170. delay(10);
  171. }
  172. while(!K_Time);
  173. {
  174. s=answertime;
  175. TR0=1;
  176. t0=0;
  177. TR1=1;}
  178. }
  179. }
  180. if(K5==0)
  181. {
  182. delay(10);
  183. if(K5==0)
  184. {
  185. while(!K5);
  186. {
  187. G=0;
  188. H=0;
  189. I=1;
  190. J=1;
  191. num=5;
  192. TR0=0;
  193. TR1=1;
  194. s_flag=0;
  195. delay(10);
  196. }
  197. while(!K_Time);
  198. {
  199. s=answertime;
  200. TR0=1;
  201. t0=0;
  202. TR1=1;
  203. }
  204. }
  205. }
  206. if(K6==0)
  207. {
  208. delay(10);
  209. if(K6==0)
  210. {
  211. while(!K6);
  212. {
  213. G=1;
  214. H=0;
  215. I=1;
  216. J=1;
  217. num=6;
  218. TR0=0;
  219. TR1=1;
  220. s_flag=0;
  221. delay(10);
  222. }
  223. while(!K_Time);
  224. {
  225. s=answertime;
  226. TR0=1;
  227. t0=0;
  228. TR1=1;
  229. }
  230. }
  231. }
  232. if(K7==0)
  233. {
  234. delay(10);
  235. if(K7==0)
  236. {
  237. while(!K7);
  238. {
  239. G=0;
  240. H=1;
  241. I=1;
  242. J=1;
  243. num=7;
  244. TR0=0;
  245. TR1=1;
  246. s_flag=0;
  247. delay(10);
  248. }
  249. while(!K_Time);
  250. {
  251. s=answertime;
  252. TR0=1;
  253. t0=0;
  254. TR1=1;}
  255. }
  256. }
  257. if(K8==0)
  258. {
  259. delay(10);
  260. if(K8==0)
  261. {
  262. while(!K8);
  263. {
  264. G=1;
  265. H=1;
  266. I=1;
  267. J=1;
  268. num=8;
  269. TR0=0;
  270. TR1=1;
  271. s_flag=0;
  272. delay(10);
  273. }
  274. while(!K_Time);
  275. {
  276. s=answertime;
  277. TR0=1;
  278. t0=0;
  279. TR1=1;
  280. }
  281. }
  282. }
  283. }
  284. void display(void)
  285. {
  286. if(flag==1)//开始键按下,开始计时抢答
  287. {
  288. if(num!=0)//如果有人抢答,则显示相应的号码
  289. {
  290. P0=tabledu[num];//显示几号抢到了
  291. P2=tablewe[0];
  292. delay(2);
  293. P0=0;
  294. P2=0XFF;
  295. }
  296. else//否则没人抢答,则前面不显示几号
  297. {
  298. P0=0;
  299. P2=0XFF;
  300. }
  301. P0=tabledu[s/10];//显示抢答倒计时的十位
  302. P2=tablewe[2];
  303. delay(2);
  304. P0=0;
  305. P2=0XFF;
  306. P0=tabledu[s%10];//显示抢答倒计时的个位
  307. P2=tablewe[3];
  308. delay(2);
  309. P2=0XFF;
  310. P0=0;
  311. }
  312. if(flag==0)//如果开始键没有按下,若有违规者,则显示违规号码
  313. {
  314. if(fall_flag==1)//违规违规
  315. {
  316. if(num!=0)
  317. {
  318. P0=tabledu[num];//显几号违规了
  319. P2=tablewe[0];
  320. delay(2);
  321. P0=0;
  322. P2=0XFF;
  323. P0=tabledu[15];
  324. P2=tablewe[2];
  325. delay(2);
  326. P0=0;//消隐
  327. P2=0XFF;
  328. P0=tabledu[15];
  329. P2=tablewe[3];
  330. delay(2);
  331. P0=0;
  332. P2=0XFF;
  333. }
  334. else
  335. {
  336. P0=0;
  337. P2=0XFF;
  338. }
  339. }
  340. else
  341. {
  342. if(K_snaptimeflag==1)
  343. {
  344. P0=0XF9;//1位数码管(表示抢答时间调整)
  345. P2=tablewe[0];
  346. delay(2);
  347. P0=0;
  348. P2=0XFF;
  349. P0=tabledu[snaptime/10];//第x位数码管(表示抢答时间调整)
  350. P2=tablewe[2];
  351. delay(2);
  352. P0=0;
  353. P2=0XFF;
  354. P0=tabledu[snaptime%10];
  355. P2=tablewe[3];
  356. delay(2);
  357. P0=0;
  358. P2=0XFF;
  359. }
  360. else if(K_answertimeflag==1)
  361. {
  362. P0=0X07;//第x位数码管(表示答题时间调整)
  363. P2=tablewe[0];
  364. delay(2);
  365. P0=0;
  366. P2=0XFF;
  367. P0=0X31;
  368. P2=tablewe[1];
  369. delay(2);
  370. P0=0;
  371. P2=0XFF;
  372. P0=tabledu[answertime/10];
  373. P2=tablewe[2];
  374. delay(2);
  375. P0=0;
  376. P2=0XFF;
  377. P0=tabledu[answertime%10];
  378. P2=tablewe[3];
  379. delay(2);
  380. P0=0;
  381. P2=0XFF;
  382. }
  383. }
  384. }
  385. }
  386. void Time_Scan(void)//调整时间键扫描
  387. {
  388. if(K_startcount==0)//抢答时间调整
  389. {
  390. delay(10);
  391. if(K_startcount==0)
  392. {
  393. while(!K_startcount);
  394. snaptime++;
  395. if(snaptime==99||snaptime==0)
  396. {
  397. snaptime=10;
  398. }
  399. K_snaptimeflag=1; //将抢答时间标志位置1
  400. K_answertimeflag=0; //同时关闭答题时间标志位
  401. }
  402. }
  403. if(K_timecount==0) //答题时间调整
  404. {
  405. delay(10);
  406. if(K_timecount==0)
  407. {
  408. while(!K_timecount);
  409. answertime++;
  410. if(answertime==99||answertime==0)
  411. {
  412. answertime=10;
  413. }
  414. K_answertimeflag=1;
  415. K_snaptimeflag=0;
  416. }
  417. }
  418. if(K_startcount0==0)//抢答时间调整
  419. {
  420. delay(10);
  421. if(K_startcount0==0)
  422. {
  423. while(!K_startcount0);
  424. snaptime--;
  425. if(snaptime==99||snaptime==0)
  426. {
  427. snaptime=10;
  428. }
  429. K_snaptimeflag=1; //将抢答时间标志位置1
  430. K_answertimeflag=0; //同时关闭答题时间标志位
  431. }
  432. }
  433. if(K_timecount0==0) //答题时间调整
  434. {
  435. delay(10);
  436. if(K_timecount0==0)
  437. {
  438. while(!K_timecount0);
  439. answertime--;
  440. if(answertime==99||answertime==0)
  441. {
  442. answertime=10;
  443. }
  444. K_answertimeflag=1;
  445. K_snaptimeflag=0;
  446. }
  447. }
  448. }
  449. void main(void)
  450. {
  451. T0_Init();
  452. G=0;
  453. H=0;
  454. I=0;
  455. J=0;
  456. while(1)
  457. {
  458. Start_Scan(); //开始键扫描
  459. if((flag==0)&(s_flag==1)) //当开始键没按下及没有人违规时才可进行时间调整
  460. {
  461. Time_Scan();
  462. }
  463. if((flag==1)&(s_flag==0))//当开始键按下及有人抢答才进行开始回答计时倒计时
  464. {
  465. led=0;
  466. if(K_Time==0)
  467. {
  468. delay(10);
  469. if(K_Time==0)
  470. {
  471. while(!K_Time);
  472. TR0=0;
  473. t0=0;
  474. TR1=1;
  475. }
  476. }
  477. }
  478. if((flag==0)&(s_flag==1)) //违规
  479. {
  480. Select_Scan();
  481. if(num!=0) //开始键没有按下时,有人按下了抢答器,则置违规标志位
  482. {
  483. fall_flag=1;
  484. led=0;
  485. }
  486. }
  487. if((flag==1)&(s_flag==1)) //如果开始键按下且抢答键没有人按下,则进行八路抢答键扫描
  488. {
  489. Select_Scan();
  490. }
  491. display(); //显示到数码管上
  492. }
  493. }
  494. void timer0(void) interrupt 1//定时器0
  495. {
  496. TH0=(65536-2000)/256; //2ms
  497. TL0=(65536-2000)%256;
  498. if(b_flag) //开始(START)键按下,嘟一声(长1秒),表示开始抢答
  499. {
  500. beep=~beep;
  501. }
  502. else
  503. beep=1;
  504. if(s<5) //抢答时间快到报警,每1秒响一声且红灯闪烁,响5
  505. {
  506. if(s%1==0)
  507. {
  508. b_flag=1;
  509. led=0;
  510. }
  511. else
  512. {
  513. b_flag=0;
  514. led=1;
  515. }
  516. }
  517. t0++;
  518. if(t0==500) //1
  519. {
  520. t0=0;
  521. s--;
  522. b_flag=0; //关闭开始键按下响一秒的嘟声
  523. if(s==-1)
  524. {
  525. s=20;
  526. TR0=0;
  527. flag=0; //显示F FF
  528. s_flag=1;
  529. num=0;
  530. led=1;
  531. }
  532. }
  533. }
  534. void timer1(void) interrupt 3 //定时器1处理有人按下抢答器嘟一声(长1秒)
  535. {
  536. TH1=(65536-2000)/256;
  537. TL1=(65536-2000)%256;
  538. beep=~beep;
  539. t1++;
  540. if(t1==500)
  541. {
  542. t1=0;
  543. TR1=0;
  544. }
  545. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/164308
推荐阅读
相关标签
  

闽ICP备14008679号