在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,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)用 > 第37節(jié):數(shù)碼管作為儀表盤顯示跑馬燈的方向,速度和狀態(tài)

            第37節(jié):數(shù)碼管作為儀表盤顯示跑馬燈的方向,速度和狀態(tài)

            作者: 時間:2016-11-22 來源:網(wǎng)絡(luò) 收藏
            開場白:
            我在第24節(jié)中講過按鍵控制跑馬燈的方向,速度和運行狀態(tài)的項目程序,只可惜那個程序不能直觀地顯示運行中的三種狀態(tài),這節(jié)我決定在24節(jié)的基礎(chǔ)上,增加一個數(shù)碼管顯示作為類似汽車儀表盤的界面,實時顯示跑馬燈的方向,速度,和運行狀態(tài)。
            這一節(jié)要教會大家一個知識點:繼續(xù)加深理解運動,按鍵與數(shù)碼管三者之間的關(guān)聯(lián)程序框架。

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

            (1)硬件平臺:
            基于朱兆祺51單片機學(xué)習(xí)板。用S1鍵作為控制跑馬燈的方向按鍵,S5鍵作為控制跑馬燈方向的加速度按鍵,S9鍵作為控制跑馬燈方向的減速度按鍵,S13鍵作為控制跑馬燈方向的啟動或者暫停按鍵。記得把輸出線P0.4一直輸出低電平,模擬獨立按鍵的觸發(fā)地GND。

            (2)實現(xiàn)功能:
            跑馬燈運行:第1個至第8個LED燈一直不亮。在第9個至第16個LED燈,依次逐個亮燈并且每次只能亮一個燈。每按一次獨立按鍵S13鍵,原來運行的跑馬燈會暫停,原來暫停的跑馬燈會運行。用S1來改變方向。用S5和S9來改變速度,每按一次按鍵的遞增或者遞減以10為單位。
            數(shù)碼管顯示:本程序只有1個窗口,這個窗口分成3個局部顯示。8,7,6位數(shù)碼管顯示運行狀態(tài),啟動時顯示“on”,停止時顯示“oFF”。5位數(shù)碼管顯示數(shù)碼管方向,正向顯示“n”,反向顯示“U”。4,3,2,1位數(shù)碼管顯示速度。數(shù)值越大速度越慢,最慢的速度是550,最快的速度是50。

            (3)源代碼講解如下:
            1. #include "REG52.H"
            2. #define const_voice_short40 //蜂鳴器短叫的持續(xù)時間
            3. #define const_key_time120 //按鍵去抖動延時的時間
            4. #define const_key_time220 //按鍵去抖動延時的時間
            5. #define const_key_time320 //按鍵去抖動延時的時間
            6. #define const_key_time420 //按鍵去抖動延時的時間
            7. void initial_myself();
            8. void initial_peripheral();
            9. void delay_short(unsigned int uiDelayShort);
            10. void delay_long(unsigned int uiDelaylong);
            11. //驅(qū)動數(shù)碼管的74HC595
            12. void dig_hc595_drive(unsigned char ucDigStatusTemp16_09,unsigned char ucDigStatusTemp08_01);
            13. void display_drive(); //顯示數(shù)碼管字模的驅(qū)動函數(shù)
            14. void display_service(); //顯示的窗口菜單服務(wù)程序
            15. //驅(qū)動LED的74HC595
            16. void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01);
            17. void led_flicker_09_16(); //第9個至第16個LED的跑馬燈程序,逐個亮并且每次只能亮一個.
            18. void led_update();//LED更新函數(shù)
            19. void T0_time();//定時中斷函數(shù)
            20. void key_service(); //按鍵服務(wù)的應(yīng)用程序
            21. void key_scan();//按鍵掃描函數(shù) 放在定時中斷里
            22. sbit beep_dr=P2^7; //蜂鳴器的驅(qū)動IO口
            23. sbit key_sr1=P0^0; //對應(yīng)朱兆祺學(xué)習(xí)板的S1鍵
            24. sbit key_sr2=P0^1; //對應(yīng)朱兆祺學(xué)習(xí)板的S5鍵
            25. sbit key_sr3=P0^2; //對應(yīng)朱兆祺學(xué)習(xí)板的S9鍵
            26. sbit key_sr4=P0^3; //對應(yīng)朱兆祺學(xué)習(xí)板的S13鍵
            27. sbit key_gnd_dr=P0^4; //模擬獨立按鍵的地GND,因此必須一直輸出低電平
            28. sbit led_dr=P3^5;
            29. sbit dig_hc595_sh_dr=P2^0; //數(shù)碼管的74HC595程序
            30. sbit dig_hc595_st_dr=P2^1;
            31. sbit dig_hc595_ds_dr=P2^2;
            32. sbit hc595_sh_dr=P2^3; //LED燈的74HC595程序
            33. sbit hc595_st_dr=P2^4;
            34. sbit hc595_ds_dr=P2^5;
            35. unsigned char ucKeySec=0; //被觸發(fā)的按鍵編號
            36. unsigned intuiKeyTimeCnt1=0; //按鍵去抖動延時計數(shù)器
            37. unsigned char ucKeyLock1=0; //按鍵觸發(fā)后自鎖的變量標(biāo)志
            38. unsigned intuiKeyTimeCnt2=0; //按鍵去抖動延時計數(shù)器
            39. unsigned char ucKeyLock2=0; //按鍵觸發(fā)后自鎖的變量標(biāo)志
            40. unsigned intuiKeyTimeCnt3=0; //按鍵去抖動延時計數(shù)器
            41. unsigned char ucKeyLock3=0; //按鍵觸發(fā)后自鎖的變量標(biāo)志
            42. unsigned intuiKeyTimeCnt4=0; //按鍵去抖動延時計數(shù)器
            43. unsigned char ucKeyLock4=0; //按鍵觸發(fā)后自鎖的變量標(biāo)志
            44. unsigned intuiVoiceCnt=0;//蜂鳴器鳴叫的持續(xù)時間計數(shù)器
            45. unsigned char ucLed_dr1=0; //代表16個燈的亮滅狀態(tài),0代表滅,1代表亮
            46. unsigned char ucLed_dr2=0;
            47. unsigned char ucLed_dr3=0;
            48. unsigned char ucLed_dr4=0;
            49. unsigned char ucLed_dr5=0;
            50. unsigned char ucLed_dr6=0;
            51. unsigned char ucLed_dr7=0;
            52. unsigned char ucLed_dr8=0;
            53. unsigned char ucLed_dr9=0;
            54. unsigned char ucLed_dr10=0;
            55. unsigned char ucLed_dr11=0;
            56. unsigned char ucLed_dr12=0;
            57. unsigned char ucLed_dr13=0;
            58. unsigned char ucLed_dr14=0;
            59. unsigned char ucLed_dr15=0;
            60. unsigned char ucLed_dr16=0;
            61. unsigned char ucLed_update=0;//刷新變量。每次更改LED燈的狀態(tài)都要更新一次。
            62. unsigned char ucLedStep_09_16=0; //第9個至第16個LED跑馬燈的步驟變量
            63. unsigned intuiTimeCnt_09_16=0; //第9個至第16個LED跑馬燈的統(tǒng)計定時中斷次數(shù)的延時計數(shù)器
            64. unsigned char ucLedStatus16_09=0; //代表底層74HC595輸出狀態(tài)的中間變量
            65. unsigned char ucLedStatus08_01=0; //代表底層74HC595輸出狀態(tài)的中間變量
            66. unsigned char ucLedDirFlag=0; //方向變量,把按鍵與跑馬燈關(guān)聯(lián)起來的核心變量,0代表正方向,1代表反方向
            67. unsigned intuiSetTimeLevel_09_16=300;//速度變量,此數(shù)值越大速度越慢,此數(shù)值越小速度越快。
            68. unsigned char ucLedStartFlag=1; //啟動和暫停的變量,0代表暫停,1代表啟動
            69. unsigned char ucDigShow8;//第8位數(shù)碼管要顯示的內(nèi)容
            70. unsigned char ucDigShow7;//第7位數(shù)碼管要顯示的內(nèi)容
            71. unsigned char ucDigShow6;//第6位數(shù)碼管要顯示的內(nèi)容
            72. unsigned char ucDigShow5;//第5位數(shù)碼管要顯示的內(nèi)容
            73. unsigned char ucDigShow4;//第4位數(shù)碼管要顯示的內(nèi)容
            74. unsigned char ucDigShow3;//第3位數(shù)碼管要顯示的內(nèi)容
            75. unsigned char ucDigShow2;//第2位數(shù)碼管要顯示的內(nèi)容
            76. unsigned char ucDigShow1;//第1位數(shù)碼管要顯示的內(nèi)容
            77. unsigned char ucDigDot8;//數(shù)碼管8的小數(shù)點是否顯示的標(biāo)志
            78. unsigned char ucDigDot7;//數(shù)碼管7的小數(shù)點是否顯示的標(biāo)志
            79. unsigned char ucDigDot6;//數(shù)碼管6的小數(shù)點是否顯示的標(biāo)志
            80. unsigned char ucDigDot5;//數(shù)碼管5的小數(shù)點是否顯示的標(biāo)志
            81. unsigned char ucDigDot4;//數(shù)碼管4的小數(shù)點是否顯示的標(biāo)志
            82. unsigned char ucDigDot3;//數(shù)碼管3的小數(shù)點是否顯示的標(biāo)志
            83. unsigned char ucDigDot2;//數(shù)碼管2的小數(shù)點是否顯示的標(biāo)志
            84. unsigned char ucDigDot1;//數(shù)碼管1的小數(shù)點是否顯示的標(biāo)志
            85. unsigned char ucDigShowTemp=0; //臨時中間變量
            86. unsigned char ucDisplayDriveStep=1;//動態(tài)掃描數(shù)碼管的步驟變量
            87. unsigned char ucWd1Part1Update=1;//窗口1的局部1更新顯示變量
            88. unsigned char ucWd1Part2Update=1;//窗口1的局部2更新顯示變量
            89. unsigned char ucWd1Part3Update=1;//窗口1的局部3更新顯示變量
            90. //根據(jù)原理圖得出的共陰數(shù)碼管字模表
            91. code unsigned char dig_table[]=
            92. {
            93. 0x3f,//0 序號0
            94. 0x06,//1 序號1
            95. 0x5b,//2 序號2
            96. 0x4f,//3 序號3
            97. 0x66,//4 序號4
            98. 0x6d,//5 序號5
            99. 0x7d,//6 序號6
            100. 0x07,//7 序號7
            101. 0x7f,//8 序號8
            102. 0x6f,//9 序號9
            103. 0x00,//無 序號10
            104. 0x40,//- 序號11
            105. 0x73,//P 序號12
            106. 0x5c,//o 序號13
            107. 0x71,//F 序號14
            108. 0x3e,//U 序號15
            109. 0x37,//n 序號16
            110. };
            111. void main()
            112. {
            113. initial_myself();
            114. delay_long(100);
            115. initial_peripheral();
            116. while(1)
            117. {
            118. key_service(); //按鍵服務(wù)的應(yīng)用程序
            119. display_service(); //顯示的窗口菜單服務(wù)程序
            120. led_flicker_09_16(); //第9個至第16個LED的跑馬燈程序,逐個亮并且每次只能亮一個.
            121. led_update();//LED更新函數(shù)
            122. }
            123. }
            124. /* 注釋一:
            125. * 由于本程序只有1個窗口,而這個窗口又分成3個局部,因此可以省略去窗口變量uWd,
            126. * 只用三個局部變量ucWdxPartyUpdate就可以了。
            127. */
            128. void display_service() //顯示的窗口菜單服務(wù)程序
            129. {
            130. if(ucWd1Part1Update==1) //更新顯示當(dāng)前系統(tǒng)是處于運行還是暫停的狀態(tài)
            131. {
            132. ucWd1Part1Update=0; //及時把更新變量清零,防止一直進來更新
            133. if(ucLedStartFlag==1)//啟動,顯示on
            134. {
            135. ucDigShow8=13;//顯示o
            136. ucDigShow7=16;//顯示n
            137. ucDigShow6=10;//顯示空
            138. }
            139. else//暫停,顯示oFF
            140. {
            141. ucDigShow8=13;//顯示o
            142. ucDigShow7=14;//顯示F
            143. ucDigShow6=14;//顯示F
            144. }
            145. }
            146. if(ucWd1Part2Update==1) //更新顯示當(dāng)前系統(tǒng)是處于正方向還是反方向
            147. {
            148. ucWd1Part2Update=0; //及時把更新變量清零,防止一直進來更新
            149. if(ucLedDirFlag==0)//正方向,向上,顯示n
            150. {
            151. ucDigShow5=16;//顯示n
            152. }
            153. else//反方向,向下,顯示U
            154. {
            155. ucDigShow5=15;//顯示U
            156. }
            157. }
            158. if(ucWd1Part3Update==1) //更新顯示當(dāng)前系統(tǒng)的速度,此數(shù)值越大速度越慢,此數(shù)值越小速度越快。
            159. {
            160. ucWd1Part3Update=0; //及時把更新變量清零,防止一直進來更新
            161. ucDigShow4=10;//顯示空這一位不用,作為空格
            162. if(uiSetTimeLevel_09_16>=100)
            163. {
            164. ucDigShow3=uiSetTimeLevel_09_16/100; //顯示速度的百位
            165. }
            166. else
            167. {
            168. ucDigShow3=10; //顯示空
            169. }
            170. if(uiSetTimeLevel_09_16>=10)
            171. {
            172. ucDigShow2=uiSetTimeLevel_09_16%100/10;//顯示速度的十位
            173. }
            174. else
            175. {
            176. ucDigShow2=10; //顯示空
            177. }
            178. ucDigShow1=uiSetTimeLevel_09_16%10; //顯示速度的個位
            179. }
            180. }
            181. void key_scan()//按鍵掃描函數(shù) 放在定時中斷里
            182. {
            183. if(key_sr1==1)//IO是高電平,說明按鍵沒有被按下,這時要及時清零一些標(biāo)志位
            184. {
            185. ucKeyLock1=0; //按鍵自鎖標(biāo)志清零
            186. uiKeyTimeCnt1=0;//按鍵去抖動延時計數(shù)器清零,此行非常巧妙,是我實戰(zhàn)中摸索出來的。
            187. }
            188. else if(ucKeyLock1==0)//有按鍵按下,且是第一次被按下
            189. {
            190. uiKeyTimeCnt1++; //累加定時中斷次數(shù)
            191. if(uiKeyTimeCnt1>const_key_time1)
            192. {
            193. uiKeyTimeCnt1=0;
            194. ucKeyLock1=1;//自鎖按鍵置位,避免一直觸發(fā)
            195. ucKeySec=1; //觸發(fā)1號鍵
            196. }
            197. }
            198. if(key_sr2==1)//IO是高電平,說明按鍵沒有被按下,這時要及時清零一些標(biāo)志位
            199. {
            200. ucKeyLock2=0; //按鍵自鎖標(biāo)志清零
            201. uiKeyTimeCnt2=0;//按鍵去抖動延時計數(shù)器清零,此行非常巧妙,是我實戰(zhàn)中摸索出來的。
            202. }
            203. else if(ucKeyLock2==0)//有按鍵按下,且是第一次被按下
            204. {
            205. uiKeyTimeCnt2++; //累加定時中斷次數(shù)
            206. if(uiKeyTimeCnt2>const_key_time2)
            207. {
            208. uiKeyTimeCnt2=0;
            209. ucKeyLock2=1;//自鎖按鍵置位,避免一直觸發(fā)
            210. ucKeySec=2; //觸發(fā)2號鍵
            211. }
            212. }
            213. if(key_sr3==1)//IO是高電平,說明按鍵沒有被按下,這時要及時清零一些標(biāo)志位
            214. {
            215. ucKeyLock3=0; //按鍵自鎖標(biāo)志清零
            216. uiKeyTimeCnt3=0;//按鍵去抖動延時計數(shù)器清零,此行非常巧妙,是我實戰(zhàn)中摸索出來的。
            217. }
            218. else if(ucKeyLock3==0)//有按鍵按下,且是第一次被按下
            219. {
            220. uiKeyTimeCnt3++; //累加定時中斷次數(shù)
            221. if(uiKeyTimeCnt3>const_key_time3)
            222. {
            223. uiKeyTimeCnt3=0;
            224. ucKeyLock3=1;//自鎖按鍵置位,避免一直觸發(fā)
            225. ucKeySec=3; //觸發(fā)3號鍵
            226. }
            227. }
            228. if(key_sr4==1)//IO是高電平,說明按鍵沒有被按下,這時要及時清零一些標(biāo)志位
            229. {
            230. ucKeyLock4=0; //按鍵自鎖標(biāo)志清零
            231. uiKeyTimeCnt4=0;//按鍵去抖動延時計數(shù)器清零,此行非常巧妙,是我實戰(zhàn)中摸索出來的。
            232. }
            233. else if(ucKeyLock4==0)//有按鍵按下,且是第一次被按下
            234. {
            235. uiKeyTimeCnt4++; //累加定時中斷次數(shù)
            236. if(uiKeyTimeCnt4>const_key_time4)
            237. {
            238. uiKeyTimeCnt4=0;
            239. ucKeyLock4=1;//自鎖按鍵置位,避免一直觸發(fā)
            240. ucKeySec=4; //觸發(fā)4號鍵
            241. }
            242. }
            243. }
            244. void key_service() //按鍵服務(wù)的應(yīng)用程序
            245. {
            246. switch(ucKeySec) //按鍵服務(wù)狀態(tài)切換
            247. {
            248. case 1:// 改變跑馬燈方向的按鍵 對應(yīng)朱兆祺學(xué)習(xí)板的S1鍵
            249. if(ucLedDirFlag==0) //通過中間變量改變跑馬燈的方向
            250. {
            251. ucLedDirFlag=1;
            252. }
            253. else
            254. {
            255. ucLedDirFlag=0;
            256. }
            257. ucWd1Part2Update=1; //及時更新顯示方向
            258. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
            259. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號清零,避免一致觸發(fā)
            260. break;
            261. case 2:// 加速按鍵 對應(yīng)朱兆祺學(xué)習(xí)板的S5鍵 uiSetTimeLevel_09_16越小速度越快
            262. uiSetTimeLevel_09_16=uiSetTimeLevel_09_16-10;
            263. if(uiSetTimeLevel_09_16<50)//最快限定在50
            264. {
            265. uiSetTimeLevel_09_16=50;
            266. }
            267. ucWd1Part3Update=1; //及時更新顯示速度
            268. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
            269. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號清零,避免一致觸發(fā)
            270. break;
            271. case 3:// 減速按鍵 對應(yīng)朱兆祺學(xué)習(xí)板的S9鍵uiSetTimeLevel_09_16越大速度越慢
            272. uiSetTimeLevel_09_16=uiSetTimeLevel_09_16+10;
            273. if(uiSetTimeLevel_09_16>550)//最慢限定在550
            274. {
            275. uiSetTimeLevel_09_16=550;
            276. }
            277. ucWd1Part3Update=1; //及時更新顯示速度
            278. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
            279. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號清零,避免一致觸發(fā)
            280. break;
            281. case 4:// 啟動和暫停按鍵 對應(yīng)朱兆祺學(xué)習(xí)板的S13鍵ucLedStartFlag為0時代表暫停,為1時代表啟動
            282. if(ucLedStartFlag==1)//啟動和暫停兩種狀態(tài)循環(huán)切換
            283. {
            284. ucLedStartFlag=0;
            285. }
            286. else //啟動和暫停兩種狀態(tài)循環(huán)切換
            287. {
            288. ucLedStartFlag=1;
            289. }
            290. ucWd1Part1Update=1; //及時更新顯示系統(tǒng)的運行狀態(tài),是運行還是暫停.
            291. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
            292. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號清零,避免一致觸發(fā)
            293. break;
            294. }
            295. }
            296. void led_update()//LED更新函數(shù)
            297. {
            298. if(ucLed_update==1)
            299. {
            300. ucLed_update=0; //及時清零,讓它產(chǎn)生只更新一次的效果,避免一直更新。
            301. if(ucLed_dr1==1)
            302. {
            303. ucLedStatus08_01=ucLedStatus08_01|0x01;
            304. }
            305. else
            306. {
            307. ucLedStatus08_01=ucLedStatus08_01&0xfe;
            308. }
            309. if(ucLed_dr2==1)
            310. {
            311. ucLedStatus08_01=ucLedStatus08_01|0x02;
            312. }
            313. else
            314. {
            315. ucLedStatus08_01=ucLedStatus08_01&0xfd;
            316. }
            317. if(ucLed_dr3==1)
            318. {
            319. ucLedStatus08_01=ucLedStatus08_01|0x04;
            320. }
            321. else
            322. {
            323. ucLedStatus08_01=ucLedStatus08_01&0xfb;
            324. }
            325. if(ucLed_dr4==1)
            326. {
            327. ucLedStatus08_01=ucLedStatus08_01|0x08;
            328. }
            329. else
            330. {
            331. ucLedStatus08_01=ucLedStatus08_01&0xf7;
            332. }
            333. if(ucLed_dr5==1)
            334. {
            335. ucLedStatus08_01=ucLedStatus08_01|0x10;
            336. }
            337. else
            338. {
            339. ucLedStatus08_01=ucLedStatus08_01&0xef;
            340. }
            341. if(ucLed_dr6==1)
            342. {
            343. ucLedStatus08_01=ucLedStatus08_01|0x20;
            344. }
            345. else
            346. {
            347. ucLedStatus08_01=ucLedStatus08_01&0xdf;
            348. }
            349. if(ucLed_dr7==1)
            350. {
            351. ucLedStatus08_01=ucLedStatus08_01|0x40;
            352. }
            353. else
            354. {
            355. ucLedStatus08_01=ucLedStatus08_01&0xbf;
            356. }
            357. if(ucLed_dr8==1)
            358. {
            359. ucLedStatus08_01=ucLedStatus08_01|0x80;
            360. }
            361. else
            362. {
            363. ucLedStatus08_01=ucLedStatus08_01&0x7f;
            364. }
            365. if(ucLed_dr9==1)
            366. {
            367. ucLedStatus16_09=ucLedStatus16_09|0x01;
            368. }
            369. else
            370. {
            371. ucLedStatus16_09=ucLedStatus16_09&0xfe;
            372. }
            373. if(ucLed_dr10==1)
            374. {
            375. ucLedStatus16_09=ucLedStatus16_09|0x02;
            376. }
            377. else
            378. {
            379. ucLedStatus16_09=ucLedStatus16_09&0xfd;
            380. }
            381. if(ucLed_dr11==1)
            382. {
            383. ucLedStatus16_09=ucLedStatus16_09|0x04;
            384. }
            385. else
            386. {
            387. ucLedStatus16_09=ucLedStatus16_09&0xfb;
            388. }
            389. if(ucLed_dr12==1)
            390. {
            391. ucLedStatus16_09=ucLedStatus16_09|0x08;
            392. }
            393. else
            394. {
            395. ucLedStatus16_09=ucLedStatus16_09&0xf7;
            396. }
            397. if(ucLed_dr13==1)
            398. {
            399. ucLedStatus16_09=ucLedStatus16_09|0x10;
            400. }
            401. else
            402. {
            403. ucLedStatus16_09=ucLedStatus16_09&0xef;
            404. }
            405. if(ucLed_dr14==1)
            406. {
            407. ucLedStatus16_09=ucLedStatus16_09|0x20;
            408. }
            409. else
            410. {
            411. ucLedStatus16_09=ucLedStatus16_09&0xdf;
            412. }
            413. if(ucLed_dr15==1)
            414. {
            415. ucLedStatus16_09=ucLedStatus16_09|0x40;
            416. }
            417. else
            418. {
            419. ucLedStatus16_09=ucLedStatus16_09&0xbf;
            420. }
            421. if(ucLed_dr16==1)
            422. {
            423. ucLedStatus16_09=ucLedStatus16_09|0x80;
            424. }
            425. else
            426. {
            427. ucLedStatus16_09=ucLedStatus16_09&0x7f;
            428. }
            429. hc595_drive(ucLedStatus16_09,ucLedStatus08_01);//74HC595底層驅(qū)動函數(shù)
            430. }
            431. }
            432. void display_drive()
            433. {
            434. //以下程序,如果加一些數(shù)組和移位的元素,還可以壓縮容量。但是鴻哥追求的不是容量,而是清晰的講解思路
            435. switch(ucDisplayDriveStep)
            436. {
            437. case 1://顯示第1位
            438. ucDigShowTemp=dig_table[ucDigShow1];
            439. if(ucDigDot1==1)
            440. {
            441. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數(shù)點
            442. }
            443. dig_hc595_drive(ucDigShowTemp,0xfe);
            444. break;
            445. case 2://顯示第2位
            446. ucDigShowTemp=dig_table[ucDigShow2];
            447. if(ucDigDot2==1)
            448. {
            449. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數(shù)點
            450. }
            451. dig_hc595_drive(ucDigShowTemp,0xfd);
            452. break;
            453. case 3://顯示第3位
            454. ucDigShowTemp=dig_table[ucDigShow3];
            455. if(ucDigDot3==1)
            456. {
            457. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數(shù)點
            458. }
            459. dig_hc595_drive(ucDigShowTemp,0xfb);
            460. break;
            461. case 4://顯示第4位
            462. ucDigShowTemp=dig_table[ucDigShow4];
            463. if(ucDigDot4==1)
            464. {
            465. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數(shù)點
            466. }
            467. dig_hc595_drive(ucDigShowTemp,0xf7);
            468. break;
            469. case 5://顯示第5位
            470. ucDigShowTemp=dig_table[ucDigShow5];
            471. if(ucDigDot5==1)
            472. {
            473. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數(shù)點
            474. }
            475. dig_hc595_drive(ucDigShowTemp,0xef);
            476. break;
            477. case 6://顯示第6位
            478. ucDigShowTemp=dig_table[ucDigShow6];
            479. if(ucDigDot6==1)
            480. {
            481. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數(shù)點
            482. }
            483. dig_hc595_drive(ucDigShowTemp,0xdf);
            484. break;
            485. case 7://顯示第7位
            486. ucDigShowTemp=dig_table[ucDigShow7];
            487. if(ucDigDot7==1)
            488. {
            489. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數(shù)點
            490. }
            491. dig_hc595_drive(ucDigShowTemp,0xbf);
            492. break;
            493. case 8://顯示第8位
            494. ucDigShowTemp=dig_table[ucDigShow8];
            495. if(ucDigDot8==1)
            496. {
            497. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數(shù)點
            498. }
            499. dig_hc595_drive(ucDigShowTemp,0x7f);
            500. break;
            501. }
            502. ucDisplayDriveStep++;
            503. if(ucDisplayDriveStep>8)//掃描完8個數(shù)碼管后,重新從第一個開始掃描
            504. {
            505. ucDisplayDriveStep=1;
            506. }
            507. }
            508. //數(shù)碼管的74HC595驅(qū)動函數(shù)
            509. void dig_hc595_drive(unsigned char ucDigStatusTemp16_09,unsigned char ucDigStatusTemp08_01)
            510. {
            511. unsigned char i;
            512. unsigned char ucTempData;
            513. dig_hc595_sh_dr=0;
            514. dig_hc595_st_dr=0;
            515. ucTempData=ucDigStatusTemp16_09;//先送高8位
            516. for(i=0;i<8;i++)
            517. {
            518. if(ucTempData>=0x80)dig_hc595_ds_dr=1;
            519. else dig_hc595_ds_dr=0;
            520. dig_hc595_sh_dr=0; //SH引腳的上升沿把數(shù)據(jù)送入寄存器
            521. delay_short(1);
            522. dig_hc595_sh_dr=1;
            523. delay_short(1);
            524. ucTempData=ucTempData<<1;
            525. }
            526. ucTempData=ucDigStatusTemp08_01;//再先送低8位
            527. for(i=0;i<8;i++)
            528. {
            529. if(ucTempData>=0x80)dig_hc595_ds_dr=1;
            530. else dig_hc595_ds_dr=0;
            531. dig_hc595_sh_dr=0; //SH引腳的上升沿把數(shù)據(jù)送入寄存器
            532. delay_short(1);
            533. dig_hc595_sh_dr=1;
            534. delay_short(1);
            535. ucTempData=ucTempData<<1;
            536. }
            537. dig_hc595_st_dr=0;//ST引腳把兩個寄存器的數(shù)據(jù)更新輸出到74HC595的輸出引腳上并且鎖存起來
            538. delay_short(1);
            539. dig_hc595_st_dr=1;
            540. delay_short(1);
            541. dig_hc595_sh_dr=0; //拉低,抗干擾就增強
            542. dig_hc595_st_dr=0;
            543. dig_hc595_ds_dr=0;
            544. }
            545. //LED燈的74HC595驅(qū)動函數(shù)
            546. void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01)
            547. {
            548. unsigned char i;
            549. unsigned char ucTempData;
            550. hc595_sh_dr=0;
            551. hc595_st_dr=0;
            552. ucTempData=ucLedStatusTemp16_09;//先送高8位
            553. for(i=0;i<8;i++)
            554. {
            555. if(ucTempData>=0x80)hc595_ds_dr=1;
            556. else hc595_ds_dr=0;
            557. hc595_sh_dr=0; //SH引腳的上升沿把數(shù)據(jù)送入寄存器
            558. delay_short(1);
            559. hc595_sh_dr=1;
            560. delay_short(1);
            561. ucTempData=ucTempData<<1;
            562. }
            563. ucTempData=ucLedStatusTemp08_01;//再先送低8位
            564. for(i=0;i<8;i++)
            565. {
            566. if(ucTempData>=0x80)hc595_ds_dr=1;
            567. else hc595_ds_dr=0;
            568. hc595_sh_dr=0; //SH引腳的上升沿把數(shù)據(jù)送入寄存器
            569. delay_short(1);
            570. hc595_sh_dr=1;
            571. delay_short(1);
            572. ucTempData=ucTempData<<1;
            573. }
            574. hc595_st_dr=0;//ST引腳把兩個寄存器的數(shù)據(jù)更新輸出到74HC595的輸出引腳上并且鎖存起來
            575. delay_short(1);
            576. hc595_st_dr=1;
            577. delay_short(1);
            578. hc595_sh_dr=0; //拉低,抗干擾就增強
            579. hc595_st_dr=0;
            580. hc595_ds_dr=0;
            581. }
            582. void led_flicker_09_16() //第9個至第16個LED的跑馬燈程序,逐個亮并且每次只能亮一個.
            583. {
            584. if(ucLedStartFlag==1)//此變量為1時代表啟動
            585. {
            586. switch(ucLedStep_09_16)
            587. {
            588. case 0:
            589. if(uiTimeCnt_09_16>=uiSetTimeLevel_09_16) //時間到
            590. {
            591. uiTimeCnt_09_16=0; //時間計數(shù)器清零
            592. if(ucLedDirFlag==0)//正方向
            593. {
            594. ucLed_dr16=0;//第16個滅
            595. ucLed_dr9=1;//第9個亮
            596. ucLed_update=1;//更新顯示
            597. ucLedStep_09_16=1; //切換到下一個步驟
            598. }
            599. else//反方向
            600. {
            601. ucLed_dr15=1;//第15個亮
            602. ucLed_dr16=0;//第16個滅
            603. ucLed_update=1;//更新顯示
            604. ucLedStep_09_16=7; //返回上一個步驟
            605. }
            606. }
            607. break;
            608. case 1:
            609. if(uiTimeCnt_09_16>=uiSetTimeLevel_09_16) //時間到
            610. {
            611. uiTimeCnt_09_16=0; //時間計數(shù)器清零
            612. if(ucLedDirFlag==0)//正方向
            613. {
            614. ucLed_dr9=0;//第9個滅
            615. ucLed_dr10=1;//第10個亮
            616. ucLed_update=1;//更新顯示
            617. ucLedStep_09_16=2; //切換到下一個步驟
            618. }
            619. else//反方向
            620. {
            621. ucLed_dr16=1;//第16個亮
            622. ucLed_dr9=0;//第9個滅
            623. ucLed_update=1;//更新顯示
            624. ucLedStep_09_16=0; //返回上一個步驟
            625. }
            626. }
            627. break;
            628. case 2:
            629. if(uiTimeCnt_09_16>=uiSetTimeLevel_09_16) //時間到
            630. {
            631. uiTimeCnt_09_16=0; //時間計數(shù)器清零
            632. if(ucLedDirFlag==0)//正方向
            633. {
            634. ucLed_dr10=0;//第10個滅
            635. ucLed_dr11=1;//第11個亮
            636. ucLed_update=1;//更新顯示
            637. ucLedStep_09_16=3; //切換到下一個步驟
            638. }
            639. else//反方向
            640. {
            641. ucLed_dr9=1;//第9個亮
            642. ucLed_dr10=0;//第10個滅
            643. ucLed_update=1;//更新顯示
            644. ucLedStep_09_16=1; //返回上一個步驟
            645. }
            646. }
            647. break;
            648. case 3:
            649. if(uiTimeCnt_09_16>=uiSetTimeLevel_09_16) //時間到
            650. {
            651. uiTimeCnt_09_16=0; //時間計數(shù)器清零
            652. if(ucLedDirFlag==0)//正方向
            653. {
            654. ucLed_dr11=0;//第11個滅
            655. ucLed_dr12=1;//第12個亮
            656. ucLed_update=1;//更新顯示
            657. ucLedStep_09_16=4; //切換到下一個步驟
            658. }
            659. else//反方向
            660. {
            661. ucLed_dr10=1;//第10個亮
            662. ucLed_dr11=0;//第11個滅
            663. ucLed_update=1;//更新顯示
            664. ucLedStep_09_16=2; //返回上一個步驟
            665. }
            666. }
            667. break;
            668. case 4:
            669. if(uiTimeCnt_09_16>=uiSetTimeLevel_09_16) //時間到
            670. {
            671. uiTimeCnt_09_16=0; //時間計數(shù)器清零
            672. if(ucLedDirFlag==0)//正方向
            673. {
            674. ucLed_dr12=0;//第12個滅
            675. ucLed_dr13=1;//第13個亮
            676. ucLed_update=1;//更新顯示
            677. ucLedStep_09_16=5; //切換到下一個步驟
            678. }
            679. else//反方向
            680. {
            681. ucLed_dr11=1;//第11個亮
            682. ucLed_dr12=0;//第12個滅
            683. ucLed_update=1;//更新顯示
            684. ucLedStep_09_16=3; //返回上一個步驟
            685. }
            686. }
            687. break;
            688. case 5:
            689. if(uiTimeCnt_09_16>=uiSetTimeLevel_09_16) //時間到
            690. {
            691. uiTimeCnt_09_16=0; //時間計數(shù)器清零
            692. if(ucLedDirFlag==0)//正方向
            693. {
            694. ucLed_dr13=0;//第13個滅
            695. ucLed_dr14=1;//第14個亮
            696. ucLed_update=1;//更新顯示
            697. ucLedStep_09_16=6; //切換到下一個步驟
            698. }
            699. else//反方向
            700. {
            701. ucLed_dr12=1;//第12個亮
            702. ucLed_dr13=0;//第13個滅
            703. ucLed_update=1;//更新顯示
            704. ucLedStep_09_16=4; //返回上一個步驟
            705. }
            706. }
            707. break;
            708. case 6:
            709. if(uiTimeCnt_09_16>=uiSetTimeLevel_09_16) //時間到
            710. {
            711. uiTimeCnt_09_16=0; //時間計數(shù)器清零
            712. if(ucLedDirFlag==0)//正方向
            713. {
            714. ucLed_dr14=0;//第14個滅
            715. ucLed_dr15=1;//第15個亮
            716. ucLed_update=1;//更新顯示
            717. ucLedStep_09_16=7; //切換到下一個步驟
            718. }
            719. else//反方向
            720. {
            721. ucLed_dr13=1;//第13個亮
            722. ucLed_dr14=0;//第14個滅
            723. ucLed_update=1;//更新顯示
            724. ucLedStep_09_16=5; //返回上一個步驟
            725. }
            726. }
            727. break;
            728. case 7:
            729. if(uiTimeCnt_09_16>=uiSetTimeLevel_09_16) //時間到
            730. {
            731. uiTimeCnt_09_16=0; //時間計數(shù)器清零
            732. if(ucLedDirFlag==0)//正方向
            733. {
            734. ucLed_dr15=0;//第15個滅
            735. ucLed_dr16=1;//第16個亮
            736. ucLed_update=1;//更新顯示
            737. ucLedStep_09_16=0; //返回到開始處,重新開始新的一次循環(huán)
            738. }
            739. else//反方向
            740. {
            741. ucLed_dr14=1;//第14個亮
            742. ucLed_dr15=0;//第15個滅
            743. ucLed_update=1;//更新顯示
            744. ucLedStep_09_16=6; //返回上一個步驟
            745. }
            746. }
            747. break;
            748. }
            749. }
            750. }
            751. void T0_time() interrupt 1
            752. {
            753. TF0=0;//清除中斷標(biāo)志
            754. TR0=0; //關(guān)中斷
            755. if(uiTimeCnt_09_16<0xffff)//設(shè)定這個條件,防止uiTimeCnt超范圍。
            756. {
            757. if(ucLedStartFlag==1)//此變量為1時代表啟動
            758. {
            759. uiTimeCnt_09_16++;//累加定時中斷的次數(shù),
            760. }
            761. }
            762. key_scan(); //按鍵掃描函數(shù)
            763. if(uiVoiceCnt!=0)
            764. {
            765. uiVoiceCnt--; //每次進入定時中斷都自減1,直到等于零為止。才停止鳴叫
            766. beep_dr=0;//蜂鳴器是PNP三極管控制,低電平就開始鳴叫。
            767. // beep_dr=1;//蜂鳴器是PNP三極管控制,低電平就開始鳴叫。
            768. }
            769. else
            770. {
            771. ; //此處多加一個空指令,想維持跟if括號語句的數(shù)量對稱,都是兩條指令。不加也可以。
            772. beep_dr=1;//蜂鳴器是PNP三極管控制,高電平就停止鳴叫。
            773. // beep_dr=0;//蜂鳴器是PNP三極管控制,高電平就停止鳴叫。
            774. }
            775. display_drive();//數(shù)碼管字模的驅(qū)動函數(shù)
            776. TH0=0xfe; //重裝初始值(65535-500)=65035=0xfe0b
            777. TL0=0x0b;
            778. TR0=1;//開中斷
            779. }
            780. void delay_short(unsigned int uiDelayShort)
            781. {
            782. unsigned int i;
            783. for(i=0;i
            784. {
            785. ; //一個分號相當(dāng)于執(zhí)行一條空語句
            786. }
            787. }
            788. void delay_long(unsigned int uiDelayLong)
            789. {
            790. unsigned int i;
            791. unsigned int j;
            792. for(i=0;i
            793. {
            794. for(j=0;j<500;j++)//內(nèi)嵌循環(huán)的空指令數(shù)量
            795. {
            796. ; //一個分號相當(dāng)于執(zhí)行一條空語句
            797. }
            798. }
            799. }
            800. void initial_myself()//第一區(qū) 初始化單片機
            801. {
            802. /* 注釋二:
            803. * 矩陣鍵盤也可以做獨立按鍵,前提是把某一根公共輸出線輸出低電平,
            804. * 模擬獨立按鍵的觸發(fā)地,本程序中,把key_gnd_dr輸出低電平。
            805. * 朱兆祺51學(xué)習(xí)板的S1就是本程序中用到的一個獨立按鍵。
            806. */
            807. key_gnd_dr=0; //模擬獨立按鍵的地GND,因此必須一直輸出低電平
            808. led_dr=0;//關(guān)閉獨立LED燈
            809. beep_dr=1; //用PNP三極管控制蜂鳴器,輸出高電平時不叫。
            810. TMOD=0x01;//設(shè)置定時器0為工作方式1
            811. TH0=0xfe; //重裝初始值(65535-500)=65035=0xfe0b
            812. TL0=0x0b;
            813. }
            814. void initial_peripheral() //第二區(qū) 初始化外圍
            815. {
            816. ucDigDot8=0; //小數(shù)點全部不顯示
            817. ucDigDot7=0;
            818. ucDigDot6=0;
            819. ucDigDot5=0;
            820. ucDigDot4=0;
            821. ucDigDot3=0;
            822. ucDigDot2=0;
            823. ucDigDot1=0;
            824. EA=1; //開總中斷
            825. ET0=1; //允許定時中斷
            826. TR0=1; //啟動定時中斷
            827. }


            總結(jié)陳詞:
            前面花了大量的章節(jié)在講數(shù)碼管顯示,按鍵,運動的關(guān)聯(lián)程序框架,從下一節(jié)開始,我將會用八節(jié)內(nèi)容來講我常用的串口程序框架,內(nèi)容非常精彩和震撼,思路非常簡單而又實用。欲知詳情,請聽下回分解-----判斷數(shù)據(jù)尾來接收一串?dāng)?shù)據(jù)的串口通用程序框架。


            關(guān)鍵詞: 數(shù)碼管儀表盤跑馬

            評論


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

            關(guān)閉