新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 第34節(jié):在數(shù)碼管中實(shí)現(xiàn)iphone4S開機(jī)密碼鎖的程序

第34節(jié):在數(shù)碼管中實(shí)現(xiàn)iphone4S開機(jī)密碼鎖的程序

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

具體內(nèi)容,請(qǐng)看源代碼講解。

(1)硬件平臺(tái):基于朱兆祺51單片機(jī)學(xué)習(xí)板。數(shù)字1鍵對(duì)應(yīng)S1鍵,數(shù)字2鍵對(duì)應(yīng)S2鍵,數(shù)字3鍵對(duì)應(yīng)S3鍵…. 數(shù)字9鍵對(duì)應(yīng)S9鍵, 數(shù)字0鍵對(duì)應(yīng)S10鍵。其他的按鍵不用。

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

(3)源代碼講解如下:
  1. #include "REG52.H"
  2. #define const_no_key_push 4400 //大概10秒內(nèi)無按鍵按下的時(shí)間
  3. #define const_0_1s220 //大概0.5秒的時(shí)間
  4. #define const_voice_short40 //蜂鳴器短叫的持續(xù)時(shí)間
  5. #define const_key_time20 //按鍵去抖動(dòng)延時(shí)的時(shí)間
  6. void initial_myself();
  7. void initial_peripheral();
  8. void delay_short(unsigned int uiDelayShort);
  9. void delay_long(unsigned int uiDelaylong);
  10. //驅(qū)動(dòng)數(shù)碼管的74HC595
  11. void dig_hc595_drive(unsigned char ucDigStatusTemp16_09,unsigned char ucDigStatusTemp08_01);
  12. void display_drive(); //顯示數(shù)碼管字模的驅(qū)動(dòng)函數(shù)
  13. void display_service(); //顯示的窗口菜單服務(wù)程序
  14. //驅(qū)動(dòng)LED的74HC595
  15. void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01);
  16. void T0_time();//定時(shí)中斷函數(shù)
  17. void number_key_input(unsigned char ucWhichKey);//由于數(shù)字按鍵的代碼相似度高,因此封裝在這個(gè)函數(shù)里
  18. void key_service(); //按鍵服務(wù)的應(yīng)用程序
  19. void key_scan();//按鍵掃描函數(shù) 放在定時(shí)中斷里
  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; //蜂鳴器的驅(qū)動(dòng)IO口
  29. sbit led_dr=P3^5;//作為中途暫停指示燈 亮的時(shí)候表示中途暫停
  30. sbit dig_hc595_sh_dr=P2^0; //數(shù)碼管的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; //按鍵去抖動(dòng)延時(shí)計(jì)數(shù)器
  38. unsigned char ucKeyLock=0; //按鍵觸發(fā)后自鎖的變量標(biāo)志
  39. unsigned char ucRowRecord=1; //記錄當(dāng)前掃描到第幾列了
  40. unsigned char ucKeySec=0; //被觸發(fā)的按鍵編號(hào)
  41. unsigned intuiVoiceCnt=0;//蜂鳴器鳴叫的持續(xù)時(shí)間計(jì)數(shù)器
  42. unsigned char ucDigShow8;//第8位數(shù)碼管要顯示的內(nèi)容
  43. unsigned char ucDigShow7;//第7位數(shù)碼管要顯示的內(nèi)容
  44. unsigned char ucDigShow6;//第6位數(shù)碼管要顯示的內(nèi)容
  45. unsigned char ucDigShow5;//第5位數(shù)碼管要顯示的內(nèi)容
  46. unsigned char ucDigShow4;//第4位數(shù)碼管要顯示的內(nèi)容
  47. unsigned char ucDigShow3;//第3位數(shù)碼管要顯示的內(nèi)容
  48. unsigned char ucDigShow2;//第2位數(shù)碼管要顯示的內(nèi)容
  49. unsigned char ucDigShow1;//第1位數(shù)碼管要顯示的內(nèi)容
  50. unsigned char ucDigDot8;//數(shù)碼管8的小數(shù)點(diǎn)是否顯示的標(biāo)志
  51. unsigned char ucDigDot7;//數(shù)碼管7的小數(shù)點(diǎn)是否顯示的標(biāo)志
  52. unsigned char ucDigDot6;//數(shù)碼管6的小數(shù)點(diǎn)是否顯示的標(biāo)志
  53. unsigned char ucDigDot5;//數(shù)碼管5的小數(shù)點(diǎn)是否顯示的標(biāo)志
  54. unsigned char ucDigDot4;//數(shù)碼管4的小數(shù)點(diǎn)是否顯示的標(biāo)志
  55. unsigned char ucDigDot3;//數(shù)碼管3的小數(shù)點(diǎn)是否顯示的標(biāo)志
  56. unsigned char ucDigDot2;//數(shù)碼管2的小數(shù)點(diǎn)是否顯示的標(biāo)志
  57. unsigned char ucDigDot1;//數(shù)碼管1的小數(shù)點(diǎn)是否顯示的標(biāo)志
  58. unsigned char ucDigShowTemp=0; //臨時(shí)中間變量
  59. unsigned char ucDisplayDriveStep=1;//動(dòng)態(tài)掃描數(shù)碼管的步驟變量
  60. unsigned char ucWd1Update=1; //窗口1更新顯示標(biāo)志
  61. unsigned char ucWd2Update=0; //窗口2更新顯示標(biāo)志
  62. unsigned char ucWd3Update=0; //窗口3更新顯示標(biāo)志
  63. unsigned char ucWd=1;//本程序的核心變量,窗口顯示變量。類似于一級(jí)菜單的變量。代表顯示不同的窗口。
  64. unsigned char ucInputPassword[4];//在第1個(gè)窗口下,顯示輸入的4個(gè)密碼
  65. unsigned char ucPasswordCnt=0; //記錄當(dāng)前已經(jīng)輸入到哪一位密碼了
  66. unsigned char ucKeyNumber=1;//在第2個(gè)窗口下,顯示當(dāng)前被按下的按鍵
  67. unsigned intuiNoKeyPushTimer=const_no_key_push;//10秒內(nèi)無按鍵按下的計(jì)時(shí)器
  68. unsigned intuiPasswordTimer=const_0_1s;//顯示0.5秒鐘全部密碼的計(jì)時(shí)器,讓窗口3停留顯示0.5秒鐘之后自動(dòng)消失
  69. unsigned char ucTemp1=0;//中間過渡變量
  70. unsigned char ucTemp2=0;//中間過渡變量
  71. unsigned char ucTemp3=0;//中間過渡變量
  72. unsigned char ucTemp4=0;//中間過渡變量
  73. //根據(jù)原理圖得出的共陰數(shù)碼管字模表
  74. code unsigned char dig_table[]=
  75. {
  76. 0x3f,//0 序號(hào)0
  77. 0x06,//1 序號(hào)1
  78. 0x5b,//2 序號(hào)2
  79. 0x4f,//3 序號(hào)3
  80. 0x66,//4 序號(hào)4
  81. 0x6d,//5 序號(hào)5
  82. 0x7d,//6 序號(hào)6
  83. 0x07,//7 序號(hào)7
  84. 0x7f,//8 序號(hào)8
  85. 0x6f,//9 序號(hào)9
  86. 0x00,//無 序號(hào)10
  87. 0x40,//- 序號(hào)11
  88. 0x73,//P 序號(hào)12
  89. };
  90. void main()
  91. {
  92. initial_myself();
  93. delay_long(100);
  94. initial_peripheral();
  95. while(1)
  96. {
  97. key_service(); //按鍵服務(wù)的應(yīng)用程序
  98. display_service(); //顯示的窗口菜單服務(wù)程序
  99. }
  100. }
  101. /* 注釋一:
  102. *鴻哥首次提出的"一二級(jí)菜單顯示理論":
  103. *凡是人機(jī)界面顯示,不管是數(shù)碼管還是液晶屏,都可以把顯示的內(nèi)容分成不同的窗口來顯示,
  104. *每個(gè)顯示的窗口中又可以分成不同的局部顯示。其中窗口就是一級(jí)菜單,用ucWd變量表示。
  105. *局部就是二級(jí)菜單,用ucPart來表示。不同的窗口,會(huì)有不同的更新顯示變量ucWdXUpdate來對(duì)應(yīng),
  106. *表示整屏全部更新顯示。不同的局部,也會(huì)有不同的更新顯示變量ucWdXPartYUpdate來對(duì)應(yīng),表示局部更新顯示。
  107. */
  108. void display_service() //顯示的窗口菜單服務(wù)程序
  109. {
  110. switch(ucWd)//本程序的核心變量,窗口顯示變量。類似于一級(jí)菜單的變量。代表顯示不同的窗口。
  111. {
  112. case 1: //顯示輸入密碼的登錄框
  113. if(ucWd1Update==1)//窗口1要全部更新顯示
  114. {
  115. ucWd1Update=0;//及時(shí)清零標(biāo)志,避免一直進(jìn)來掃描
  116. ucDigShow8=10;//第8位數(shù)碼管顯示無
  117. ucDigShow7=10;//第7位數(shù)碼管顯示無
  118. ucDigShow6=10;//第6位數(shù)碼管顯示無
  119. ucDigShow5=10;//第5位數(shù)碼管顯示無
  120. ucDigShow4=ucInputPassword[0];//第4位數(shù)碼管顯示輸入的密碼
  121. ucDigShow3=ucInputPassword[1];//第3位數(shù)碼管顯示輸入的密碼
  122. ucDigShow2=ucInputPassword[2];//第2位數(shù)碼管顯示輸入的密碼
  123. ucDigShow1=ucInputPassword[3];//第1位數(shù)碼管顯示輸入的密碼
  124. }
  125. break;
  126. case 2://顯示被按下的鍵值
  127. if(ucWd2Update==1)//窗口2要全部更新顯示
  128. {
  129. ucWd2Update=0;//及時(shí)清零標(biāo)志,避免一直進(jìn)來掃描
  130. ucDigShow8=10;//第8位數(shù)碼管顯示無
  131. ucDigShow7=10;//第7位數(shù)碼管顯示無
  132. ucDigShow6=10;//第6位數(shù)碼管顯示無
  133. ucDigShow5=10;//第5位數(shù)碼管顯示無
  134. ucDigShow4=10;//第4位數(shù)碼管顯示無
  135. ucDigShow3=10;//第3位數(shù)碼管顯示無
  136. ucDigShow2=10;//第2位數(shù)碼管顯示無
  137. ucDigShow1=ucKeyNumber; //第1位數(shù)碼管顯示被按下的鍵值
  138. }
  139. break;
  140. case 3: //當(dāng)輸入完4個(gè)密碼后,顯示1秒鐘的密碼登錄框,
  141. if(ucWd3Update==1)//窗口3要全部更新顯示
  142. {
  143. ucWd3Update=0;//及時(shí)清零標(biāo)志,避免一直進(jìn)來掃描
  144. ucDigShow8=10;//第8位數(shù)碼管顯示無
  145. ucDigShow7=10;//第7位數(shù)碼管顯示無
  146. ucDigShow6=10;//第6位數(shù)碼管顯示無
  147. ucDigShow5=10;//第5位數(shù)碼管顯示無
  148. ucDigShow4=ucInputPassword[0];//第4位數(shù)碼管顯示輸入的密碼
  149. ucDigShow3=ucInputPassword[1];//第3位數(shù)碼管顯示輸入的密碼
  150. ucDigShow2=ucInputPassword[2];//第2位數(shù)碼管顯示輸入的密碼
  151. ucDigShow1=ucInputPassword[3];//第1位數(shù)碼管顯示輸入的密碼
  152. }
  153. break;
  154. }
  155. }
  156. void key_scan()//按鍵掃描函數(shù) 放在定時(shí)中斷里
  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;//延時(shí)計(jì)數(shù)器清零
  190. ucKeyStep++; //切換到下一個(gè)運(yùn)行步驟
  191. break;
  192. case 2: //此處的小延時(shí)用來等待剛才列輸出信號(hào)穩(wěn)定,再判斷輸入信號(hào)。不是去抖動(dòng)延時(shí)。
  193. uiKeyTimeCnt++;
  194. if(uiKeyTimeCnt>1)
  195. {
  196. uiKeyTimeCnt=0;
  197. ucKeyStep++; //切換到下一個(gè)運(yùn)行步驟
  198. }
  199. break;
  200. case 3:
  201. if(key_sr1==1&&key_sr2==1&&key_sr3==1&&key_sr4==1)
  202. {
  203. ucKeyStep=1;//如果沒有按鍵按下,返回到第一個(gè)運(yùn)行步驟重新開始掃描
  204. ucKeyLock=0;//按鍵自鎖標(biāo)志清零
  205. uiKeyTimeCnt=0; //按鍵去抖動(dòng)延時(shí)計(jì)數(shù)器清零,此行非常巧妙
  206. ucRowRecord++;//輸出下一列
  207. if(ucRowRecord>4)
  208. {
  209. ucRowRecord=1; //依次輸出完四列之后,繼續(xù)從第一列開始輸出低電平
  210. }
  211. }
  212. else if(ucKeyLock==0)//有按鍵按下,且是第一次觸發(fā)
  213. {
  214. if(key_sr1==0&&key_sr2==1&&key_sr3==1&&key_sr4==1)
  215. {
  216. uiKeyTimeCnt++;//去抖動(dòng)延時(shí)計(jì)數(shù)器
  217. if(uiKeyTimeCnt>const_key_time)
  218. {
  219. uiKeyTimeCnt=0;
  220. ucKeyLock=1;//自鎖按鍵置位,避免一直觸發(fā),只有松開按鍵,此標(biāo)志位才會(huì)被清零
  221. if(ucRowRecord==1)//第一列輸出低電平
  222. {
  223. ucKeySec=1;//觸發(fā)1號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S1鍵
  224. }
  225. else if(ucRowRecord==2)//第二列輸出低電平
  226. {
  227. ucKeySec=2;//觸發(fā)2號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S2鍵
  228. }
  229. else if(ucRowRecord==3)//第三列輸出低電平
  230. {
  231. ucKeySec=3;//觸發(fā)3號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S3鍵
  232. }
  233. else //第四列輸出低電平
  234. {
  235. ucKeySec=4;//觸發(fā)4號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S4鍵
  236. }
  237. }
  238. }
  239. else if(key_sr1==1&&key_sr2==0&&key_sr3==1&&key_sr4==1)
  240. {
  241. uiKeyTimeCnt++;//去抖動(dòng)延時(shí)計(jì)數(shù)器
  242. if(uiKeyTimeCnt>const_key_time)
  243. {
  244. uiKeyTimeCnt=0;
  245. ucKeyLock=1;//自鎖按鍵置位,避免一直觸發(fā),只有松開按鍵,此標(biāo)志位才會(huì)被清零
  246. if(ucRowRecord==1)//第一列輸出低電平
  247. {
  248. ucKeySec=5;//觸發(fā)5號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S5鍵
  249. }
  250. else if(ucRowRecord==2)//第二列輸出低電平
  251. {
  252. ucKeySec=6;//觸發(fā)6號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S6鍵
  253. }
  254. else if(ucRowRecord==3)//第三列輸出低電平
  255. {
  256. ucKeySec=7;//觸發(fā)7號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S7鍵
  257. }
  258. else //第四列輸出低電平
  259. {
  260. ucKeySec=8;//觸發(fā)8號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S8鍵
  261. }
  262. }
  263. }
  264. else if(key_sr1==1&&key_sr2==1&&key_sr3==0&&key_sr4==1)
  265. {
  266. uiKeyTimeCnt++;//去抖動(dòng)延時(shí)計(jì)數(shù)器
  267. if(uiKeyTimeCnt>const_key_time)
  268. {
  269. uiKeyTimeCnt=0;
  270. ucKeyLock=1;//自鎖按鍵置位,避免一直觸發(fā),只有松開按鍵,此標(biāo)志位才會(huì)被清零
  271. if(ucRowRecord==1)//第一列輸出低電平
  272. {
  273. ucKeySec=9;//觸發(fā)9號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S9鍵
  274. }
  275. else if(ucRowRecord==2)//第二列輸出低電平
  276. {
  277. ucKeySec=10;//觸發(fā)10號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S10鍵
  278. }
  279. else if(ucRowRecord==3)//第三列輸出低電平
  280. {
  281. ucKeySec=11;//觸發(fā)11號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S11鍵
  282. }
  283. else //第四列輸出低電平
  284. {
  285. ucKeySec=12;//觸發(fā)12號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S12鍵
  286. }
  287. }
  288. }
  289. else if(key_sr1==1&&key_sr2==1&&key_sr3==1&&key_sr4==0)
  290. {
  291. uiKeyTimeCnt++;//去抖動(dòng)延時(shí)計(jì)數(shù)器
  292. if(uiKeyTimeCnt>const_key_time)
  293. {
  294. uiKeyTimeCnt=0;
  295. ucKeyLock=1;//自鎖按鍵置位,避免一直觸發(fā),只有松開按鍵,此標(biāo)志位才會(huì)被清零
  296. if(ucRowRecord==1)//第一列輸出低電平
  297. {
  298. ucKeySec=13;//觸發(fā)13號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S13鍵
  299. }
  300. else if(ucRowRecord==2)//第二列輸出低電平
  301. {
  302. ucKeySec=14;//觸發(fā)14號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S14鍵
  303. }
  304. else if(ucRowRecord==3)//第三列輸出低電平
  305. {
  306. ucKeySec=15;//觸發(fā)15號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S15鍵
  307. }
  308. else //第四列輸出低電平
  309. {
  310. ucKeySec=16;//觸發(fā)16號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S16鍵
  311. }
  312. }
  313. }
  314. }
  315. break;
  316. }
  317. }
  318. void key_service() //第三區(qū) 按鍵服務(wù)的應(yīng)用程序
  319. {
  320. switch(ucKeySec) //按鍵服務(wù)狀態(tài)切換
  321. {
  322. case 1:// 1號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S1鍵
  323. number_key_input(1);//由于數(shù)字按鍵的代碼相似度高,因此把具體代碼封裝在這個(gè)函數(shù)里
  324. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  325. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  326. break;
  327. case 2:// 2號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S2鍵
  328. number_key_input(2);//由于數(shù)字按鍵的代碼相似度高,因此把具體代碼封裝在這個(gè)函數(shù)里
  329. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  330. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  331. break;
  332. case 3:// 3號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S3鍵
  333. number_key_input(3);//由于數(shù)字按鍵的代碼相似度高,因此把具體代碼封裝在這個(gè)函數(shù)里
  334. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  335. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  336. break;
  337. case 4:// 4號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S4鍵
  338. number_key_input(4);//由于數(shù)字按鍵的代碼相似度高,因此把具體代碼封裝在這個(gè)函數(shù)里
  339. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  340. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  341. break;
  342. case 5:// 5號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S5鍵
  343. number_key_input(5);//由于數(shù)字按鍵的代碼相似度高,因此把具體代碼封裝在這個(gè)函數(shù)里
  344. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  345. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  346. break;
  347. case 6:// 6號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S6鍵
  348. number_key_input(6);//由于數(shù)字按鍵的代碼相似度高,因此把具體代碼封裝在這個(gè)函數(shù)里
  349. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  350. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  351. break;
  352. case 7:// 7號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S7鍵
  353. number_key_input(7);//由于數(shù)字按鍵的代碼相似度高,因此把具體代碼封裝在這個(gè)函數(shù)里
  354. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  355. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  356. break;
  357. case 8:// 8號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S8鍵
  358. number_key_input(8);//由于數(shù)字按鍵的代碼相似度高,因此把具體代碼封裝在這個(gè)函數(shù)里
  359. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  360. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  361. break;
  362. case 9:// 9號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S9鍵
  363. number_key_input(9);//由于數(shù)字按鍵的代碼相似度高,因此把具體代碼封裝在這個(gè)函數(shù)里
  364. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  365. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  366. break;
  367. case 10:// 把這個(gè)按鍵專門用來輸入數(shù)字0 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S10鍵
  368. number_key_input(0);//由于數(shù)字按鍵的代碼相似度高,因此把具體代碼封裝在這個(gè)函數(shù)里
  369. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  370. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  371. break;
  372. case 11:// 11號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S11鍵
  373. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  374. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  375. break;
  376. case 12:// 12號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S12鍵
  377. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  378. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  379. break;
  380. case 13:// 13號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S13鍵
  381. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  382. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  383. break;
  384. case 14:// 14號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S14鍵
  385. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  386. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  387. break;
  388. case 15:// 15號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S15鍵
  389. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  390. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  391. break;
  392. case 16:// 16號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S16鍵
  393. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  394. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  395. break;
  396. }
  397. }
  398. void number_key_input(unsigned char ucWhichKey)//由于數(shù)字按鍵的代碼相似度高,因此封裝在這個(gè)函數(shù)里
  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個(gè)的窗口,停留顯示1秒鐘全部密碼
  409. ucWd3Update=1;//更新顯示窗口3
  410. uiPasswordTimer=const_0_1s;//顯示0.5秒鐘全部密碼的計(jì)時(shí)器,讓窗口3停留顯示0.5秒鐘之后自動(dòng)消失
  411. }
  412. ucWd1Update=1; //更新顯示窗口1
  413. uiNoKeyPushTimer=const_no_key_push;//10秒內(nèi)無按鍵按下的計(jì)時(shí)器賦新值
  414. break;
  415. case 2: //在顯示按鍵值的窗口下
  416. ucKeyNumber=ucWhichKey; //輸入的按鍵數(shù)值顯示
  417. ucWd2Update=1;//更新顯示窗口2
  418. uiNoKeyPushTimer=const_no_key_push;//10秒內(nèi)無按鍵按下的計(jì)時(shí)器賦新值
  419. break;
  420. }
  421. }
  422. void display_drive()
  423. {
  424. //以下程序,如果加一些數(shù)組和移位的元素,還可以壓縮容量。但是鴻哥追求的不是容量,而是清晰的講解思路
  425. switch(ucDisplayDriveStep)
  426. {
  427. case 1://顯示第1位
  428. ucDigShowTemp=dig_table[ucDigShow1];
  429. if(ucDigDot1==1)
  430. {
  431. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數(shù)點(diǎn)
  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;//顯示小數(shù)點(diǎn)
  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;//顯示小數(shù)點(diǎn)
  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;//顯示小數(shù)點(diǎn)
  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;//顯示小數(shù)點(diǎn)
  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;//顯示小數(shù)點(diǎn)
  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;//顯示小數(shù)點(diǎn)
  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;//顯示小數(shù)點(diǎn)
  488. }
  489. dig_hc595_drive(ucDigShowTemp,0x7f);
  490. break;
  491. }
  492. ucDisplayDriveStep++;
  493. if(ucDisplayDriveStep>8)//掃描完8個(gè)數(shù)碼管后,重新從第一個(gè)開始掃描
  494. {
  495. ucDisplayDriveStep=1;
  496. }
  497. }
  498. //數(shù)碼管的74HC595驅(qū)動(dòng)函數(shù)
  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引腳的上升沿把數(shù)據(jù)送入寄存器
  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引腳的上升沿把數(shù)據(jù)送入寄存器
  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引腳把兩個(gè)寄存器的數(shù)據(jù)更新輸出到74HC595的輸出引腳上并且鎖存起來
  528. delay_short(1);
  529. dig_hc595_st_dr=1;
  530. delay_short(1);
  531. dig_hc595_sh_dr=0; //拉低,抗干擾就增強(qiáng)
  532. dig_hc595_st_dr=0;
  533. dig_hc595_ds_dr=0;
  534. }
  535. //LED燈的74HC595驅(qū)動(dòng)函數(shù)
  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引腳的上升沿把數(shù)據(jù)送入寄存器
  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引腳的上升沿把數(shù)據(jù)送入寄存器
  559. delay_short(1);
  560. hc595_sh_dr=1;
  561. delay_short(1);
  562. ucTempData=ucTempData<<1;
  563. }
  564. hc595_st_dr=0;//ST引腳把兩個(gè)寄存器的數(shù)據(jù)更新輸出到74HC595的輸出引腳上并且鎖存起來
  565. delay_short(1);
  566. hc595_st_dr=1;
  567. delay_short(1);
  568. hc595_sh_dr=0; //拉低,抗干擾就增強(qiáng)
  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;//清除中斷標(biāo)志
  576. TR0=0; //關(guān)中斷
  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個(gè)顯示按鍵的窗口
  588. ucWd2Update=1;//更新顯示窗口2
  589. }
  590. else //如果密碼不正確,則繼續(xù)顯示----
  591. {
  592. for(i=0;i<4;i++)
  593. {
  594. ucInputPassword[i]=11;//開機(jī)默認(rèn)密碼全部顯示"----"
  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秒內(nèi)無按鍵按下,則自動(dòng)切換到顯示密碼登錄框的界面
  608. {
  609. for(i=0;i<4;i++)
  610. {
  611. ucInputPassword[i]=11;//開機(jī)默認(rèn)密碼全部顯示"----"
  612. }
  613. ucWd=1;
  614. ucWd1Update=1; //更新顯示窗口1
  615. }
  616. }
  617. key_scan(); //按鍵掃描函數(shù)
  618. if(uiVoiceCnt!=0)
  619. {
  620. uiVoiceCnt--; //每次進(jìn)入定時(shí)中斷都自減1,直到等于零為止。才停止鳴叫
  621. beep_dr=0;//蜂鳴器是PNP三極管控制,低電平就開始鳴叫。
  622. // beep_dr=1;//蜂鳴器是PNP三極管控制,低電平就開始鳴叫。
  623. }
  624. else
  625. {
  626. ; //此處多加一個(gè)空指令,想維持跟if括號(hào)語句的數(shù)量對(duì)稱,都是兩條指令。不加也可以。
  627. beep_dr=1;//蜂鳴器是PNP三極管控制,高電平就停止鳴叫。
  628. // beep_dr=0;//蜂鳴器是PNP三極管控制,高電平就停止鳴叫。
  629. }
  630. display_drive();//數(shù)碼管字模的驅(qū)動(dòng)函數(shù)
  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. ; //一個(gè)分號(hào)相當(dāng)于執(zhí)行一條空語句
  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++)//內(nèi)嵌循環(huán)的空指令數(shù)量
  650. {
  651. ; //一個(gè)分號(hào)相當(dāng)于執(zhí)行一條空語句
  652. }
  653. }
  654. }
  655. void initial_myself()//第一區(qū) 初始化單片機(jī)
  656. {
  657. led_dr=0;//關(guān)閉獨(dú)立LED燈
  658. beep_dr=1; //用PNP三極管控制蜂鳴器,輸出高電平時(shí)不叫。
  659. hc595_drive(0x00,0x00);//關(guān)閉所有經(jīng)過另外兩個(gè)74HC595驅(qū)動(dòng)的LED燈
  660. TMOD=0x01;//設(shè)置定時(shí)器0為工作方式1
  661. TH0=0xfe; //重裝初始值(65535-500)=65035=0xfe0b
  662. TL0=0x0b;
  663. }
  664. void initial_peripheral() //第二區(qū) 初始化外圍
  665. {
  666. unsigned int i; //個(gè)人的變量命名習(xí)慣,i,j,k等單個(gè)字母的變量名只用在for循環(huán)里
  667. for(i=0;i<4;i++)
  668. {
  669. ucInputPassword[i]=11;//開機(jī)默認(rèn)密碼全部顯示"----"
  670. }
  671. ucDigDot8=0; //小數(shù)點(diǎn)全部不顯示
  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; //允許定時(shí)中斷
  681. TR0=1; //啟動(dòng)定時(shí)中斷
  682. }
復(fù)制代碼


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


評(píng)論


技術(shù)專區(qū)

關(guān)閉