您的位置 首页 发布

第35节:带数码管显现的象棋竞赛专用计时器

开场白:2014年春节的时候,一帮朋友举行小规模的象棋比赛,有一些朋友下棋的速度实在是太慢了,为了限制比赛时间,我专门用朱兆祺的51学习

开场白:
2014年新年的时分,一帮朋友举办小规模的象棋竞赛,有一些朋友下棋的速度实在是太慢了,为了约束竞赛时刻,我专门用朱兆祺的51学习板做了一个棋类竞赛专用计时器给他们用。这一节要教会我们两个知识点:
榜首个:按键服务程序操作的精华在于依据当时体系处于什么窗口状况下就履行什么操作。紧紧围绕着不同的窗口ucWd来履行不同的操作。
第二个:持续加深了解鸿哥初次提出的“一二级菜单显现理论”:但凡人机界面显现,不管是数码管仍是液晶屏,都能够把显现的内容分红不同的窗口来显现,每个显现的窗口中又能够分红不同的部分显现。其间窗口便是一级菜单,用ucWd变量表明。部分便是二级菜单,用ucPart来表明。不同的窗口,会有不同的更新显现变量ucWdXUpdate来对应,表明整屏悉数更新显现。不同的部分,也会有不同的更新显现变量ucWdXPartYUpdate来对应,表明部分更新显现。

具体内容,请看源代码解说。

(1)硬件渠道:依据朱兆祺51单片机学习板
刚上电开机时,红棋加时键对应S1键,红棋减时键对应S2键.。
刚上电开机时,黑棋加时键对应S3键,黑棋减时键对应S4键.。
竞赛半途暂停两边计时的暂停按键对应S6键。刚上电时,复位两边默许20分时刻的复位按键对应S7按键。
红棋的抢时按键对应S13键,黑棋的抢时按键对应S16按键。

