在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,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) > 設(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單片機學習板。數(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ā)后自鎖的變量標志
            37. unsigned char ucRowRecord=1; //記錄當前掃描到第幾列了
            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; //更新顯示標志
            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代表當前沒有選擇運行符號。1代表當前的運算符是加法。
            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;//按鍵自鎖標志清零
            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ā),只有松開按鍵,此標志位才會被清零
            400. if(ucRowRecord==1)//第一列輸出低電平
            401. {
            402. ucKeySec=1;//觸發(fā)1號鍵 對應(yīng)朱兆祺學習板的S1鍵
            403. }
            404. else if(ucRowRecord==2)//第二列輸出低電平
            405. {
            406. ucKeySec=2;//觸發(fā)2號鍵 對應(yīng)朱兆祺學習板的S2鍵
            407. }
            408. else if(ucRowRecord==3)//第三列輸出低電平
            409. {
            410. ucKeySec=3;//觸發(fā)3號鍵 對應(yīng)朱兆祺學習板的S3鍵
            411. }
            412. else //第四列輸出低電平
            413. {
            414. ucKeySec=4;//觸發(fā)4號鍵 對應(yīng)朱兆祺學習板的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ā),只有松開按鍵,此標志位才會被清零
            425. if(ucRowRecord==1)//第一列輸出低電平
            426. {
            427. ucKeySec=5;//觸發(fā)5號鍵 對應(yīng)朱兆祺學習板的S5鍵
            428. }
            429. else if(ucRowRecord==2)//第二列輸出低電平
            430. {
            431. ucKeySec=6;//觸發(fā)6號鍵 對應(yīng)朱兆祺學習板的S6鍵
            432. }
            433. else if(ucRowRecord==3)//第三列輸出低電平
            434. {
            435. ucKeySec=7;//觸發(fā)7號鍵 對應(yīng)朱兆祺學習板的S7鍵
            436. }
            437. else //第四列輸出低電平
            438. {
            439. ucKeySec=8;//觸發(fā)8號鍵 對應(yīng)朱兆祺學習板的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ā),只有松開按鍵,此標志位才會被清零
            450. if(ucRowRecord==1)//第一列輸出低電平
            451. {
            452. ucKeySec=9;//觸發(fā)9號鍵 對應(yīng)朱兆祺學習板的S9鍵
            453. }
            454. else if(ucRowRecord==2)//第二列輸出低電平
            455. {
            456. ucKeySec=10;//觸發(fā)10號鍵 對應(yīng)朱兆祺學習板的S10鍵
            457. }
            458. else if(ucRowRecord==3)//第三列輸出低電平
            459. {
            460. ucKeySec=11;//觸發(fā)11號鍵 對應(yīng)朱兆祺學習板的S11鍵
            461. }
            462. else //第四列輸出低電平
            463. {
            464. ucKeySec=12;//觸發(fā)12號鍵 對應(yīng)朱兆祺學習板的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ā),只有松開按鍵,此標志位才會被清零
            475. if(ucRowRecord==1)//第一列輸出低電平
            476. {
            477. ucKeySec=13;//觸發(fā)13號鍵 對應(yīng)朱兆祺學習板的S13鍵
            478. }
            479. else if(ucRowRecord==2)//第二列輸出低電平
            480. {
            481. ucKeySec=14;//觸發(fā)14號鍵 對應(yīng)朱兆祺學習板的S14鍵
            482. }
            483. else if(ucRowRecord==3)//第三列輸出低電平
            484. {
            485. ucKeySec=15;//觸發(fā)15號鍵 對應(yīng)朱兆祺學習板的S15鍵
            486. }
            487. else //第四列輸出低電平
            488. {
            489. ucKeySec=16;//觸發(fā)16號鍵 對應(yīng)朱兆祺學習板的S16鍵
            490. }
            491. }
            492. }
            493. }
            494. break;
            495. }
            496. }
            497. /* 注釋三:
            498. *按鍵服務(wù)程序操作的精髓在于根據(jù)當前系統(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)朱兆祺學習板的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)朱兆祺學習板的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)朱兆祺學習板的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)朱兆祺學習板的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)朱兆祺學習板的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)朱兆祺學習板的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)朱兆祺學習板的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)朱兆祺學習板的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)朱兆祺學習板的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)朱兆祺學習板的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)朱兆祺學習板的S11鍵
            556. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
            557. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號清零,避免一致觸發(fā)
            558. break;
            559. case 12:// 12號鍵 對應(yīng)朱兆祺學習板的S12鍵
            560. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
            561. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號清零,避免一致觸發(fā)
            562. break;
            563. case 13:// 13號鍵 加號按鍵對應(yīng)朱兆祺學習板的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ù)默認為當前運算結(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)朱兆祺學習板的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ù)默認為當前運算結(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ù)默認為當前運算結(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)朱兆祺學習板的S15鍵
            616. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
            617. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號清零,避免一致觸發(fā)
            618. break;
            619. case 16:// 16號鍵 清除按鍵 相當于復(fù)位的功能。重新輸入數(shù)據(jù)對應(yīng)朱兆祺學習板的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;//清除中斷標志
            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. ; //一個分號相當于執(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. ; //一個分號相當于執(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)閉