新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 第34節:在數碼管中實現iphone4S開機密碼鎖的程序

        第34節:在數碼管中實現iphone4S開機密碼鎖的程序

        作者: 時間:2016-11-22 來源:網絡 收藏
        開場白:
        這一節要教會大家四個知識點:
        第一個:類似手機上10秒鐘內無按鍵操作將自動進入鎖屏的程序。
        第二個:如何用一個數組來接收按鍵的一串數字輸入。
        第三個:矩陣鍵盤中,數字按鍵的輸入,由于這部分按鍵的代碼相似度非常高,因此把它封裝在一個函數里可以非常簡潔方便。
        第四個:繼續加深熟悉鴻哥首次提出的“一二級菜單顯示理論”:凡是人機界面顯示,不管是數碼管還是液晶屏,都可以把顯示的內容分成不同的窗口來顯示,每個顯示的窗口中又可以分成不同的局部顯示。其中窗口就是一級菜單,用ucWd變量表示。局部就是二級菜單,用ucPart來表示。不同的窗口,會有不同的更新顯示變量ucWdXUpdate來對應,表示整屏全部更新顯示。不同的局部,也會有不同的更新顯示變量ucWdXPartYUpdate來對應,表示局部更新顯示。

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

        (1)硬件平臺:基于朱兆祺51單片機學習板。數字1鍵對應S1鍵,數字2鍵對應S2鍵,數字3鍵對應S3鍵…. 數字9鍵對應S9鍵, 數字0鍵對應S10鍵。其他的按鍵不用。

        (2)實現功能:
        本程序有3個窗口。
        開機顯示第1個密碼登錄框窗口“----”,在這個窗口下輸入密碼,如果密碼等于”9922”表示密碼正確,將會切換到第2個顯示按鍵值的窗口。在窗口2下,按不同的按鍵會顯示不同的按鍵值,如果10秒內沒有按鍵操作,將會自動切換到第1個密碼登錄窗口,類似手機上的自動鎖屏操作。在密碼登錄窗口1下,如果密碼不正確,會自動清除密碼的數字,繼續在窗口1下顯示”----”。
        窗口3是用來停留0.5秒顯示全部密碼的信息,然后根據密碼的正確與否自動切換到對應的窗口。

        (3)源代碼講解如下:
        1. #include "REG52.H"
        2. #define const_no_key_push 4400 //大概10秒內無按鍵按下的時間
        3. #define const_0_1s220 //大概0.5秒的時間
        4. #define const_voice_short40 //蜂鳴器短叫的持續時間
        5. #define const_key_time20 //按鍵去抖動延時的時間
        6. void initial_myself();
        7. void initial_peripheral();
        8. void delay_short(unsigned int uiDelayShort);
        9. void delay_long(unsigned int uiDelaylong);
        10. //驅動數碼管的74HC595
        11. void dig_hc595_drive(unsigned char ucDigStatusTemp16_09,unsigned char ucDigStatusTemp08_01);
        12. void display_drive(); //顯示數碼管字模的驅動函數
        13. void display_service(); //顯示的窗口菜單服務程序
        14. //驅動LED的74HC595
        15. void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01);
        16. void T0_time();//定時中斷函數
        17. void number_key_input(unsigned char ucWhichKey);//由于數字按鍵的代碼相似度高,因此封裝在這個函數里
        18. void key_service(); //按鍵服務的應用程序
        19. void key_scan();//按鍵掃描函數 放在定時中斷里
        20. sbit key_sr1=P0^0; //第一行輸入
        21. sbit key_sr2=P0^1; //第二行輸入
        22. sbit key_sr3=P0^2; //第三行輸入
        23. sbit key_sr4=P0^3; //第四行輸入
        24. sbit key_dr1=P0^4; //第一列輸出
        25. sbit key_dr2=P0^5; //第二列輸出
        26. sbit key_dr3=P0^6; //第三列輸出
        27. sbit key_dr4=P0^7; //第四列輸出
        28. sbit beep_dr=P2^7; //蜂鳴器的驅動IO口
        29. sbit led_dr=P3^5;//作為中途暫停指示燈 亮的時候表示中途暫停
        30. sbit dig_hc595_sh_dr=P2^0; //數碼管的74HC595程序
        31. sbit dig_hc595_st_dr=P2^1;
        32. sbit dig_hc595_ds_dr=P2^2;
        33. sbit hc595_sh_dr=P2^3; //LED燈的74HC595程序
        34. sbit hc595_st_dr=P2^4;
        35. sbit hc595_ds_dr=P2^5;
        36. unsigned char ucKeyStep=1;//按鍵掃描步驟變量
        37. unsigned intuiKeyTimeCnt=0; //按鍵去抖動延時計數器
        38. unsigned char ucKeyLock=0; //按鍵觸發后自鎖的變量標志
        39. unsigned char ucRowRecord=1; //記錄當前掃描到第幾列了
        40. unsigned char ucKeySec=0; //被觸發的按鍵編號
        41. unsigned intuiVoiceCnt=0;//蜂鳴器鳴叫的持續時間計數器
        42. unsigned char ucDigShow8;//第8位數碼管要顯示的內容
        43. unsigned char ucDigShow7;//第7位數碼管要顯示的內容
        44. unsigned char ucDigShow6;//第6位數碼管要顯示的內容
        45. unsigned char ucDigShow5;//第5位數碼管要顯示的內容
        46. unsigned char ucDigShow4;//第4位數碼管要顯示的內容
        47. unsigned char ucDigShow3;//第3位數碼管要顯示的內容
        48. unsigned char ucDigShow2;//第2位數碼管要顯示的內容
        49. unsigned char ucDigShow1;//第1位數碼管要顯示的內容
        50. unsigned char ucDigDot8;//數碼管8的小數點是否顯示的標志
        51. unsigned char ucDigDot7;//數碼管7的小數點是否顯示的標志
        52. unsigned char ucDigDot6;//數碼管6的小數點是否顯示的標志
        53. unsigned char ucDigDot5;//數碼管5的小數點是否顯示的標志
        54. unsigned char ucDigDot4;//數碼管4的小數點是否顯示的標志
        55. unsigned char ucDigDot3;//數碼管3的小數點是否顯示的標志
        56. unsigned char ucDigDot2;//數碼管2的小數點是否顯示的標志
        57. unsigned char ucDigDot1;//數碼管1的小數點是否顯示的標志
        58. unsigned char ucDigShowTemp=0; //臨時中間變量
        59. unsigned char ucDisplayDriveStep=1;//動態掃描數碼管的步驟變量
        60. unsigned char ucWd1Update=1; //窗口1更新顯示標志
        61. unsigned char ucWd2Update=0; //窗口2更新顯示標志
        62. unsigned char ucWd3Update=0; //窗口3更新顯示標志
        63. unsigned char ucWd=1;//本程序的核心變量,窗口顯示變量。類似于一級菜單的變量。代表顯示不同的窗口。
        64. unsigned char ucInputPassword[4];//在第1個窗口下,顯示輸入的4個密碼
        65. unsigned char ucPasswordCnt=0; //記錄當前已經輸入到哪一位密碼了
        66. unsigned char ucKeyNumber=1;//在第2個窗口下,顯示當前被按下的按鍵
        67. unsigned intuiNoKeyPushTimer=const_no_key_push;//10秒內無按鍵按下的計時器
        68. unsigned intuiPasswordTimer=const_0_1s;//顯示0.5秒鐘全部密碼的計時器,讓窗口3停留顯示0.5秒鐘之后自動消失
        69. unsigned char ucTemp1=0;//中間過渡變量
        70. unsigned char ucTemp2=0;//中間過渡變量
        71. unsigned char ucTemp3=0;//中間過渡變量
        72. unsigned char ucTemp4=0;//中間過渡變量
        73. //根據原理圖得出的共陰數碼管字模表
        74. code unsigned char dig_table[]=
        75. {
        76. 0x3f,//0 序號0
        77. 0x06,//1 序號1
        78. 0x5b,//2 序號2
        79. 0x4f,//3 序號3
        80. 0x66,//4 序號4
        81. 0x6d,//5 序號5
        82. 0x7d,//6 序號6
        83. 0x07,//7 序號7
        84. 0x7f,//8 序號8
        85. 0x6f,//9 序號9
        86. 0x00,//無 序號10
        87. 0x40,//- 序號11
        88. 0x73,//P 序號12
        89. };
        90. void main()
        91. {
        92. initial_myself();
        93. delay_long(100);
        94. initial_peripheral();
        95. while(1)
        96. {
        97. key_service(); //按鍵服務的應用程序
        98. display_service(); //顯示的窗口菜單服務程序
        99. }
        100. }
        101. /* 注釋一:
        102. *鴻哥首次提出的"一二級菜單顯示理論":
        103. *凡是人機界面顯示,不管是數碼管還是液晶屏,都可以把顯示的內容分成不同的窗口來顯示,
        104. *每個顯示的窗口中又可以分成不同的局部顯示。其中窗口就是一級菜單,用ucWd變量表示。
        105. *局部就是二級菜單,用ucPart來表示。不同的窗口,會有不同的更新顯示變量ucWdXUpdate來對應,
        106. *表示整屏全部更新顯示。不同的局部,也會有不同的更新顯示變量ucWdXPartYUpdate來對應,表示局部更新顯示。
        107. */
        108. void display_service() //顯示的窗口菜單服務程序
        109. {
        110. switch(ucWd)//本程序的核心變量,窗口顯示變量。類似于一級菜單的變量。代表顯示不同的窗口。
        111. {
        112. case 1: //顯示輸入密碼的登錄框
        113. if(ucWd1Update==1)//窗口1要全部更新顯示
        114. {
        115. ucWd1Update=0;//及時清零標志,避免一直進來掃描
        116. ucDigShow8=10;//第8位數碼管顯示無
        117. ucDigShow7=10;//第7位數碼管顯示無
        118. ucDigShow6=10;//第6位數碼管顯示無
        119. ucDigShow5=10;//第5位數碼管顯示無
        120. ucDigShow4=ucInputPassword[0];//第4位數碼管顯示輸入的密碼
        121. ucDigShow3=ucInputPassword[1];//第3位數碼管顯示輸入的密碼
        122. ucDigShow2=ucInputPassword[2];//第2位數碼管顯示輸入的密碼
        123. ucDigShow1=ucInputPassword[3];//第1位數碼管顯示輸入的密碼
        124. }
        125. break;
        126. case 2://顯示被按下的鍵值
        127. if(ucWd2Update==1)//窗口2要全部更新顯示
        128. {
        129. ucWd2Update=0;//及時清零標志,避免一直進來掃描
        130. ucDigShow8=10;//第8位數碼管顯示無
        131. ucDigShow7=10;//第7位數碼管顯示無
        132. ucDigShow6=10;//第6位數碼管顯示無
        133. ucDigShow5=10;//第5位數碼管顯示無
        134. ucDigShow4=10;//第4位數碼管顯示無
        135. ucDigShow3=10;//第3位數碼管顯示無
        136. ucDigShow2=10;//第2位數碼管顯示無
        137. ucDigShow1=ucKeyNumber; //第1位數碼管顯示被按下的鍵值
        138. }
        139. break;
        140. case 3: //當輸入完4個密碼后,顯示1秒鐘的密碼登錄框,
        141. if(ucWd3Update==1)//窗口3要全部更新顯示
        142. {
        143. ucWd3Update=0;//及時清零標志,避免一直進來掃描
        144. ucDigShow8=10;//第8位數碼管顯示無
        145. ucDigShow7=10;//第7位數碼管顯示無
        146. ucDigShow6=10;//第6位數碼管顯示無
        147. ucDigShow5=10;//第5位數碼管顯示無
        148. ucDigShow4=ucInputPassword[0];//第4位數碼管顯示輸入的密碼
        149. ucDigShow3=ucInputPassword[1];//第3位數碼管顯示輸入的密碼
        150. ucDigShow2=ucInputPassword[2];//第2位數碼管顯示輸入的密碼
        151. ucDigShow1=ucInputPassword[3];//第1位數碼管顯示輸入的密碼
        152. }
        153. break;
        154. }
        155. }
        156. void key_scan()//按鍵掃描函數 放在定時中斷里
        157. {
        158. switch(ucKeyStep)
        159. {
        160. case 1: //按鍵掃描輸出第ucRowRecord列低電平
        161. if(ucRowRecord==1)//第一列輸出低電平
        162. {
        163. key_dr1=0;
        164. key_dr2=1;
        165. key_dr3=1;
        166. key_dr4=1;
        167. }
        168. else if(ucRowRecord==2)//第二列輸出低電平
        169. {
        170. key_dr1=1;
        171. key_dr2=0;
        172. key_dr3=1;
        173. key_dr4=1;
        174. }
        175. else if(ucRowRecord==3)//第三列輸出低電平
        176. {
        177. key_dr1=1;
        178. key_dr2=1;
        179. key_dr3=0;
        180. key_dr4=1;
        181. }
        182. else //第四列輸出低電平
        183. {
        184. key_dr1=1;
        185. key_dr2=1;
        186. key_dr3=1;
        187. key_dr4=0;
        188. }
        189. uiKeyTimeCnt=0;//延時計數器清零
        190. ucKeyStep++; //切換到下一個運行步驟
        191. break;
        192. case 2: //此處的小延時用來等待剛才列輸出信號穩定,再判斷輸入信號。不是去抖動延時。
        193. uiKeyTimeCnt++;
        194. if(uiKeyTimeCnt>1)
        195. {
        196. uiKeyTimeCnt=0;
        197. ucKeyStep++; //切換到下一個運行步驟
        198. }
        199. break;
        200. case 3:
        201. if(key_sr1==1&&key_sr2==1&&key_sr3==1&&key_sr4==1)
        202. {
        203. ucKeyStep=1;//如果沒有按鍵按下,返回到第一個運行步驟重新開始掃描
        204. ucKeyLock=0;//按鍵自鎖標志清零
        205. uiKeyTimeCnt=0; //按鍵去抖動延時計數器清零,此行非常巧妙
        206. ucRowRecord++;//輸出下一列
        207. if(ucRowRecord>4)
        208. {
        209. ucRowRecord=1; //依次輸出完四列之后,繼續從第一列開始輸出低電平
        210. }
        211. }
        212. else if(ucKeyLock==0)//有按鍵按下,且是第一次觸發
        213. {
        214. if(key_sr1==0&&key_sr2==1&&key_sr3==1&&key_sr4==1)
        215. {
        216. uiKeyTimeCnt++;//去抖動延時計數器
        217. if(uiKeyTimeCnt>const_key_time)
        218. {
        219. uiKeyTimeCnt=0;
        220. ucKeyLock=1;//自鎖按鍵置位,避免一直觸發,只有松開按鍵,此標志位才會被清零
        221. if(ucRowRecord==1)//第一列輸出低電平
        222. {
        223. ucKeySec=1;//觸發1號鍵 對應朱兆祺學習板的S1鍵
        224. }
        225. else if(ucRowRecord==2)//第二列輸出低電平
        226. {
        227. ucKeySec=2;//觸發2號鍵 對應朱兆祺學習板的S2鍵
        228. }
        229. else if(ucRowRecord==3)//第三列輸出低電平
        230. {
        231. ucKeySec=3;//觸發3號鍵 對應朱兆祺學習板的S3鍵
        232. }
        233. else //第四列輸出低電平
        234. {
        235. ucKeySec=4;//觸發4號鍵 對應朱兆祺學習板的S4鍵
        236. }
        237. }
        238. }
        239. else if(key_sr1==1&&key_sr2==0&&key_sr3==1&&key_sr4==1)
        240. {
        241. uiKeyTimeCnt++;//去抖動延時計數器
        242. if(uiKeyTimeCnt>const_key_time)
        243. {
        244. uiKeyTimeCnt=0;
        245. ucKeyLock=1;//自鎖按鍵置位,避免一直觸發,只有松開按鍵,此標志位才會被清零
        246. if(ucRowRecord==1)//第一列輸出低電平
        247. {
        248. ucKeySec=5;//觸發5號鍵 對應朱兆祺學習板的S5鍵
        249. }
        250. else if(ucRowRecord==2)//第二列輸出低電平
        251. {
        252. ucKeySec=6;//觸發6號鍵 對應朱兆祺學習板的S6鍵
        253. }
        254. else if(ucRowRecord==3)//第三列輸出低電平
        255. {
        256. ucKeySec=7;//觸發7號鍵 對應朱兆祺學習板的S7鍵
        257. }
        258. else //第四列輸出低電平
        259. {
        260. ucKeySec=8;//觸發8號鍵 對應朱兆祺學習板的S8鍵
        261. }
        262. }
        263. }
        264. else if(key_sr1==1&&key_sr2==1&&key_sr3==0&&key_sr4==1)
        265. {
        266. uiKeyTimeCnt++;//去抖動延時計數器
        267. if(uiKeyTimeCnt>const_key_time)
        268. {
        269. uiKeyTimeCnt=0;
        270. ucKeyLock=1;//自鎖按鍵置位,避免一直觸發,只有松開按鍵,此標志位才會被清零
        271. if(ucRowRecord==1)//第一列輸出低電平
        272. {
        273. ucKeySec=9;//觸發9號鍵 對應朱兆祺學習板的S9鍵
        274. }
        275. else if(ucRowRecord==2)//第二列輸出低電平
        276. {
        277. ucKeySec=10;//觸發10號鍵 對應朱兆祺學習板的S10鍵
        278. }
        279. else if(ucRowRecord==3)//第三列輸出低電平
        280. {
        281. ucKeySec=11;//觸發11號鍵 對應朱兆祺學習板的S11鍵
        282. }
        283. else //第四列輸出低電平
        284. {
        285. ucKeySec=12;//觸發12號鍵 對應朱兆祺學習板的S12鍵
        286. }
        287. }
        288. }
        289. else if(key_sr1==1&&key_sr2==1&&key_sr3==1&&key_sr4==0)
        290. {
        291. uiKeyTimeCnt++;//去抖動延時計數器
        292. if(uiKeyTimeCnt>const_key_time)
        293. {
        294. uiKeyTimeCnt=0;
        295. ucKeyLock=1;//自鎖按鍵置位,避免一直觸發,只有松開按鍵,此標志位才會被清零
        296. if(ucRowRecord==1)//第一列輸出低電平
        297. {
        298. ucKeySec=13;//觸發13號鍵 對應朱兆祺學習板的S13鍵
        299. }
        300. else if(ucRowRecord==2)//第二列輸出低電平
        301. {
        302. ucKeySec=14;//觸發14號鍵 對應朱兆祺學習板的S14鍵
        303. }
        304. else if(ucRowRecord==3)//第三列輸出低電平
        305. {
        306. ucKeySec=15;//觸發15號鍵 對應朱兆祺學習板的S15鍵
        307. }
        308. else //第四列輸出低電平
        309. {
        310. ucKeySec=16;//觸發16號鍵 對應朱兆祺學習板的S16鍵
        311. }
        312. }
        313. }
        314. }
        315. break;
        316. }
        317. }
        318. void key_service() //第三區 按鍵服務的應用程序
        319. {
        320. switch(ucKeySec) //按鍵服務狀態切換
        321. {
        322. case 1:// 1號鍵 對應朱兆祺學習板的S1鍵
        323. number_key_input(1);//由于數字按鍵的代碼相似度高,因此把具體代碼封裝在這個函數里
        324. uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。
        325. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發
        326. break;
        327. case 2:// 2號鍵 對應朱兆祺學習板的S2鍵
        328. number_key_input(2);//由于數字按鍵的代碼相似度高,因此把具體代碼封裝在這個函數里
        329. uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。
        330. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發
        331. break;
        332. case 3:// 3號鍵 對應朱兆祺學習板的S3鍵
        333. number_key_input(3);//由于數字按鍵的代碼相似度高,因此把具體代碼封裝在這個函數里
        334. uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。
        335. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發
        336. break;
        337. case 4:// 4號鍵 對應朱兆祺學習板的S4鍵
        338. number_key_input(4);//由于數字按鍵的代碼相似度高,因此把具體代碼封裝在這個函數里
        339. uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。
        340. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發
        341. break;
        342. case 5:// 5號鍵 對應朱兆祺學習板的S5鍵
        343. number_key_input(5);//由于數字按鍵的代碼相似度高,因此把具體代碼封裝在這個函數里
        344. uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。
        345. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發
        346. break;
        347. case 6:// 6號鍵 對應朱兆祺學習板的S6鍵
        348. number_key_input(6);//由于數字按鍵的代碼相似度高,因此把具體代碼封裝在這個函數里
        349. uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。
        350. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發
        351. break;
        352. case 7:// 7號鍵 對應朱兆祺學習板的S7鍵
        353. number_key_input(7);//由于數字按鍵的代碼相似度高,因此把具體代碼封裝在這個函數里
        354. uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。
        355. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發
        356. break;
        357. case 8:// 8號鍵 對應朱兆祺學習板的S8鍵
        358. number_key_input(8);//由于數字按鍵的代碼相似度高,因此把具體代碼封裝在這個函數里
        359. uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。
        360. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發
        361. break;
        362. case 9:// 9號鍵 對應朱兆祺學習板的S9鍵
        363. number_key_input(9);//由于數字按鍵的代碼相似度高,因此把具體代碼封裝在這個函數里
        364. uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。
        365. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發
        366. break;
        367. case 10:// 把這個按鍵專門用來輸入數字0 對應朱兆祺學習板的S10鍵
        368. number_key_input(0);//由于數字按鍵的代碼相似度高,因此把具體代碼封裝在這個函數里
        369. uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。
        370. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發
        371. break;
        372. case 11:// 11號鍵 對應朱兆祺學習板的S11鍵
        373. uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。
        374. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發
        375. break;
        376. case 12:// 12號鍵 對應朱兆祺學習板的S12鍵
        377. uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。
        378. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發
        379. break;
        380. case 13:// 13號鍵 對應朱兆祺學習板的S13鍵
        381. uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。
        382. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發
        383. break;
        384. case 14:// 14號鍵 對應朱兆祺學習板的S14鍵
        385. uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。
        386. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發
        387. break;
        388. case 15:// 15號鍵 對應朱兆祺學習板的S15鍵
        389. uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。
        390. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發
        391. break;
        392. case 16:// 16號鍵 對應朱兆祺學習板的S16鍵
        393. uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。
        394. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發
        395. break;
        396. }
        397. }
        398. void number_key_input(unsigned char ucWhichKey)//由于數字按鍵的代碼相似度高,因此封裝在這個函數里
        399. {
        400. switch(ucWd)
        401. {
        402. case 1: //在顯示密碼登錄框的窗口下
        403. ucInputPassword[ucPasswordCnt]=ucWhichKey; //輸入的密碼值顯示
        404. ucPasswordCnt++;
        405. if(ucPasswordCnt>=4)
        406. {
        407. ucPasswordCnt=0;
        408. ucWd=3;//切換到第3個的窗口,停留顯示1秒鐘全部密碼
        409. ucWd3Update=1;//更新顯示窗口3
        410. uiPasswordTimer=const_0_1s;//顯示0.5秒鐘全部密碼的計時器,讓窗口3停留顯示0.5秒鐘之后自動消失
        411. }
        412. ucWd1Update=1; //更新顯示窗口1
        413. uiNoKeyPushTimer=const_no_key_push;//10秒內無按鍵按下的計時器賦新值
        414. break;
        415. case 2: //在顯示按鍵值的窗口下
        416. ucKeyNumber=ucWhichKey; //輸入的按鍵數值顯示
        417. ucWd2Update=1;//更新顯示窗口2
        418. uiNoKeyPushTimer=const_no_key_push;//10秒內無按鍵按下的計時器賦新值
        419. break;
        420. }
        421. }
        422. void display_drive()
        423. {
        424. //以下程序,如果加一些數組和移位的元素,還可以壓縮容量。但是鴻哥追求的不是容量,而是清晰的講解思路
        425. switch(ucDisplayDriveStep)
        426. {
        427. case 1://顯示第1位
        428. ucDigShowTemp=dig_table[ucDigShow1];
        429. if(ucDigDot1==1)
        430. {
        431. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數點
        432. }
        433. dig_hc595_drive(ucDigShowTemp,0xfe);
        434. break;
        435. case 2://顯示第2位
        436. ucDigShowTemp=dig_table[ucDigShow2];
        437. if(ucDigDot2==1)
        438. {
        439. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數點
        440. }
        441. dig_hc595_drive(ucDigShowTemp,0xfd);
        442. break;
        443. case 3://顯示第3位
        444. ucDigShowTemp=dig_table[ucDigShow3];
        445. if(ucDigDot3==1)
        446. {
        447. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數點
        448. }
        449. dig_hc595_drive(ucDigShowTemp,0xfb);
        450. break;
        451. case 4://顯示第4位
        452. ucDigShowTemp=dig_table[ucDigShow4];
        453. if(ucDigDot4==1)
        454. {
        455. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數點
        456. }
        457. dig_hc595_drive(ucDigShowTemp,0xf7);
        458. break;
        459. case 5://顯示第5位
        460. ucDigShowTemp=dig_table[ucDigShow5];
        461. if(ucDigDot5==1)
        462. {
        463. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數點
        464. }
        465. dig_hc595_drive(ucDigShowTemp,0xef);
        466. break;
        467. case 6://顯示第6位
        468. ucDigShowTemp=dig_table[ucDigShow6];
        469. if(ucDigDot6==1)
        470. {
        471. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數點
        472. }
        473. dig_hc595_drive(ucDigShowTemp,0xdf);
        474. break;
        475. case 7://顯示第7位
        476. ucDigShowTemp=dig_table[ucDigShow7];
        477. if(ucDigDot7==1)
        478. {
        479. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數點
        480. }
        481. dig_hc595_drive(ucDigShowTemp,0xbf);
        482. break;
        483. case 8://顯示第8位
        484. ucDigShowTemp=dig_table[ucDigShow8];
        485. if(ucDigDot8==1)
        486. {
        487. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數點
        488. }
        489. dig_hc595_drive(ucDigShowTemp,0x7f);
        490. break;
        491. }
        492. ucDisplayDriveStep++;
        493. if(ucDisplayDriveStep>8)//掃描完8個數碼管后,重新從第一個開始掃描
        494. {
        495. ucDisplayDriveStep=1;
        496. }
        497. }
        498. //數碼管的74HC595驅動函數
        499. void dig_hc595_drive(unsigned char ucDigStatusTemp16_09,unsigned char ucDigStatusTemp08_01)
        500. {
        501. unsigned char i;
        502. unsigned char ucTempData;
        503. dig_hc595_sh_dr=0;
        504. dig_hc595_st_dr=0;
        505. ucTempData=ucDigStatusTemp16_09;//先送高8位
        506. for(i=0;i<8;i++)
        507. {
        508. if(ucTempData>=0x80)dig_hc595_ds_dr=1;
        509. else dig_hc595_ds_dr=0;
        510. dig_hc595_sh_dr=0; //SH引腳的上升沿把數據送入寄存器
        511. delay_short(1);
        512. dig_hc595_sh_dr=1;
        513. delay_short(1);
        514. ucTempData=ucTempData<<1;
        515. }
        516. ucTempData=ucDigStatusTemp08_01;//再先送低8位
        517. for(i=0;i<8;i++)
        518. {
        519. if(ucTempData>=0x80)dig_hc595_ds_dr=1;
        520. else dig_hc595_ds_dr=0;
        521. dig_hc595_sh_dr=0; //SH引腳的上升沿把數據送入寄存器
        522. delay_short(1);
        523. dig_hc595_sh_dr=1;
        524. delay_short(1);
        525. ucTempData=ucTempData<<1;
        526. }
        527. dig_hc595_st_dr=0;//ST引腳把兩個寄存器的數據更新輸出到74HC595的輸出引腳上并且鎖存起來
        528. delay_short(1);
        529. dig_hc595_st_dr=1;
        530. delay_short(1);
        531. dig_hc595_sh_dr=0; //拉低,抗干擾就增強
        532. dig_hc595_st_dr=0;
        533. dig_hc595_ds_dr=0;
        534. }
        535. //LED燈的74HC595驅動函數
        536. void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01)
        537. {
        538. unsigned char i;
        539. unsigned char ucTempData;
        540. hc595_sh_dr=0;
        541. hc595_st_dr=0;
        542. ucTempData=ucLedStatusTemp16_09;//先送高8位
        543. for(i=0;i<8;i++)
        544. {
        545. if(ucTempData>=0x80)hc595_ds_dr=1;
        546. else hc595_ds_dr=0;
        547. hc595_sh_dr=0; //SH引腳的上升沿把數據送入寄存器
        548. delay_short(1);
        549. hc595_sh_dr=1;
        550. delay_short(1);
        551. ucTempData=ucTempData<<1;
        552. }
        553. ucTempData=ucLedStatusTemp08_01;//再先送低8位
        554. for(i=0;i<8;i++)
        555. {
        556. if(ucTempData>=0x80)hc595_ds_dr=1;
        557. else hc595_ds_dr=0;
        558. hc595_sh_dr=0; //SH引腳的上升沿把數據送入寄存器
        559. delay_short(1);
        560. hc595_sh_dr=1;
        561. delay_short(1);
        562. ucTempData=ucTempData<<1;
        563. }
        564. hc595_st_dr=0;//ST引腳把兩個寄存器的數據更新輸出到74HC595的輸出引腳上并且鎖存起來
        565. delay_short(1);
        566. hc595_st_dr=1;
        567. delay_short(1);
        568. hc595_sh_dr=0; //拉低,抗干擾就增強
        569. hc595_st_dr=0;
        570. hc595_ds_dr=0;
        571. }
        572. void T0_time() interrupt 1
        573. {
        574. unsigned int i;
        575. TF0=0;//清除中斷標志
        576. TR0=0; //關中斷
        577. if(ucWd==3)//在窗口3下
        578. {
        579. if(uiPasswordTimer>0)
        580. {
        581. uiPasswordTimer--;
        582. }
        583. if(uiPasswordTimer==0)
        584. {
        585. if(ucInputPassword[0]==9&&ucInputPassword[1]==9&&ucInputPassword[2]==2&&ucInputPassword[3]==2)
        586. { //如果密碼等于9922,則正確
        587. ucWd=2;//切換到第2個顯示按鍵的窗口
        588. ucWd2Update=1;//更新顯示窗口2
        589. }
        590. else //如果密碼不正確,則繼續顯示----
        591. {
        592. for(i=0;i<4;i++)
        593. {
        594. ucInputPassword[i]=11;//開機默認密碼全部顯示"----"
        595. }
        596. ucWd=1;
        597. ucWd1Update=1; //更新顯示窗口1
        598. }
        599. }
        600. }
        601. if(ucWd==2)//在窗口2下
        602. {
        603. if(uiNoKeyPushTimer>0)
        604. {
        605. uiNoKeyPushTimer--;
        606. }
        607. if(uiNoKeyPushTimer==0)//如果10秒內無按鍵按下,則自動切換到顯示密碼登錄框的界面
        608. {
        609. for(i=0;i<4;i++)
        610. {
        611. ucInputPassword[i]=11;//開機默認密碼全部顯示"----"
        612. }
        613. ucWd=1;
        614. ucWd1Update=1; //更新顯示窗口1
        615. }
        616. }
        617. key_scan(); //按鍵掃描函數
        618. if(uiVoiceCnt!=0)
        619. {
        620. uiVoiceCnt--; //每次進入定時中斷都自減1,直到等于零為止。才停止鳴叫
        621. beep_dr=0;//蜂鳴器是PNP三極管控制,低電平就開始鳴叫。
        622. // beep_dr=1;//蜂鳴器是PNP三極管控制,低電平就開始鳴叫。
        623. }
        624. else
        625. {
        626. ; //此處多加一個空指令,想維持跟if括號語句的數量對稱,都是兩條指令。不加也可以。
        627. beep_dr=1;//蜂鳴器是PNP三極管控制,高電平就停止鳴叫。
        628. // beep_dr=0;//蜂鳴器是PNP三極管控制,高電平就停止鳴叫。
        629. }
        630. display_drive();//數碼管字模的驅動函數
        631. TH0=0xfe; //重裝初始值(65535-500)=65035=0xfe0b
        632. TL0=0x0b;
        633. TR0=1;//開中斷
        634. }
        635. void delay_short(unsigned int uiDelayShort)
        636. {
        637. unsigned int i;
        638. for(i=0;i
        639. {
        640. ; //一個分號相當于執行一條空語句
        641. }
        642. }
        643. void delay_long(unsigned int uiDelayLong)
        644. {
        645. unsigned int i;
        646. unsigned int j;
        647. for(i=0;i
        648. {
        649. for(j=0;j<500;j++)//內嵌循環的空指令數量
        650. {
        651. ; //一個分號相當于執行一條空語句
        652. }
        653. }
        654. }
        655. void initial_myself()//第一區 初始化單片機
        656. {
        657. led_dr=0;//關閉獨立LED燈
        658. beep_dr=1; //用PNP三極管控制蜂鳴器,輸出高電平時不叫。
        659. hc595_drive(0x00,0x00);//關閉所有經過另外兩個74HC595驅動的LED燈
        660. TMOD=0x01;//設置定時器0為工作方式1
        661. TH0=0xfe; //重裝初始值(65535-500)=65035=0xfe0b
        662. TL0=0x0b;
        663. }
        664. void initial_peripheral() //第二區 初始化外圍
        665. {
        666. unsigned int i; //個人的變量命名習慣,i,j,k等單個字母的變量名只用在for循環里
        667. for(i=0;i<4;i++)
        668. {
        669. ucInputPassword[i]=11;//開機默認密碼全部顯示"----"
        670. }
        671. ucDigDot8=0; //小數點全部不顯示
        672. ucDigDot7=0;
        673. ucDigDot6=0;
        674. ucDigDot5=0;
        675. ucDigDot4=0;
        676. ucDigDot3=0;
        677. ucDigDot2=0;
        678. ucDigDot1=0;
        679. EA=1; //開總中斷
        680. ET0=1; //允許定時中斷
        681. TR0=1; //啟動定時中斷
        682. }
        復制代碼


        總結陳詞:
        這節講了iphone4S開機密碼鎖的程序。2014年春節的時候,一幫朋友舉行小規模的象棋比賽,有一些朋友下棋的速度實在是太慢了,為了限制比賽時間,我專門用朱兆祺的51學習板做了一個棋類比賽專用計時器給他們用,這個程序該怎么編寫?欲知詳情,請聽下回分解-----帶數碼管顯示的象棋比賽專用計時器。


        關鍵詞: 數碼管開機密碼

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 肇州县| 富宁县| 鸡泽县| 巴南区| 衡阳县| 孙吴县| 耿马| 介休市| 西林县| 玉屏| 灌云县| 丹寨县| 黄龙县| 鲜城| 大埔区| 商都县| 玉龙| 拜城县| 大荔县| 雷山县| 桓台县| 和平县| 德安县| 井陉县| 房山区| 遂溪县| 崇礼县| 富源县| 梨树县| 阿克陶县| 怀集县| 探索| 壤塘县| 海城市| 获嘉县| 和政县| 巨鹿县| 武强县| 栖霞市| 开阳县| 琼中|