<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 第36節(jié):帶數(shù)碼管顯示的加法簡易計算器

          第36節(jié):帶數(shù)碼管顯示的加法簡易計算器

          作者: 時間:2016-11-22 來源:網(wǎng)絡(luò) 收藏
          開場白:
          這一節(jié)要做一個簡單的計算器。這個計算器不帶小數(shù)點,只能進行不超過8位數(shù)據(jù)的加法運算,它麻雀雖小但是五臟俱全,它能清晰地勾勒出商業(yè)計算器的程序框架和思路。讀者只要看懂本節(jié)程序框架的規(guī)律,以后自己想做一個復(fù)雜一點的計算器應(yīng)該是沒問題的。復(fù)雜的計算器在算法上要用數(shù)組進行特殊處理,不能簡單地直接用C語言的+,-,*,/運算符,這方面的內(nèi)容我會在以后的章節(jié)中跟大家分享。
          這一節(jié)要教會大家兩個知識點:
          第一個:數(shù)字按鍵的輸入和十進制數(shù)值的移位方法。
          第二個:繼續(xù)加深理解按鍵與數(shù)碼管的關(guān)聯(lián)程序框架。

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

          (1)硬件平臺:
          基于朱兆祺51單片機學(xué)習(xí)板。數(shù)字1鍵對應(yīng)S1鍵,數(shù)字2鍵對應(yīng)S2鍵,數(shù)字3鍵對應(yīng)S3鍵…. 數(shù)字9鍵對應(yīng)S9鍵, 數(shù)字0鍵對應(yīng)S10鍵。加號鍵對應(yīng)S13,等于號鍵對應(yīng)S14,清除復(fù)位按鍵對應(yīng)S16。其它按鍵不用。

          (2)實現(xiàn)功能:
          常用的加法計算器功能。有連加功能。
          本程序有2個窗口。
          第1個窗口:原始數(shù)據(jù)和運算結(jié)果窗口。比如加法運算中的被加數(shù)
          第2個窗口:第二個參與運行的數(shù)據(jù)窗口。比如加法運算中的加數(shù)

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


          總結(jié)陳詞:
          這節(jié)講了加法簡易計算器的程序項目。為了讓讀者理解運動,按鍵,顯示是如何有規(guī)律關(guān)聯(lián)起來的,下節(jié)會繼續(xù)講一個相關(guān)的小項目程序。欲知詳情,請聽下回分解-----數(shù)碼管作為儀表盤顯示跑馬燈的方向,速度和運行狀態(tài)。


          評論


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

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();