新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 第47節(jié):操作AT24C02利用定時(shí)器延時(shí)改善數(shù)碼管的閃爍

第47節(jié):操作AT24C02利用定時(shí)器延時(shí)改善數(shù)碼管的閃爍

作者: 時(shí)間:2016-11-22 來(lái)源:網(wǎng)絡(luò) 收藏
開(kāi)場(chǎng)白:
上一節(jié)在按鍵更改參數(shù)時(shí),會(huì)出現(xiàn)短暫明顯的數(shù)碼管閃爍現(xiàn)象。這節(jié)通過(guò)教大家使用新型延時(shí)函數(shù)可以有效的改善閃爍現(xiàn)象。要教會(huì)大家三個(gè)知識(shí)點(diǎn):
第一個(gè):如何編寫(xiě)一氣呵成的定時(shí)器延時(shí)函數(shù)。
第二個(gè):如何編寫(xiě)檢查EEPROM芯片是否存在短路,虛焊或者芯片壞了的監(jiān)控程序。
第三個(gè):經(jīng)過(guò)網(wǎng)友“cjseng”的提醒,我建議大家以后在用EEPROM芯片時(shí),如果單片機(jī)IO口足夠多,WP引腳應(yīng)該專門(mén)接一個(gè)IO口,并且加一個(gè)上拉電阻,需要更改EEPROM存儲(chǔ)數(shù)據(jù)時(shí)置低,其他任何一個(gè)時(shí)刻都置高,這樣可以更加有效地保護(hù)EEPROM內(nèi)部數(shù)據(jù)不會(huì)被意外更改。

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

(1)硬件平臺(tái):
基于朱兆祺51單片機(jī)學(xué)習(xí)板。舊版的朱兆祺51學(xué)習(xí)板在硬件上有一個(gè)bug,AT24C02的第8個(gè)引腳VCC懸空了!!!,讀者記得把它飛線連接到5V電源處。新版的朱兆祺51學(xué)習(xí)板已經(jīng)改過(guò)來(lái)了。


(2)實(shí)現(xiàn)功能:
4個(gè)被更改后的參數(shù)斷電后不丟失,數(shù)據(jù)可以保存,斷電再上電后還是上一次最新被修改的數(shù)據(jù)。如果AT24C02短路,虛焊,或者壞了,系統(tǒng)可以檢查出來(lái),并且蜂鳴器會(huì)間歇性鳴叫報(bào)警。按更改參數(shù)按鍵時(shí),數(shù)碼管比上一節(jié)大大降低了閃爍現(xiàn)象。
顯示和獨(dú)立按鍵部分根據(jù)第29節(jié)的程序來(lái)改編,用朱兆祺51單片機(jī)學(xué)習(xí)板中的S1,S5,S9作為獨(dú)立按鍵。
一共有4個(gè)窗口。每個(gè)窗口顯示一個(gè)參數(shù)。
第8,7,6,5位數(shù)碼管顯示當(dāng)前窗口,P-1代表第1個(gè)窗口,P-2代表第2個(gè)窗口,P-3代表第3個(gè)窗口,P-4代表第1個(gè)窗口。
第4,3,2,1位數(shù)碼管顯示當(dāng)前窗口被設(shè)置的參數(shù)。范圍是從0到9999。S1是加按鍵,按下此按鍵會(huì)依次增加當(dāng)前窗口的參數(shù)。S5是減按鍵,按下此按鍵會(huì)依次減少當(dāng)前窗口的參數(shù)。S9是切換窗口按鍵,按下此按鍵會(huì)依次循環(huán)切換不同的窗口。


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

總結(jié)陳詞:
下一節(jié)開(kāi)始講關(guān)于單片機(jī)驅(qū)動(dòng)實(shí)時(shí)時(shí)鐘芯片的內(nèi)容,欲知詳情,請(qǐng)聽(tīng)下回分解-----利用DS1302做一個(gè)實(shí)時(shí)時(shí)鐘。


評(píng)論


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

關(guān)閉