(2)完结功用:
棋类计时器有点像抢答器,实质上有两个计时器。竞赛的时分对弈的两个棋友各用一个不同的按键抢时刻,红棋走一步棋后,就按一下自己的抢时按键,这个时分红棋的计时器中止计时,而黑棋的计时器开端计时,黑棋走了一步棋后,按一下自己的计时器,黑棋中止计时,红棋持续计时,顺次循环,谁的时刻最早用完谁就输,蜂鸣器也会宣布长鸣的声响提示时刻到。
上电开机默许两边各有20分钟的时刻,左面显现的是红棋的时刻,右边显现的是黑棋的时刻。此刻能够经过S1,S2.,S3,S4的加减按键来设置各自的最大倒计时时刻。此刻假如按下复位按键S7,会主动把两边的时刻设置为默许的20分钟。
设置好最大倒计时的时刻后,此刻恣意一方按下各自的抢时按键(S13或许S16),则自己的计时器中止计时,而对方开端倒计时。此刻数码管显现的是对方的时刻,而自己的时刻屏蔽不显现。
在开端倒计时的时分,假如半途有棋友要接听电话或许忙其他工作,需求暂时暂停一下两边的时刻,这个时分能够按S6暂停按键来暂停两边的计时,忙完后再次按下暂停按键会持续倒计时。任何一方的时刻走完,都会蜂鸣器长鸣提示。
(3)源代码解说如下:

  1. #include “REG52.H”
  2. #define const_voice_short40 //蜂鸣器短叫的持续时刻
  3. #define const_voice_long 900 //蜂鸣器长叫的持续时刻
  4. #define const_key_time10 //按键去颤动延时的时刻
  5. #define const_1s 422 //发生一秒钟的时刻基准
  6. void initial_myself();
  7. void initial_peripheral();
  8. void delay_short(unsigned int uiDelayShort);
  9. void delay_long(unsigned int uiDelaylong);
  10. void T0_time();//守时中止函数
  11. void key_service();
  12. void key_scan(); //按键扫描函数 放在守时中止里
  13. void dig_hc595_drive(unsigned char ucDigStatusTemp16_09,unsigned char ucDigStatusTemp08_01);
  14. void display_drive();//放在守时中止里的数码管驱动函数
  15. void time_service();//放在守时中止里的时刻应用程序
  16. void display_service();
  17. sbit key_sr1=P0^0; //榜首行输入
  18. sbit key_sr2=P0^1; //第二行输入
  19. sbit key_sr3=P0^2; //第三行输入
  20. sbit key_sr4=P0^3; //第四行输入
  21. sbit key_dr1=P0^4; //榜首列输出
  22. sbit key_dr2=P0^5; //第二列输出
  23. sbit key_dr3=P0^6; //第三列输出
  24. sbit key_dr4=P0^7; //第四列输出
  25. sbit beep_dr=P2^7; //蜂鸣器的驱动IO口
  26. sbit led_dr=P3^5;//作为半途暂停指示灯 亮的时分表明半途暂停
  27. sbit dig_hc595_sh_dr=P2^0; //数码管 的74HC595程序
  28. sbit dig_hc595_st_dr=P2^1;
  29. sbit dig_hc595_ds_dr=P2^2;
  30. sbit hc595_sh_dr=P2^3; //LED灯的74HC595程序
  31. sbit hc595_st_dr=P2^4;
  32. sbit hc595_ds_dr=P2^5;
  33. unsigned char ucKeyStep=1;//按键扫描过程变量
  34. unsigned char ucKeySec=0; //被触发的按键编号
  35. unsigned intuiKeyTimeCnt=0; //按键去颤动延时计数器
  36. unsigned char ucKeyLock=0; //按键触发后自锁的变量标志
  37. unsigned char ucRowRecord=1; //记载当时扫描到第几列了
  38. unsigned intuiVoiceCnt=0;//蜂鸣器鸣叫的持续时刻计数器
  39. unsigned char ucDigShow8=0;//第8位数码管要显现的内容
  40. unsigned char ucDigShow7=0;//第7位数码管要显现的内容
  41. unsigned char ucDigShow6=0;//第6位数码管要显现的内容
  42. unsigned char ucDigShow5=0;//第5位数码管要显现的内容
  43. unsigned char ucDigShow4=0;//第4位数码管要显现的内容
  44. unsigned char ucDigShow3=0;//第3位数码管要显现的内容
  45. unsigned char ucDigShow2=0;//第2位数码管要显现的内容
  46. unsigned char ucDigShow1=0;//第1位数码管要显现的内容
  47. unsigned char ucDigDot3=1;//数码管3的小数点是否显现的标志
  48. unsigned char ucDigDot7=1;//数码管7的小数点是否显现的标志
  49. unsigned char ucDigShowTemp=0; //暂时中心变量
  50. unsigned char ucDisplayDriveStep=1;//动态扫描数码管的过程变量
  51. unsigned int uiRedTimeCnt=0; //红棋发生秒基准的时刻计时器
  52. unsigned int uiBlackTimeCnt=0;//黑棋发生秒基准的时刻计时器
  53. unsigned int uiRedTotal=1200; //红棋的总时刻
  54. unsigned int uiBlackTotal=1200;//黑棋的总时刻
  55. unsigned char ucRedFlag=0;//红棋是否开端计时的标志
  56. unsigned char ucBlackFlag=0;//黑棋是否开端计时的标志
  57. unsigned char ucDisplayUpdate=1; //更新显现标志
  58. /* 注释一:
  59. *ucWd变量是本程序最中心的变量,代表显现哪一个窗口和体系处于当时哪种状况
  60. */
  61. unsigned char ucWd=1;
  62. code unsigned char dig_table[]=
  63. {
  64. 0x3f,//0 序号0
  65. 0x06,//1 序号1
  66. 0x5b,//2 序号2
  67. 0x4f,//3 序号3
  68. 0x66,//4 序号4
  69. 0x6d,//5 序号5
  70. 0x7d,//6 序号6
  71. 0x07,//7 序号7
  72. 0x7f,//8 序号8
  73. 0x6f,//9 序号9
  74. 0x00,//不显现序号10
  75. };
  76. void main()
  77. {
  78. initial_myself();
  79. delay_long(100);
  80. initial_peripheral();
  81. while(1)
  82. {
  83. key_service();
  84. display_service();
  85. }
  86. }
  87. void time_service()//放在守时中止里的时刻应用程序
  88. {
  89. if(ucRedFlag==1)//1代表红棋在运转中
  90. {
  91. uiRedTimeCnt++;
  92. if(uiRedTimeCnt>const_1s)
  93. {
  94. uiRedTimeCnt=0;
  95. if(uiRedTotal>0)
  96. {
  97. uiRedTotal–;
  98. }
  99. else//时刻到
  100. {
  101. ucRedFlag=0; //红棋和黑棋一起中止计时
  102. ucBlackFlag=0;
  103. ucWd=1;//切换到榜首个窗口的状况
  104. uiVoiceCnt=const_voice_long; //报警声响触发
  105. }
  106. ucDisplayUpdate=1;//更新显现
  107. }
  108. }
  109. if(ucBlackFlag==1)//1代表黑棋在运转中
  110. {
  111. uiBlackTimeCnt++;
  112. if(uiBlackTimeCnt>const_1s)
  113. {
  114. uiBlackTimeCnt=0;
  115. if(uiBlackTotal>0)
  116. {
  117. uiBlackTotal–;
  118. }
  119. else//时刻到
  120. {
  121. ucRedFlag=0;//红棋和黑棋一起中止计时
  122. ucBlackFlag=0;
  123. ucWd=1;//切换到榜首个窗口的状况
  124. uiVoiceCnt=const_voice_long; //报警声响触发
  125. }
  126. ucDisplayUpdate=1;//更新显现
  127. }
  128. }
  129. }
  130. void display_service()//放在守时中止里的显现应用程序
  131. {
  132. if(ucDisplayUpdate==1)//有数据更新显现
  133. {
  134. ucDisplayUpdate=0;
  135. switch(ucWd) //本程序最中心的变量ucWd
  136. {
  137. case 1://窗口1,代表刚上电或许复位后的状况
  138. //红棋分解出分
  139. ucDigShowTemp=uiRedTotal/60;
  140. ucDigShow8=ucDigShowTemp/10;
  141. ucDigShow7=ucDigShowTemp%10;
  142. //红棋分解出秒
  143. ucDigShowTemp=uiRedTotal%60;
  144. ucDigShow6=ucDigShowTemp/10;
  145. ucDigShow5=ucDigShowTemp%10;
  146. ucDigDot7=1;//数码管7的小数点显现
  147. //黑棋分解出分
  148. ucDigShowTemp=uiBlackTotal/60;
  149. ucDigShow4=ucDigShowTemp/10;
  150. ucDigShow3=ucDigShowTemp%10;
  151. //黑棋分解出秒
  152. ucDigShowTemp=uiBlackTotal%60;
  153. ucDigShow2=ucDigShowTemp/10;
  154. ucDigShow1=ucDigShowTemp%10;
  155. ucDigDot3=1;//数码管3的小数点显现
  156. led_dr=1;//计时器处于中止状况,LED亮
  157. break;
  158. case 2://窗口2,代表黑棋正在运转中的状况
  159. //红棋悉数不显现
  160. ucDigShow8=10;
  161. ucDigShow7=10;
  162. ucDigShow6=10;
  163. ucDigShow5=10;
  164. ucDigDot7=0;//数码管7的小数点不显现
  165. //黑棋分解出分
  166. ucDigShowTemp=uiBlackTotal/60;
  167. ucDigShow4=ucDigShowTemp/10;
  168. ucDigShow3=ucDigShowTemp%10;
  169. //黑棋分解出秒
  170. ucDigShowTemp=uiBlackTotal%60;
  171. ucDigShow2=ucDigShowTemp/10;
  172. ucDigShow1=ucDigShowTemp%10;
  173. ucDigDot3=1;//数码管3的小数点显现
  174. led_dr=0;//计时器处于计时状况,LED灭
  175. break;
  176. case 3://窗口3,代表黑棋在半途暂停的状况
  177. //红棋悉数不显现
  178. ucDigShow8=10;
  179. ucDigShow7=10;
  180. ucDigShow6=10;
  181. ucDigShow5=10;
  182. ucDigDot7=0;//数码管7的小数点不显现
  183. //黑棋分解出分
  184. ucDigShowTemp=uiBlackTotal/60;
  185. ucDigShow4=ucDigShowTemp/10;
  186. ucDigShow3=ucDigShowTemp%10;
  187. //黑棋分解出秒
  188. ucDigShowTemp=uiBlackTotal%60;
  189. ucDigShow2=ucDigShowTemp/10;
  190. ucDigShow1=ucDigShowTemp%10;
  191. ucDigDot3=1;//数码管3的小数点显现
  192. led_dr=1;//计时器处于暂停状况,LED亮
  193. break;
  194. case 4://窗口4,代表红棋正在运转中的状况
  195. //红棋分解出分
  196. ucDigShowTemp=uiRedTotal/60;
  197. ucDigShow8=ucDigShowTemp/10;
  198. ucDigShow7=ucDigShowTemp%10;
  199. //红棋分解出秒
  200. ucDigShowTemp=uiRedTotal%60;
  201. ucDigShow6=ucDigShowTemp/10;
  202. ucDigShow5=ucDigShowTemp%10;
  203. ucDigDot7=1;//数码管7的小数点显现
  204. //黑棋悉数不显现
  205. ucDigShow4=10;
  206. ucDigShow3=10;
  207. ucDigShow2=10;
  208. ucDigShow1=10;
  209. ucDigDot3=0;//数码管3的小数点不显现
  210. led_dr=0;//计时器处于倒计时状况,LED灭
  211. break;
  212. case 5://窗口5,代表红棋在半途暂停的状况
  213. //红棋分解出分
  214. ucDigShowTemp=uiRedTotal/60;
  215. ucDigShow8=ucDigShowTemp/10;
  216. ucDigShow7=ucDigShowTemp%10;
  217. //红棋分解出秒
  218. ucDigShowTemp=uiRedTotal%60;
  219. ucDigShow6=ucDigShowTemp/10;
  220. ucDigShow5=ucDigShowTemp%10;
  221. ucDigDot7=1;//数码管7的小数点显现
  222. //黑棋悉数不显现
  223. ucDigShow4=10;
  224. ucDigShow3=10;
  225. ucDigShow2=10;
  226. ucDigShow1=10;
  227. ucDigDot3=0;//数码管3的小数点不显现
  228. led_dr=1;//计时器处于暂停状况,LED亮
  229. break;
  230. }
  231. }
  232. }
  233. void display_drive()//放在守时中止里的数码管驱动函数
  234. {
  235. //以下程序,假如加一些数组和移位的元素,还能够紧缩容量。可是鸿哥寻求的不是容量,而是明晰的解说思路
  236. switch(ucDisplayDriveStep)
  237. {
  238. case 1://显现第1位
  239. ucDigShowTemp=dig_table[ucDigShow1];
  240. dig_hc595_drive(ucDigShowTemp,0xfe);
  241. break;
  242. case 2://显现第2位
  243. ucDigShowTemp=dig_table[ucDigShow2];
  244. dig_hc595_drive(ucDigShowTemp,0xfd);
  245. break;
  246. case 3://显现第3位
  247. ucDigShowTemp=dig_table[ucDigShow3];
  248. if(ucDigDot3==1)
  249. {
  250. ucDigShowTemp=ucDigShowTemp|0x80;//显现小数点
  251. }
  252. dig_hc595_drive(ucDigShowTemp,0xfb);
  253. break;
  254. case 4://显现第4位
  255. ucDigShowTemp=dig_table[ucDigShow4];
  256. dig_hc595_drive(ucDigShowTemp,0xf7);
  257. break;
  258. case 5://显现第5位
  259. ucDigShowTemp=dig_table[ucDigShow5];
  260. dig_hc595_drive(ucDigShowTemp,0xef);
  261. break;
  262. case 6://显现第6位
  263. ucDigShowTemp=dig_table[ucDigShow6];
  264. dig_hc595_drive(ucDigShowTemp,0xdf);
  265. break;
  266. case 7://显现第7位
  267. ucDigShowTemp=dig_table[ucDigShow7];
  268. if(ucDigDot7==1)
  269. {
  270. ucDigShowTemp=ucDigShowTemp|0x80;//显现小数点
  271. }
  272. dig_hc595_drive(ucDigShowTemp,0xbf);
  273. break;
  274. case 8://显现第8位
  275. ucDigShowTemp=dig_table[ucDigShow8];
  276. dig_hc595_drive(ucDigShowTemp,0x7f);
  277. break;
  278. }
  279. ucDisplayDriveStep++;
  280. if(ucDisplayDriveStep>8)//扫描完8个数码管后,从头从榜首个开端扫描
  281. {
  282. ucDisplayDriveStep=1;
  283. }
  284. }
  285. //数码管的74HC595驱动函数
  286. void dig_hc595_drive(unsigned char ucDigStatusTemp16_09,unsigned char ucDigStatusTemp08_01)
  287. {
  288. unsigned char i;
  289. unsigned char ucTempData;
  290. dig_hc595_sh_dr=0;
  291. dig_hc595_st_dr=0;
  292. ucTempData=ucDigStatusTemp16_09;//先送高8位
  293. for(i=0;i<8;i++)
  294. {
  295. if(ucTempData>=0x80)dig_hc595_ds_dr=1;
  296. else dig_hc595_ds_dr=0;
  297. /* 注释二:
  298. *留意,此处的延时delay_short有必要尽可能小,不然动态扫描数码管的速度就不行。
  299. */
  300. dig_hc595_sh_dr=0; //SH引脚的上升沿把数据送入寄存器
  301. delay_short(1);
  302. dig_hc595_sh_dr=1;
  303. delay_short(1);
  304. ucTempData=ucTempData<<1;
  305. }
  306. ucTempData=ucDigStatusTemp08_01;//再先送低8位
  307. for(i=0;i<8;i++)
  308. {
  309. if(ucTempData>=0x80)dig_hc595_ds_dr=1;
  310. else dig_hc595_ds_dr=0;
  311. dig_hc595_sh_dr=0; //SH引脚的上升沿把数据送入寄存器
  312. delay_short(1);
  313. dig_hc595_sh_dr=1;
  314. delay_short(1);
  315. ucTempData=ucTempData<<1;
  316. }
  317. dig_hc595_st_dr=0;//ST引脚把两个寄存器的数据更新输出到74HC595的输出引脚上而且锁存起来
  318. delay_short(1);
  319. dig_hc595_st_dr=1;
  320. delay_short(1);
  321. dig_hc595_sh_dr=0; //拉低,抗干扰就增强
  322. dig_hc595_st_dr=0;
  323. dig_hc595_ds_dr=0;
  324. }
  325. //LED灯的74HC595驱动函数
  326. void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01)
  327. {
  328. unsigned char i;
  329. unsigned char ucTempData;
  330. hc595_sh_dr=0;
  331. hc595_st_dr=0;
  332. ucTempData=ucLedStatusTemp16_09;//先送高8位
  333. for(i=0;i<8;i++)
  334. {
  335. if(ucTempData>=0x80)hc595_ds_dr=1;
  336. else hc595_ds_dr=0;
  337. hc595_sh_dr=0; //SH引脚的上升沿把数据送入寄存器
  338. delay_short(1);
  339. hc595_sh_dr=1;
  340. delay_short(1);
  341. ucTempData=ucTempData<<1;
  342. }
  343. ucTempData=ucLedStatusTemp08_01;//再先送低8位
  344. for(i=0;i<8;i++)
  345. {
  346. if(ucTempData>=0x80)hc595_ds_dr=1;
  347. else hc595_ds_dr=0;
  348. hc595_sh_dr=0; //SH引脚的上升沿把数据送入寄存器
  349. delay_short(1);
  350. hc595_sh_dr=1;
  351. delay_short(1);
  352. ucTempData=ucTempData<<1;
  353. }
  354. hc595_st_dr=0;//ST引脚把两个寄存器的数据更新输出到74HC595的输出引脚上而且锁存起来
  355. delay_short(1);
  356. hc595_st_dr=1;
  357. delay_short(1);
  358. hc595_sh_dr=0; //拉低,抗干扰就增强
  359. hc595_st_dr=0;
  360. hc595_ds_dr=0;
  361. }
  362. void key_scan()//按键扫描函数 放在守时中止里
  363. {
  364. switch(ucKeyStep)
  365. {
  366. case 1: //按键扫描输出第ucRowRecord列低电平
  367. if(ucRowRecord==1)//榜首列输出低电平
  368. {
  369. key_dr1=0;
  370. key_dr2=1;
  371. key_dr3=1;
  372. key_dr4=1;
  373. }
  374. else if(ucRowRecord==2)//第二列输出低电平
  375. {
  376. key_dr1=1;
  377. key_dr2=0;
  378. key_dr3=1;
  379. key_dr4=1;
  380. }
  381. else if(ucRowRecord==3)//第三列输出低电平
  382. {
  383. key_dr1=1;
  384. key_dr2=1;
  385. key_dr3=0;
  386. key_dr4=1;
  387. }
  388. else //第四列输出低电平
  389. {
  390. key_dr1=1;
  391. key_dr2=1;
  392. key_dr3=1;
  393. key_dr4=0;
  394. }
  395. uiKeyTimeCnt=0;//延时计数器清零
  396. ucKeyStep++; //切换到下一个运转过程
  397. break;
  398. case 2: //此处的小延时用来等候方才列输出信号安稳,再判别输入信号。不是去颤动延时。
  399. uiKeyTimeCnt++;
  400. if(uiKeyTimeCnt>1)
  401. {
  402. uiKeyTimeCnt=0;
  403. ucKeyStep++; //切换到下一个运转过程
  404. }
  405. break;
  406. case 3:
  407. if(key_sr1==1&&key_sr2==1&&key_sr3==1&&key_sr4==1)
  408. {
  409. ucKeyStep=1;//假如没有按键按下,返回到榜首个运转过程从头开端扫描
  410. ucKeyLock=0;//按键自锁标志清零
  411. uiKeyTimeCnt=0; //按键去颤动延时计数器清零,此行十分奇妙
  412. ucRowRecord++;//输出下一列
  413. if(ucRowRecord>4)
  414. {
  415. ucRowRecord=1; //顺次输出完四列之后,持续从榜首列开端输出低电平
  416. }
  417. }
  418. else if(ucKeyLock==0)//有按键按下,且是榜首次触发
  419. {
  420. if(key_sr1==0&&key_sr2==1&&key_sr3==1&&key_sr4==1)
  421. {
  422. uiKeyTimeCnt++;//去颤动延时计数器
  423. if(uiKeyTimeCnt>const_key_time)
  424. {
  425. uiKeyTimeCnt=0;
  426. ucKeyLock=1;//自锁按键置位,防止一向触发,只要松开按键,此标志位才会被清零
  427. if(ucRowRecord==1)//榜首列输出低电平
  428. {
  429. ucKeySec=1;//触发1号键 对应朱兆祺学习板的S1键
  430. }
  431. else if(ucRowRecord==2)//第二列输出低电平
  432. {
  433. ucKeySec=2;//触发2号键 对应朱兆祺学习板的S2键
  434. }
  435. else if(ucRowRecord==3)//第三列输出低电平
  436. {
  437. ucKeySec=3;//触发3号键 对应朱兆祺学习板的S3键
  438. }
  439. else //第四列输出低电平
  440. {
  441. ucKeySec=4;//触发4号键 对应朱兆祺学习板的S4键
  442. }
  443. }
  444. }
  445. else if(key_sr1==1&&key_sr2==0&&key_sr3==1&&key_sr4==1)
  446. {
  447. uiKeyTimeCnt++;//去颤动延时计数器
  448. if(uiKeyTimeCnt>const_key_time)
  449. {
  450. uiKeyTimeCnt=0;
  451. ucKeyLock=1;//自锁按键置位,防止一向触发,只要松开按键,此标志位才会被清零
  452. if(ucRowRecord==1)//榜首列输出低电平
  453. {
  454. ucKeySec=5;//触发5号键 对应朱兆祺学习板的S5键
  455. }
  456. else if(ucRowRecord==2)//第二列输出低电平
  457. {
  458. ucKeySec=6;//触发6号键 对应朱兆祺学习板的S6键
  459. }
  460. else if(ucRowRecord==3)//第三列输出低电平
  461. {
  462. ucKeySec=7;//触发7号键 对应朱兆祺学习板的S7键
  463. }
  464. else //第四列输出低电平
  465. {
  466. ucKeySec=8;//触发8号键 对应朱兆祺学习板的S8键
  467. }
  468. }
  469. }
  470. else if(key_sr1==1&&key_sr2==1&&key_sr3==0&&key_sr4==1)
  471. {
  472. uiKeyTimeCnt++;//去颤动延时计数器
  473. if(uiKeyTimeCnt>const_key_time)
  474. {
  475. uiKeyTimeCnt=0;
  476. ucKeyLock=1;//自锁按键置位,防止一向触发,只要松开按键,此标志位才会被清零
  477. if(ucRowRecord==1)//榜首列输出低电平
  478. {
  479. ucKeySec=9;//触发9号键 对应朱兆祺学习板的S9键
  480. }
  481. else if(ucRowRecord==2)//第二列输出低电平
  482. {
  483. ucKeySec=10;//触发10号键 对应朱兆祺学习板的S10键
  484. }
  485. else if(ucRowRecord==3)//第三列输出低电平
  486. {
  487. ucKeySec=11;//触发11号键 对应朱兆祺学习板的S11键
  488. }
  489. else //第四列输出低电平
  490. {
  491. ucKeySec=12;//触发12号键 对应朱兆祺学习板的S12键
  492. }
  493. }
  494. }
  495. else if(key_sr1==1&&key_sr2==1&&key_sr3==1&&key_sr4==0)
  496. {
  497. uiKeyTimeCnt++;//去颤动延时计数器
  498. if(uiKeyTimeCnt>const_key_time)
  499. {
  500. uiKeyTimeCnt=0;
  501. ucKeyLock=1;//自锁按键置位,防止一向触发,只要松开按键,此标志位才会被清零
  502. if(ucRowRecord==1)//榜首列输出低电平
  503. {
  504. ucKeySec=13;//触发13号键 对应朱兆祺学习板的S13键
  505. }
  506. else if(ucRowRecord==2)//第二列输出低电平
  507. {
  508. ucKeySec=14;//触发14号键 对应朱兆祺学习板的S14键
  509. }
  510. else if(ucRowRecord==3)//第三列输出低电平
  511. {
  512. ucKeySec=15;//触发15号键 对应朱兆祺学习板的S15键
  513. }
  514. else //第四列输出低电平
  515. {
  516. ucKeySec=16;//触发16号键 对应朱兆祺学习板的S16键
  517. }
  518. }
  519. }
  520. }
  521. break;
  522. }
  523. }
  524. /* 注释三:
  525. *按键服务程序操作的精华在于依据当时体系处于什么窗口下就履行什么操作。
  526. *紧紧围绕着不同的窗口ucWd来履行不同的操作。
  527. */
  528. void key_service() //第三区 放在守时中止里的按键服务应用程序
  529. {
  530. switch(ucKeySec) //按键服务状况切换
  531. {
  532. case 1:// 1号键 对应朱兆祺学习板的S1键红棋加分 按键
  533. switch(ucWd)//本程序最中心的变量ucWd
  534. {
  535. case 1://窗口1,代表刚上电,完结或许复位后的状况
  536. uiRedTotal=uiRedTotal+60;//加红棋分的时刻,此处60秒代表一分
  537. if(uiRedTotal>5940)
  538. {
  539. uiRedTotal=5940;
  540. }
  541. uiRedTotal=uiRedTotal-(uiRedTotal%60);//去秒取整分
  542. ucDisplayUpdate=1;//更新显现
  543. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  544. break;
  545. case 2://窗口2,代表黑棋正在运转中的状况
  546. break;
  547. case 3://窗口3,代表黑棋在半途暂停的状况
  548. break;
  549. case 4://窗口4,代表红棋正在运转中的状况
  550. break;
  551. case 5://窗口5,代表红棋在半途暂停的状况
  552. break;
  553. }
  554. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  555. break;
  556. case 2:// 2号键 对应朱兆祺学习板的S2键红棋减分 按键
  557. switch(ucWd)//本程序最中心的变量ucWd
  558. {
  559. case 1://窗口1,代表刚上电,完结或许复位后的状况
  560. if(uiRedTotal>=60)
  561. {
  562. uiRedTotal=uiRedTotal-60;//减红棋分的时刻,此处60秒代表一分
  563. }
  564. uiRedTotal=uiRedTotal-(uiRedTotal%60);//去秒取整分
  565. ucDisplayUpdate=1;//更新显现
  566. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  567. break;
  568. case 2://窗口2,代表黑棋正在运转中的状况
  569. break;
  570. case 3://窗口3,代表黑棋在半途暂停的状况
  571. break;
  572. case 4://窗口4,代表红棋正在运转中的状况
  573. break;
  574. case 5://窗口5,代表红棋在半途暂停的状况
  575. break;
  576. }
  577. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  578. break;
  579. case 3:// 3号键 对应朱兆祺学习板的S3键黑棋加分 按键
  580. switch(ucWd)//本程序最中心的变量ucWd
  581. {
  582. case 1://窗口1,代表刚上电,完结或许复位后的状况
  583. uiBlackTotal=uiBlackTotal+60;//加黑棋分的时刻,此处60秒代表一分
  584. if(uiBlackTotal>5940)
  585. {
  586. uiBlackTotal=5940;
  587. }
  588. uiBlackTotal=uiBlackTotal-(uiBlackTotal%60);//去秒取整分
  589. ucDisplayUpdate=1;//更新显现
  590. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  591. break;
  592. case 2://窗口2,代表黑棋正在运转中的状况
  593. break;
  594. case 3://窗口3,代表黑棋在半途暂停的状况
  595. break;
  596. case 4://窗口4,代表红棋正在运转中的状况
  597. break;
  598. case 5://窗口5,代表红棋在半途暂停的状况
  599. break;
  600. }
  601. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  602. break;
  603. case 4:// 4号键 对应朱兆祺学习板的S4键黑棋减分 按键
  604. switch(ucWd)//本程序最中心的变量ucWd
  605. {
  606. case 1://窗口1,代表刚上电,完结或许复位后的状况
  607. if(uiBlackTotal>=60)
  608. {
  609. uiBlackTotal=uiBlackTotal-60;//减黑棋分的时刻,此处60秒代表一分
  610. }
  611. uiBlackTotal=uiBlackTotal-(uiBlackTotal%60);//去秒取整分
  612. ucDisplayUpdate=1;//更新显现
  613. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  614. break;
  615. case 2://窗口2,代表黑棋正在运转中的状况
  616. break;
  617. case 3://窗口3,代表黑棋在半途暂停的状况
  618. break;
  619. case 4://窗口4,代表红棋正在运转中的状况
  620. break;
  621. case 5://窗口5,代表红棋在半途暂停的状况
  622. break;
  623. }
  624. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  625. break;
  626. case 5:// 5号键 对应朱兆祺学习板的S5键
  627. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  628. break;
  629. case 6:// 6号键 对应朱兆祺学习板的S6键半途暂停和发动按键
  630. switch(ucWd)//本程序最中心的变量ucWd
  631. {
  632. case 1://窗口1,代表刚上电,完结或许复位后的状况
  633. break;
  634. case 2://窗口2,代表黑棋正在运转中的状况
  635. ucRedFlag=0; //暂停计时
  636. ucBlackFlag=0;//暂停计时
  637. ucWd=3; //切换到黑棋半途暂停的状况
  638. ucDisplayUpdate=1;//更新显现
  639. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  640. break;
  641. case 3://窗口3,代表黑棋在半途暂停的状况
  642. ucRedFlag=0; //红棋暂停计时
  643. ucBlackFlag=1; //黑棋持续计时
  644. ucWd=2; //切换到黑棋正在运转中的状况
  645. ucDisplayUpdate=1;//更新显现
  646. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  647. break;
  648. case 4://窗口4,代表红棋正在运转中的状况
  649. ucRedFlag=0; //暂停计时
  650. ucBlackFlag=0;//暂停计时
  651. ucWd=5; //切换到红棋半途暂停的状况
  652. ucDisplayUpdate=1;//更新显现
  653. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  654. break;
  655. case 5://窗口5,代表红棋在半途暂停的状况
  656. ucRedFlag=1; //红棋持续计时
  657. ucBlackFlag=0; //黑棋暂停计时
  658. ucWd=4; //切换到红棋正在运转中的状况
  659. ucDisplayUpdate=1;//更新显现
  660. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  661. break;
  662. }
  663. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  664. break;
  665. case 7:// 7号键 对应朱兆祺学习板的S7键在榜首个窗口下,把计时器的值康复为开机时的默许值20分钟
  666. switch(ucWd)//本程序最中心的变量ucWd
  667. {
  668. case 1://窗口1,代表刚上电,完结或许复位后的状况
  669. uiRedTotal=1200; //红棋的总时刻
  670. uiBlackTotal=1200;//黑棋的总时刻
  671. ucDisplayUpdate=1;//更新显现
  672. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  673. break;
  674. case 2://窗口2,代表黑棋正在运转中的状况
  675. break;
  676. case 3://窗口3,代表黑棋在半途暂停的状况
  677. break;
  678. case 4://窗口4,代表红棋正在运转中的状况
  679. break;
  680. case 5://窗口5,代表红棋在半途暂停的状况
  681. break;
  682. }
  683. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  684. break;
  685. case 8:// 8号键 对应朱兆祺学习板的S8键
  686. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  687. break;
  688. case 9:// 9号键 对应朱兆祺学习板的S9键
  689. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  690. break;
  691. case 10:// 10号键 对应朱兆祺学习板的S10键
  692. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  693. break;
  694. case 11:// 11号键 对应朱兆祺学习板的S11键
  695. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  696. break;
  697. case 12:// 12号键 对应朱兆祺学习板的S12键
  698. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  699. break;
  700. case 13:// 13号键 对应朱兆祺学习板的S13键红棋按下
  701. switch(ucWd)//本程序最中心的变量ucWd
  702. {
  703. case 1://窗口1,代表刚上电,完结或许复位后的状况
  704. ucRedFlag=0; //红棋暂停计时
  705. ucBlackFlag=1;//黑棋持续计时
  706. ucWd=2; //切换到黑棋正在运转中的状况
  707. ucDisplayUpdate=1;//更新显现
  708. break;
  709. case 2://窗口2,代表黑棋正在运转中的状况
  710. break;
  711. case 3://窗口3,代表黑棋在半途暂停的状况
  712. break;
  713. case 4://窗口4,代表红棋正在运转中的状况
  714. ucRedFlag=0; //红棋暂停计时
  715. ucBlackFlag=1;//黑棋持续计时
  716. ucWd=2; //切换到黑棋正在运转中的状况
  717. ucDisplayUpdate=1;//更新显现
  718. break;
  719. case 5://窗口5,代表红棋在半途暂停的状况
  720. break;
  721. }
  722. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  723. break;
  724. case 14:// 14号键 对应朱兆祺学习板的S14键
  725. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  726. break;
  727. case 15:// 15号键 对应朱兆祺学习板的S15键
  728. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  729. break;
  730. case 16:// 16号键 对应朱兆祺学习板的S16键 黑棋按下
  731. switch(ucWd)//本程序最中心的变量ucWd
  732. {
  733. case 1://窗口1,代表刚上电,完结或许复位后的状况
  734. ucRedFlag=1; //红棋持续计时
  735. ucBlackFlag=0;//黑棋暂停计时
  736. ucWd=4; //切换到红棋正在运转中的状况
  737. ucDisplayUpdate=1;//更新显现
  738. break;
  739. case 2://窗口2,代表黑棋正在运转中的状况
  740. ucRedFlag=1; //红棋持续计时
  741. ucBlackFlag=0;//黑棋暂停计时
  742. ucWd=4; //切换到红棋正在运转中的状况
  743. ucDisplayUpdate=1;//更新显现
  744. break;
  745. case 3://窗口3,代表黑棋在半途暂停的状况
  746. break;
  747. case 4://窗口4,代表红棋正在运转中的状况
  748. break;
  749. case 5://窗口5,代表红棋在半途暂停的状况
  750. break;
  751. }
  752. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  753. break;
  754. }
  755. }
  756. void T0_time() interrupt 1
  757. {
  758. TF0=0;//铲除中止标志
  759. TR0=0; //关中止
  760. key_scan(); //放在守时中止里的按键扫描函数
  761. time_service();//放在守时中止里的时刻应用程序
  762. if(uiVoiceCnt!=0)
  763. {
  764. uiVoiceCnt–; //每次进入守时中止都自减1,直到等于零中止。才中止鸣叫
  765. beep_dr=0;//蜂鸣器是PNP三极管操控,低电平就开端鸣叫。
  766. }
  767. else
  768. {
  769. ; //此处多加一个空指令,想保持跟if括号句子的数量对称,都是两条指令。不加也能够。
  770. beep_dr=1;//蜂鸣器是PNP三极管操控,高电平就中止鸣叫。
  771. }
  772. display_drive();//放在守时中止里的数码管驱动函数
  773. /* 注释四:
  774. *留意,此处的重装初始值不能太大,不然动态扫描数码管的速度就不行。我把本来常用的2000改成了500。
  775. */
  776. TH0=0xfe; //重装初始值(65535-500)=65035=0xfe0b
  777. TL0=0x0b;
  778. TR0=1;//开中止
  779. }
  780. void delay_short(unsigned int uiDelayShort)
  781. {
  782. unsigned int i;
  783. for(i=0;i
  784. {
  785. ; //一个分号相当于履行一条空句子
  786. }
  787. }
  788. void delay_long(unsigned int uiDelayLong)
  789. {
  790. unsigned int i;
  791. unsigned int j;
  792. for(i=0;i
  793. {
  794. for(j=0;j<500;j++)//内嵌循环的空指令数量
  795. {
  796. ; //一个分号相当于履行一条空句子
  797. }
  798. }
  799. }
  800. void initial_myself()//榜首区 初始化单片机
  801. {
  802. led_dr=1;
  803. beep_dr=1; //用PNP三极管操控蜂鸣器,输出高电平时不叫。
  804. hc595_drive(0x00,0x00);
  805. TMOD=0x01;//设置守时器0为工作方式1
  806. TH0=0xfe; //重装初始值(65535-500)=65035=0xfe0b
  807. TL0=0x0b;
  808. }
  809. void initial_peripheral() //第二区 初始化外围
  810. {
  811. EA=1; //开总中止
  812. ET0=1; //答应守时中止
  813. TR0=1; //发动守时中止
  814. }

总结陈词:
这节讲了象棋竞赛专用计时器的项目程序。为了持续加深读者了解按键和显现是怎么有规则相关起来的,下节会持续讲一个相关的小项目程序。欲知概况,请听下回分解—–带数码管显现的加法简易计算器。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/changshang/fabu/262086.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部