在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > 第35節(jié):帶數碼管顯示的象棋比賽專用計時器

            第35節(jié):帶數碼管顯示的象棋比賽專用計時器

            作者: 時間:2016-11-22 來源:網絡 收藏
            開場白:
            2014年春節(jié)的時候,一幫朋友舉行小規(guī)模的象棋比賽,有一些朋友下棋的速度實在是太慢了,為了限制比賽時間,我專門用朱兆祺的51學習板做了一個棋類比賽專用計時器給他們用。這一節(jié)要教會大家兩個知識點:
            第一個:按鍵服務程序操作的精髓在于根據當前系統(tǒng)處于什么窗口狀態(tài)下就執(zhí)行什么操作。緊緊圍繞著不同的窗口ucWd來執(zhí)行不同的操作。
            第二個:繼續(xù)加深熟悉鴻哥首次提出的“一二級菜單顯示理論”:凡是人機界面顯示,不管是數碼管還是液晶屏,都可以把顯示的內容分成不同的窗口來顯示,每個顯示的窗口中又可以分成不同的局部顯示。其中窗口就是一級菜單,用ucWd變量表示。局部就是二級菜單,用ucPart來表示。不同的窗口,會有不同的更新顯示變量ucWdXUpdate來對應,表示整屏全部更新顯示。不同的局部,也會有不同的更新顯示變量ucWdXPartYUpdate來對應,表示局部更新顯示。

            具體內容,請看源代碼講解。

            (1)硬件平臺:基于朱兆祺51單片機學習板。
            剛上電開機時,紅棋加時鍵對應S1鍵,紅棋減時鍵對應S2鍵.。
            剛上電開機時,黑棋加時鍵對應S3鍵,黑棋減時鍵對應S4鍵.。
            比賽中途暫停雙方計時的暫停按鍵對應S6鍵。剛上電時,復位雙方默認20分時間的復位按鍵對應S7按鍵。
            紅棋的搶時按鍵對應S13鍵,黑棋的搶時按鍵對應S16按鍵。

            (2)實現功能:
            棋類計時器有點像搶答器,本質上有兩個計時器。比賽的時候對弈的兩個棋友各用一個不同的按鍵搶時間,紅棋走一步棋后,就按一下自己的搶時按鍵,這個時候紅棋的計時器停止計時,而黑棋的計時器開始計時,黑棋走了一步棋后,按一下自己的計時器,黑棋停止計時,紅棋繼續(xù)計時,依次循環(huán),誰的時間最先用完誰就輸,蜂鳴器也會發(fā)出長鳴的聲音提示時間到。
            上電開機默認雙方各有20分鐘的時間,左邊顯示的是紅棋的時間,右邊顯示的是黑棋的時間。此時可以通過S1,S2.,S3,S4的加減按鍵來設置各自的最大倒計時時間。此時如果按下復位按鍵S7,會自動把雙方的時間設置為默認的20分鐘。
            設置好最大倒計時的時間后,此時任意一方按下各自的搶時按鍵(S13或者S16),則自己的計時器停止計時,而對方開始倒計時。此時數碼管顯示的是對方的時間,而自己的時間屏蔽不顯示。
            在開始倒計時的時候,如果中途有棋友要接聽電話或者忙別的事情,需要暫時暫停一下雙方的時間,這個時候可以按S6暫停按鍵來暫停雙方的計時,忙完后再次按下暫停按鍵會繼續(xù)倒計時。任何一方的時間走完,都會蜂鳴器長鳴提示。
            (3)源代碼講解如下:
            1. #include "REG52.H"
            2. #define const_voice_short40 //蜂鳴器短叫的持續(xù)時間
            3. #define const_voice_long 900 //蜂鳴器長叫的持續(xù)時間
            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; //被觸發(fā)的按鍵編號
            35. unsigned intuiKeyTimeCnt=0; //按鍵去抖動延時計數器
            36. unsigned char ucKeyLock=0; //按鍵觸發(fā)后自鎖的變量標志
            37. unsigned char ucRowRecord=1; //記錄當前掃描到第幾列了
            38. unsigned intuiVoiceCnt=0;//蜂鳴器鳴叫的持續(xù)時間計數器
            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;//動態(tài)掃描數碼管的步驟變量
            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變量是本程序最核心的變量,代表顯示哪一個窗口和系統(tǒng)處于當前哪種狀態(tài)
            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;//切換到第一個窗口的狀態(tài)
            104. uiVoiceCnt=const_voice_long; //報警聲音觸發(fā)
            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;//切換到第一個窗口的狀態(tài)
            124. uiVoiceCnt=const_voice_long; //報警聲音觸發(fā)
            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,代表剛上電或者復位后的狀態(tài)
            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;//計時器處于停止狀態(tài),LED亮
            157. break;
            158. case 2://窗口2,代表黑棋正在運行中的狀態(tài)
            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;//計時器處于計時狀態(tài),LED滅
            175. break;
            176. case 3://窗口3,代表黑棋在中途暫停的狀態(tài)
            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;//計時器處于暫停狀態(tài),LED亮
            193. break;
            194. case 4://窗口4,代表紅棋正在運行中的狀態(tài)
            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;//計時器處于倒計時狀態(tài),LED滅
            211. break;
            212. case 5://窗口5,代表紅棋在中途暫停的狀態(tài)
            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;//計時器處于暫停狀態(tài),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必須盡可能小,否則動態(tài)掃描數碼管的速度就不夠。
            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: //此處的小延時用來等待剛才列輸出信號穩(wěn)定,再判斷輸入信號。不是去抖動延時。
            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; //依次輸出完四列之后,繼續(xù)從第一列開始輸出低電平
            416. }
            417. }
            418. else if(ucKeyLock==0)//有按鍵按下,且是第一次觸發(fā)
            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;//自鎖按鍵置位,避免一直觸發(fā),只有松開按鍵,此標志位才會被清零
            427. if(ucRowRecord==1)//第一列輸出低電平
            428. {
            429. ucKeySec=1;//觸發(fā)1號鍵 對應朱兆祺學習板的S1鍵
            430. }
            431. else if(ucRowRecord==2)//第二列輸出低電平
            432. {
            433. ucKeySec=2;//觸發(fā)2號鍵 對應朱兆祺學習板的S2鍵
            434. }
            435. else if(ucRowRecord==3)//第三列輸出低電平
            436. {
            437. ucKeySec=3;//觸發(fā)3號鍵 對應朱兆祺學習板的S3鍵
            438. }
            439. else //第四列輸出低電平
            440. {
            441. ucKeySec=4;//觸發(fā)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;//自鎖按鍵置位,避免一直觸發(fā),只有松開按鍵,此標志位才會被清零
            452. if(ucRowRecord==1)//第一列輸出低電平
            453. {
            454. ucKeySec=5;//觸發(fā)5號鍵 對應朱兆祺學習板的S5鍵
            455. }
            456. else if(ucRowRecord==2)//第二列輸出低電平
            457. {
            458. ucKeySec=6;//觸發(fā)6號鍵 對應朱兆祺學習板的S6鍵
            459. }
            460. else if(ucRowRecord==3)//第三列輸出低電平
            461. {
            462. ucKeySec=7;//觸發(fā)7號鍵 對應朱兆祺學習板的S7鍵
            463. }
            464. else //第四列輸出低電平
            465. {
            466. ucKeySec=8;//觸發(fā)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;//自鎖按鍵置位,避免一直觸發(fā),只有松開按鍵,此標志位才會被清零
            477. if(ucRowRecord==1)//第一列輸出低電平
            478. {
            479. ucKeySec=9;//觸發(fā)9號鍵 對應朱兆祺學習板的S9鍵
            480. }
            481. else if(ucRowRecord==2)//第二列輸出低電平
            482. {
            483. ucKeySec=10;//觸發(fā)10號鍵 對應朱兆祺學習板的S10鍵
            484. }
            485. else if(ucRowRecord==3)//第三列輸出低電平
            486. {
            487. ucKeySec=11;//觸發(fā)11號鍵 對應朱兆祺學習板的S11鍵
            488. }
            489. else //第四列輸出低電平
            490. {
            491. ucKeySec=12;//觸發(fā)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;//自鎖按鍵置位,避免一直觸發(fā),只有松開按鍵,此標志位才會被清零
            502. if(ucRowRecord==1)//第一列輸出低電平
            503. {
            504. ucKeySec=13;//觸發(fā)13號鍵 對應朱兆祺學習板的S13鍵
            505. }
            506. else if(ucRowRecord==2)//第二列輸出低電平
            507. {
            508. ucKeySec=14;//觸發(fā)14號鍵 對應朱兆祺學習板的S14鍵
            509. }
            510. else if(ucRowRecord==3)//第三列輸出低電平
            511. {
            512. ucKeySec=15;//觸發(fā)15號鍵 對應朱兆祺學習板的S15鍵
            513. }
            514. else //第四列輸出低電平
            515. {
            516. ucKeySec=16;//觸發(fā)16號鍵 對應朱兆祺學習板的S16鍵
            517. }
            518. }
            519. }
            520. }
            521. break;
            522. }
            523. }
            524. /* 注釋三:
            525. *按鍵服務程序操作的精髓在于根據當前系統(tǒng)處于什么窗口下就執(zhí)行什么操作。
            526. *緊緊圍繞著不同的窗口ucWd來執(zhí)行不同的操作。
            527. */
            528. void key_service() //第三區(qū) 放在定時中斷里的按鍵服務應用程序
            529. {
            530. switch(ucKeySec) //按鍵服務狀態(tài)切換
            531. {
            532. case 1:// 1號鍵 對應朱兆祺學習板的S1鍵紅棋加分 按鍵
            533. switch(ucWd)//本程序最核心的變量ucWd
            534. {
            535. case 1://窗口1,代表剛上電,完成或者復位后的狀態(tài)
            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; //按鍵聲音觸發(fā),滴一聲就停。
            544. break;
            545. case 2://窗口2,代表黑棋正在運行中的狀態(tài)
            546. break;
            547. case 3://窗口3,代表黑棋在中途暫停的狀態(tài)
            548. break;
            549. case 4://窗口4,代表紅棋正在運行中的狀態(tài)
            550. break;
            551. case 5://窗口5,代表紅棋在中途暫停的狀態(tài)
            552. break;
            553. }
            554. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發(fā)
            555. break;
            556. case 2:// 2號鍵 對應朱兆祺學習板的S2鍵紅棋減分 按鍵
            557. switch(ucWd)//本程序最核心的變量ucWd
            558. {
            559. case 1://窗口1,代表剛上電,完成或者復位后的狀態(tài)
            560. if(uiRedTotal>=60)
            561. {
            562. uiRedTotal=uiRedTotal-60;//減紅棋分的時間,此處60秒代表一分
            563. }
            564. uiRedTotal=uiRedTotal-(uiRedTotal%60);//去秒取整分
            565. ucDisplayUpdate=1;//更新顯示
            566. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
            567. break;
            568. case 2://窗口2,代表黑棋正在運行中的狀態(tài)
            569. break;
            570. case 3://窗口3,代表黑棋在中途暫停的狀態(tài)
            571. break;
            572. case 4://窗口4,代表紅棋正在運行中的狀態(tài)
            573. break;
            574. case 5://窗口5,代表紅棋在中途暫停的狀態(tài)
            575. break;
            576. }
            577. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發(fā)
            578. break;
            579. case 3:// 3號鍵 對應朱兆祺學習板的S3鍵黑棋加分 按鍵
            580. switch(ucWd)//本程序最核心的變量ucWd
            581. {
            582. case 1://窗口1,代表剛上電,完成或者復位后的狀態(tài)
            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; //按鍵聲音觸發(fā),滴一聲就停。
            591. break;
            592. case 2://窗口2,代表黑棋正在運行中的狀態(tài)
            593. break;
            594. case 3://窗口3,代表黑棋在中途暫停的狀態(tài)
            595. break;
            596. case 4://窗口4,代表紅棋正在運行中的狀態(tài)
            597. break;
            598. case 5://窗口5,代表紅棋在中途暫停的狀態(tài)
            599. break;
            600. }
            601. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發(fā)
            602. break;
            603. case 4:// 4號鍵 對應朱兆祺學習板的S4鍵黑棋減分 按鍵
            604. switch(ucWd)//本程序最核心的變量ucWd
            605. {
            606. case 1://窗口1,代表剛上電,完成或者復位后的狀態(tài)
            607. if(uiBlackTotal>=60)
            608. {
            609. uiBlackTotal=uiBlackTotal-60;//減黑棋分的時間,此處60秒代表一分
            610. }
            611. uiBlackTotal=uiBlackTotal-(uiBlackTotal%60);//去秒取整分
            612. ucDisplayUpdate=1;//更新顯示
            613. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
            614. break;
            615. case 2://窗口2,代表黑棋正在運行中的狀態(tài)
            616. break;
            617. case 3://窗口3,代表黑棋在中途暫停的狀態(tài)
            618. break;
            619. case 4://窗口4,代表紅棋正在運行中的狀態(tài)
            620. break;
            621. case 5://窗口5,代表紅棋在中途暫停的狀態(tài)
            622. break;
            623. }
            624. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發(fā)
            625. break;
            626. case 5:// 5號鍵 對應朱兆祺學習板的S5鍵
            627. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發(fā)
            628. break;
            629. case 6:// 6號鍵 對應朱兆祺學習板的S6鍵中途暫停和啟動按鍵
            630. switch(ucWd)//本程序最核心的變量ucWd
            631. {
            632. case 1://窗口1,代表剛上電,完成或者復位后的狀態(tài)
            633. break;
            634. case 2://窗口2,代表黑棋正在運行中的狀態(tài)
            635. ucRedFlag=0; //暫停計時
            636. ucBlackFlag=0;//暫停計時
            637. ucWd=3; //切換到黑棋中途暫停的狀態(tài)
            638. ucDisplayUpdate=1;//更新顯示
            639. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
            640. break;
            641. case 3://窗口3,代表黑棋在中途暫停的狀態(tài)
            642. ucRedFlag=0; //紅棋暫停計時
            643. ucBlackFlag=1; //黑棋繼續(xù)計時
            644. ucWd=2; //切換到黑棋正在運行中的狀態(tài)
            645. ucDisplayUpdate=1;//更新顯示
            646. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
            647. break;
            648. case 4://窗口4,代表紅棋正在運行中的狀態(tài)
            649. ucRedFlag=0; //暫停計時
            650. ucBlackFlag=0;//暫停計時
            651. ucWd=5; //切換到紅棋中途暫停的狀態(tài)
            652. ucDisplayUpdate=1;//更新顯示
            653. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
            654. break;
            655. case 5://窗口5,代表紅棋在中途暫停的狀態(tài)
            656. ucRedFlag=1; //紅棋繼續(xù)計時
            657. ucBlackFlag=0; //黑棋暫停計時
            658. ucWd=4; //切換到紅棋正在運行中的狀態(tài)
            659. ucDisplayUpdate=1;//更新顯示
            660. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
            661. break;
            662. }
            663. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發(fā)
            664. break;
            665. case 7:// 7號鍵 對應朱兆祺學習板的S7鍵在第一個窗口下,把計時器的值恢復為開機時的默認值20分鐘
            666. switch(ucWd)//本程序最核心的變量ucWd
            667. {
            668. case 1://窗口1,代表剛上電,完成或者復位后的狀態(tài)
            669. uiRedTotal=1200; //紅棋的總時間
            670. uiBlackTotal=1200;//黑棋的總時間
            671. ucDisplayUpdate=1;//更新顯示
            672. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
            673. break;
            674. case 2://窗口2,代表黑棋正在運行中的狀態(tài)
            675. break;
            676. case 3://窗口3,代表黑棋在中途暫停的狀態(tài)
            677. break;
            678. case 4://窗口4,代表紅棋正在運行中的狀態(tài)
            679. break;
            680. case 5://窗口5,代表紅棋在中途暫停的狀態(tài)
            681. break;
            682. }
            683. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發(fā)
            684. break;
            685. case 8:// 8號鍵 對應朱兆祺學習板的S8鍵
            686. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發(fā)
            687. break;
            688. case 9:// 9號鍵 對應朱兆祺學習板的S9鍵
            689. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發(fā)
            690. break;
            691. case 10:// 10號鍵 對應朱兆祺學習板的S10鍵
            692. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發(fā)
            693. break;
            694. case 11:// 11號鍵 對應朱兆祺學習板的S11鍵
            695. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發(fā)
            696. break;
            697. case 12:// 12號鍵 對應朱兆祺學習板的S12鍵
            698. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發(fā)
            699. break;
            700. case 13:// 13號鍵 對應朱兆祺學習板的S13鍵紅棋按下
            701. switch(ucWd)//本程序最核心的變量ucWd
            702. {
            703. case 1://窗口1,代表剛上電,完成或者復位后的狀態(tài)
            704. ucRedFlag=0; //紅棋暫停計時
            705. ucBlackFlag=1;//黑棋繼續(xù)計時
            706. ucWd=2; //切換到黑棋正在運行中的狀態(tài)
            707. ucDisplayUpdate=1;//更新顯示
            708. break;
            709. case 2://窗口2,代表黑棋正在運行中的狀態(tài)
            710. break;
            711. case 3://窗口3,代表黑棋在中途暫停的狀態(tài)
            712. break;
            713. case 4://窗口4,代表紅棋正在運行中的狀態(tài)
            714. ucRedFlag=0; //紅棋暫停計時
            715. ucBlackFlag=1;//黑棋繼續(xù)計時
            716. ucWd=2; //切換到黑棋正在運行中的狀態(tài)
            717. ucDisplayUpdate=1;//更新顯示
            718. break;
            719. case 5://窗口5,代表紅棋在中途暫停的狀態(tài)
            720. break;
            721. }
            722. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發(fā)
            723. break;
            724. case 14:// 14號鍵 對應朱兆祺學習板的S14鍵
            725. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發(fā)
            726. break;
            727. case 15:// 15號鍵 對應朱兆祺學習板的S15鍵
            728. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發(fā)
            729. break;
            730. case 16:// 16號鍵 對應朱兆祺學習板的S16鍵 黑棋按下
            731. switch(ucWd)//本程序最核心的變量ucWd
            732. {
            733. case 1://窗口1,代表剛上電,完成或者復位后的狀態(tài)
            734. ucRedFlag=1; //紅棋繼續(xù)計時
            735. ucBlackFlag=0;//黑棋暫停計時
            736. ucWd=4; //切換到紅棋正在運行中的狀態(tài)
            737. ucDisplayUpdate=1;//更新顯示
            738. break;
            739. case 2://窗口2,代表黑棋正在運行中的狀態(tài)
            740. ucRedFlag=1; //紅棋繼續(xù)計時
            741. ucBlackFlag=0;//黑棋暫停計時
            742. ucWd=4; //切換到紅棋正在運行中的狀態(tài)
            743. ucDisplayUpdate=1;//更新顯示
            744. break;
            745. case 3://窗口3,代表黑棋在中途暫停的狀態(tài)
            746. break;
            747. case 4://窗口4,代表紅棋正在運行中的狀態(tài)
            748. break;
            749. case 5://窗口5,代表紅棋在中途暫停的狀態(tài)
            750. break;
            751. }
            752. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發(fā)
            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. *注意,此處的重裝初始值不能太大,否則動態(tài)掃描數碼管的速度就不夠。我把原來常用的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. ; //一個分號相當于執(zhí)行一條空語句
            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++)//內嵌循環(huán)的空指令數量
            795. {
            796. ; //一個分號相當于執(zhí)行一條空語句
            797. }
            798. }
            799. }
            800. void initial_myself()//第一區(qū) 初始化單片機
            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() //第二區(qū) 初始化外圍
            810. {
            811. EA=1; //開總中斷
            812. ET0=1; //允許定時中斷
            813. TR0=1; //啟動定時中斷
            814. }


            總結陳詞:
            這節(jié)講了象棋比賽專用計時器的項目程序。為了繼續(xù)加深讀者理解按鍵和顯示是如何有規(guī)律關聯(lián)起來的,下節(jié)會繼續(xù)講一個相關的小項目程序。欲知詳情,請聽下回分解-----帶數碼管顯示的加法簡易計算器。


            評論


            技術專區(qū)

            關閉