新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 第88節(jié):?jiǎn)纹瑱C(jī)靠關(guān)鍵字快速截取有效數(shù)據(jù)串

第88節(jié):?jiǎn)纹瑱C(jī)靠關(guān)鍵字快速截取有效數(shù)據(jù)串

作者: 時(shí)間:2016-11-22 來源:網(wǎng)絡(luò) 收藏
開場(chǎng)白:
我前面串口程序大部分都是通過靠時(shí)間來識(shí)別每一串?dāng)?shù)據(jù)是否接收完畢,有一些串口項(xiàng)目的協(xié)議是固定不變的,而且也不需要從機(jī)反饋任何應(yīng)答信號(hào),這類項(xiàng)目只需根據(jù)特定關(guān)鍵字來快速識(shí)別數(shù)據(jù)串是否接收完畢即可。比如現(xiàn)在有一種電子稱,它的測(cè)量范圍是0.00克到500.00克,他是靠串口不斷對(duì)外發(fā)送當(dāng)前重量數(shù)據(jù)的,每串?dāng)?shù)據(jù)固定長(zhǎng)度26個(gè)字節(jié),最后兩個(gè)字節(jié)是回車換行符0x0d 0x0a,倒數(shù)第9,10,11,12,13,14為有效的ASCII碼數(shù)字,其中倒數(shù)第11位為固定的小數(shù)點(diǎn),其它的數(shù)據(jù)可以忽略不計(jì)。這類串口框架的思路是:根據(jù)數(shù)據(jù)尾是否有0x0d 0x0a來判斷數(shù)據(jù)串是否有效的,一旦發(fā)現(xiàn)有此關(guān)鍵字,再判斷總的數(shù)據(jù)長(zhǎng)度是否等于或者大于一串?dāng)?shù)據(jù)的固定長(zhǎng)度,如果滿足,則把相關(guān)標(biāo)志位置位,通知主函數(shù)中的串口服務(wù)程序進(jìn)行處理。同時(shí)也及時(shí)關(guān)閉串口中斷,避免在處理串口數(shù)據(jù)期間受到串口數(shù)據(jù)的中斷干擾,等串口服務(wù)程序處理完畢再打開。
具體內(nèi)容,請(qǐng)看源代碼講解。
(1) 硬件平臺(tái):
基于朱兆祺51單片機(jī)學(xué)習(xí)板。
(2) 實(shí)現(xiàn)功能:
波特率是:9600。把當(dāng)前電子稱的重量數(shù)據(jù)顯示在數(shù)碼管上,在電腦上用串口助手軟件來模擬電子稱發(fā)送以下格式協(xié)議的3串?dāng)?shù)據(jù),它的協(xié)議很簡(jiǎn)單,每串?dāng)?shù)據(jù)固定長(zhǎng)度26個(gè)字節(jié),最后兩個(gè)字節(jié)是回車換行符0x0d 0x0a,倒數(shù)第9,10,11,12,13,14為有效的ASCII碼數(shù)字,其中倒數(shù)第11位為固定的小數(shù)點(diǎn),其它的數(shù)據(jù)可以忽略不計(jì)。
(a)字符是:
ST,GS,+ 0.77 g
轉(zhuǎn)換成16進(jìn)制是:
20 53 54 2C 47 53 2C 2B 20 20 20 20 20 20 30 2E 37 37 20 2020 20 20 67 0D 0A
數(shù)碼管顯示:0.77
(b)
字符是:
ST,GS,+ 136.39 g
轉(zhuǎn)換成16進(jìn)制是:
20 53 54 2C 47 53 2C 2B 20 20 20 20 31 33 36 2E 33 39 20 2020 20 20 67 0D 0A
數(shù)碼管顯示:136.39
(c)
字符是:
ST,GS,+ 0.00 g
轉(zhuǎn)換成16進(jìn)制是:
20 53 54 2C 47 53 2C 2B 20 20 20 20 20 20 30 2E 30 30 20 2020 20 20 67 0D 0A
數(shù)碼管顯示:0.00

(3)源代碼講解如下:
  1. #include "REG52.H"
  2. #define const_rc_size36//接收串口中斷數(shù)據(jù)的緩沖區(qū)數(shù)組大小
  3. #define const_least_size 26 //一串標(biāo)準(zhǔn)數(shù)據(jù)的大小
  4. void initial_myself();
  5. void initial_peripheral();
  6. void delay_short(unsigned int uiDelayShort);
  7. void delay_long(unsigned int uiDelaylong);
  8. //驅(qū)動(dòng)數(shù)碼管的74HC595
  9. void dig_hc595_drive(unsigned char ucDigStatusTemp16_09,unsigned char ucDigStatusTemp08_01);
  10. void display_drive(); //顯示數(shù)碼管字模的驅(qū)動(dòng)函數(shù)
  11. void display_service(); //顯示的窗口菜單服務(wù)程序
  12. //驅(qū)動(dòng)LED的74HC595
  13. void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01);
  14. void usart_service(void);//串口接收服務(wù)程序,在main函數(shù)里
  15. void usart_receive(void); //串口接收中斷函數(shù)
  16. void T0_time();//定時(shí)中斷函數(shù)
  17. sbit dig_hc595_sh_dr=P2^0; //數(shù)碼管的74HC595程序
  18. sbit dig_hc595_st_dr=P2^1;
  19. sbit dig_hc595_ds_dr=P2^2;
  20. sbit hc595_sh_dr=P2^3; //LED燈的74HC595程序
  21. sbit hc595_st_dr=P2^4;
  22. sbit hc595_ds_dr=P2^5;
  23. sbit beep_dr=P2^7; //蜂鳴器的驅(qū)動(dòng)IO口
  24. sbit led_dr=P3^5;//獨(dú)立LED燈
  25. //根據(jù)原理圖得出的共陰數(shù)碼管字模表
  26. code unsigned char dig_table[]=
  27. {
  28. 0x3f,//0 序號(hào)0
  29. 0x06,//1 序號(hào)1
  30. 0x5b,//2 序號(hào)2
  31. 0x4f,//3 序號(hào)3
  32. 0x66,//4 序號(hào)4
  33. 0x6d,//5 序號(hào)5
  34. 0x7d,//6 序號(hào)6
  35. 0x07,//7 序號(hào)7
  36. 0x7f,//8 序號(hào)8
  37. 0x6f,//9 序號(hào)9
  38. 0x00,//無 序號(hào)10
  39. 0x40,//- 序號(hào)11
  40. 0x73,//P 序號(hào)12
  41. };
  42. unsigned intuiRcregTotal=0;//代表當(dāng)前緩沖區(qū)已經(jīng)接收了多少個(gè)數(shù)據(jù)
  43. unsigned intuiRcregTotalTemp=0;//代表當(dāng)前緩沖區(qū)已經(jīng)接收了多少個(gè)數(shù)據(jù)的中間變量
  44. unsigned char ucRcregBuf[const_rc_size]; //接收串口中斷數(shù)據(jù)的緩沖區(qū)數(shù)組
  45. unsigned char ucReceiveFlag=0; //接收成功標(biāo)志
  46. unsigned char ucDigShow8;//第8位數(shù)碼管要顯示的內(nèi)容
  47. unsigned char ucDigShow7;//第7位數(shù)碼管要顯示的內(nèi)容
  48. unsigned char ucDigShow6;//第6位數(shù)碼管要顯示的內(nèi)容
  49. unsigned char ucDigShow5;//第5位數(shù)碼管要顯示的內(nèi)容
  50. unsigned char ucDigShow4;//第4位數(shù)碼管要顯示的內(nèi)容
  51. unsigned char ucDigShow3;//第3位數(shù)碼管要顯示的內(nèi)容
  52. unsigned char ucDigShow2;//第2位數(shù)碼管要顯示的內(nèi)容
  53. unsigned char ucDigShow1;//第1位數(shù)碼管要顯示的內(nèi)容
  54. unsigned char ucDigDot8;//數(shù)碼管8的小數(shù)點(diǎn)是否顯示的標(biāo)志
  55. unsigned char ucDigDot7;//數(shù)碼管7的小數(shù)點(diǎn)是否顯示的標(biāo)志
  56. unsigned char ucDigDot6;//數(shù)碼管6的小數(shù)點(diǎn)是否顯示的標(biāo)志
  57. unsigned char ucDigDot5;//數(shù)碼管5的小數(shù)點(diǎn)是否顯示的標(biāo)志
  58. unsigned char ucDigDot4;//數(shù)碼管4的小數(shù)點(diǎn)是否顯示的標(biāo)志
  59. unsigned char ucDigDot3;//數(shù)碼管3的小數(shù)點(diǎn)是否顯示的標(biāo)志
  60. unsigned char ucDigDot2;//數(shù)碼管2的小數(shù)點(diǎn)是否顯示的標(biāo)志
  61. unsigned char ucDigDot1;//數(shù)碼管1的小數(shù)點(diǎn)是否顯示的標(biāo)志
  62. unsigned char ucDigShowTemp=0; //臨時(shí)中間變量
  63. unsigned char ucDisplayDriveStep=1;//動(dòng)態(tài)掃描數(shù)碼管的步驟變量
  64. unsigned char ucWd1Part1Update=1; //8位數(shù)碼管更新顯示標(biāo)志
  65. unsigned long ulWeightCurrent=12345; //顯示當(dāng)前實(shí)際的重量
  66. void main()
  67. {
  68. initial_myself();
  69. delay_long(100);
  70. initial_peripheral();
  71. while(1)
  72. {
  73. usart_service();//串口接收服務(wù)程序
  74. display_service(); //顯示的窗口菜單服務(wù)程序
  75. }
  76. }
  77. /* 注釋一:
  78. * 本節(jié)內(nèi)容處理串口數(shù)據(jù)是根據(jù)數(shù)據(jù)尾是否有0x0d 0x0a來判斷數(shù)據(jù)串是否有效的,一旦發(fā)現(xiàn)有此關(guān)鍵字,
  79. * 再判斷總的數(shù)據(jù)長(zhǎng)度是否等于或者大于一串?dāng)?shù)據(jù)的固定長(zhǎng)度,如果滿足,則把相關(guān)標(biāo)志位置位,通知主函數(shù)中
  80. * 的串口服務(wù)程序進(jìn)行處理。同時(shí)也及時(shí)關(guān)閉串口中斷,避免在處理串口數(shù)據(jù)期間受到串口數(shù)據(jù)的中斷干擾,
  81. * 等串口服務(wù)程序處理完畢再打開。
  82. */
  83. void usart_receive(void) interrupt 4 //串口接收數(shù)據(jù)中斷函數(shù)
  84. {
  85. if(RI==1)
  86. {
  87. RI = 0;
  88. ++uiRcregTotal;
  89. ucRcregBuf[uiRcregTotal-1]=SBUF; //將串口接收到的數(shù)據(jù)緩存到接收緩沖區(qū)里
  90. if(uiRcregTotal>=2&&ucRcregBuf[uiRcregTotal-2]==0x0d&&ucRcregBuf[uiRcregTotal-1]==0x0a)//一旦發(fā)現(xiàn)后綴是0x0d 0x0a關(guān)鍵字的就進(jìn)去處理判斷
  91. {
  92. if(uiRcregTotal
  93. {
  94. uiRcregTotal=0;
  95. }
  96. else
  97. {
  98. uiRcregTotalTemp=uiRcregTotal; //把接收到的總數(shù)據(jù)傳遞給一個(gè)中間變量,在主函數(shù)那邊處理這個(gè)中間變量
  99. ucReceiveFlag=1; //通知主程序接收成功
  100. ES=0; // 禁止接收中斷,等主函數(shù)處理完接收的數(shù)據(jù)后再打開串口中斷,避免在處理串口數(shù)據(jù)期間受到串口數(shù)據(jù)的中斷干擾。
  101. }
  102. }
  103. else if(uiRcregTotal>=const_rc_size)//超過緩沖區(qū)
  104. {
  105. uiRcregTotal=0;
  106. }
  107. }
  108. else //如果不是串口接收中斷,那么必然是串口發(fā)送中斷,及時(shí)清除發(fā)送中斷的標(biāo)志,否則一直發(fā)送中斷
  109. {
  110. TI = 0;
  111. }
  112. }
  113. void usart_service(void)//串口接收服務(wù)程序,在main函數(shù)里
  114. {
  115. //加了static關(guān)鍵字后,此局部變量不會(huì)每次進(jìn)來函數(shù)都初始化一次,這樣有可能減少了一點(diǎn)指令消耗的時(shí)間。
  116. static unsigned long ulReceiveData10000; //定義成long類型,是為了方便后面換算的乘法運(yùn)算,讓它不會(huì)溢出而出錯(cuò)。
  117. static unsigned long ulReceiveData1000;
  118. static unsigned long ulReceiveData100;
  119. static unsigned long ulReceiveData10;
  120. static unsigned long ulReceiveData1;
  121. if(ucReceiveFlag==1)//說明有數(shù)據(jù)接收成功,進(jìn)入數(shù)據(jù)處理分析
  122. {
  123. ulReceiveData10000=0;
  124. ulReceiveData1000=0;
  125. ulReceiveData100=0;
  126. ulReceiveData10=0;
  127. ulReceiveData1=0;
  128. /* 注釋二:
  129. * 根據(jù)協(xié)議,倒數(shù)第9,10,11,12,13,14為有效的ASCII碼數(shù)字,其中倒數(shù)第11位為固定的小數(shù)點(diǎn),因此省略不寫。
  130. */
  131. if(ucRcregBuf[uiRcregTotalTemp-9]>=0x30)
  132. {
  133. ulReceiveData1=ucRcregBuf[uiRcregTotalTemp-9]-0x30; //接收到的ASCII碼數(shù)字減去0x30變成實(shí)際數(shù)值.
  134. }
  135. if(ucRcregBuf[uiRcregTotalTemp-10]>=0x30)
  136. {
  137. ulReceiveData10=ucRcregBuf[uiRcregTotalTemp-10]-0x30;
  138. ulReceiveData10=ulReceiveData10*10;
  139. }
  140. if(ucRcregBuf[uiRcregTotalTemp-12]>=0x30)
  141. {
  142. ulReceiveData100=ucRcregBuf[uiRcregTotalTemp-12]-0x30;
  143. ulReceiveData100=ulReceiveData100*100;
  144. }
  145. if(ucRcregBuf[uiRcregTotalTemp-13]>=0x30)
  146. {
  147. ulReceiveData1000=ucRcregBuf[uiRcregTotalTemp-13]-0x30;
  148. ulReceiveData1000=ulReceiveData1000*1000;
  149. }
  150. if(ucRcregBuf[uiRcregTotalTemp-14]>=0x30)
  151. {
  152. ulReceiveData10000=ucRcregBuf[uiRcregTotalTemp-14]-0x30;
  153. ulReceiveData10000=ulReceiveData10000*10000;
  154. }
  155. ulWeightCurrent=ulReceiveData10000+ulReceiveData1000+ulReceiveData100+ulReceiveData10+ulReceiveData1;
  156. ucWd1Part1Update=1; //更新顯示
  157. uiRcregTotalTemp=0;//清零實(shí)際接收到的字節(jié)數(shù)的中間變量
  158. uiRcregTotal=0;//清零實(shí)際接收到的字節(jié)數(shù)
  159. ucReceiveFlag=0;//清零完成標(biāo)志
  160. ES = 1; // 允許接收中斷
  161. }
  162. }
  163. void display_service() //顯示的窗口菜單服務(wù)程序
  164. {
  165. //加了static關(guān)鍵字后,此局部變量不會(huì)每次進(jìn)來函數(shù)都初始化一次,這樣有可能減少了一點(diǎn)指令消耗的時(shí)間。
  166. static unsigned char ucTemp5; //中間過渡變量
  167. static unsigned char ucTemp4; //中間過渡變量
  168. static unsigned char ucTemp3; //中間過渡變量
  169. static unsigned char ucTemp2; //中間過渡變量
  170. static unsigned char ucTemp1; //中間過渡變量
  171. if(ucWd1Part1Update==1)//更新顯示
  172. {
  173. ucWd1Part1Update=0;//及時(shí)清零標(biāo)志,避免一直進(jìn)來掃描
  174. //先分解數(shù)據(jù)用來顯示每一位
  175. ucTemp5=ulWeightCurrent%100000/10000;
  176. ucTemp4=ulWeightCurrent%10000/1000;
  177. ucTemp3=ulWeightCurrent%1000/100;
  178. ucTemp2=ulWeightCurrent%100/10;
  179. ucTemp1=ulWeightCurrent%10;
  180. ucDigDot3=1;//顯示第3位數(shù)碼管的小數(shù)點(diǎn),實(shí)際數(shù)據(jù)帶2位小數(shù)點(diǎn)。
  181. ucDigShow8=10;//沒有用到第8位數(shù)碼管,因此顯示無。10代表顯示空。
  182. ucDigShow7=10;//沒有用到第7位數(shù)碼管,因此顯示無。10代表顯示空。
  183. ucDigShow6=10;//沒有用到第6位數(shù)碼管,因此顯示無。10代表顯示空。
  184. if(ulWeightCurrent<10000)
  185. {
  186. ucDigShow5=10;//如果小于1000,千位顯示無
  187. }
  188. else
  189. {
  190. ucDigShow5=ucTemp5;//第5位數(shù)碼管要顯示的內(nèi)容
  191. }
  192. if(ulWeightCurrent<1000)
  193. {
  194. ucDigShow4=10;//如果小于1000,千位顯示無
  195. }
  196. else
  197. {
  198. ucDigShow4=ucTemp4;//第4位數(shù)碼管要顯示的內(nèi)容
  199. }
  200. //因?yàn)閹?位小數(shù)點(diǎn),因此最前面3位數(shù)據(jù)都是有效數(shù),必然要顯示,不要判斷去0的空顯示處理。
  201. ucDigShow3=ucTemp3;//第3位數(shù)碼管要顯示的內(nèi)容
  202. ucDigShow2=ucTemp2;//第2位數(shù)碼管要顯示的內(nèi)容
  203. ucDigShow1=ucTemp1;//第1位數(shù)碼管要顯示的內(nèi)容
  204. }
  205. }
  206. void display_drive()
  207. {
  208. //以下程序,如果加一些數(shù)組和移位的元素,還可以壓縮容量。但是鴻哥追求的不是容量,而是清晰的講解思路
  209. switch(ucDisplayDriveStep)
  210. {
  211. case 1://顯示第1位
  212. ucDigShowTemp=dig_table[ucDigShow1];
  213. if(ucDigDot1==1)
  214. {
  215. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數(shù)點(diǎn)
  216. }
  217. dig_hc595_drive(ucDigShowTemp,0xfe);
  218. break;
  219. case 2://顯示第2位
  220. ucDigShowTemp=dig_table[ucDigShow2];
  221. if(ucDigDot2==1)
  222. {
  223. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數(shù)點(diǎn)
  224. }
  225. dig_hc595_drive(ucDigShowTemp,0xfd);
  226. break;
  227. case 3://顯示第3位
  228. ucDigShowTemp=dig_table[ucDigShow3];
  229. if(ucDigDot3==1)
  230. {
  231. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數(shù)點(diǎn)
  232. }
  233. dig_hc595_drive(ucDigShowTemp,0xfb);
  234. break;
  235. case 4://顯示第4位
  236. ucDigShowTemp=dig_table[ucDigShow4];
  237. if(ucDigDot4==1)
  238. {
  239. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數(shù)點(diǎn)
  240. }
  241. dig_hc595_drive(ucDigShowTemp,0xf7);
  242. break;
  243. case 5://顯示第5位
  244. ucDigShowTemp=dig_table[ucDigShow5];
  245. if(ucDigDot5==1)
  246. {
  247. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數(shù)點(diǎn)
  248. }
  249. dig_hc595_drive(ucDigShowTemp,0xef);
  250. break;
  251. case 6://顯示第6位
  252. ucDigShowTemp=dig_table[ucDigShow6];
  253. if(ucDigDot6==1)
  254. {
  255. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數(shù)點(diǎn)
  256. }
  257. dig_hc595_drive(ucDigShowTemp,0xdf);
  258. break;
  259. case 7://顯示第7位
  260. ucDigShowTemp=dig_table[ucDigShow7];
  261. if(ucDigDot7==1)
  262. {
  263. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數(shù)點(diǎn)
  264. }
  265. dig_hc595_drive(ucDigShowTemp,0xbf);
  266. break;
  267. case 8://顯示第8位
  268. ucDigShowTemp=dig_table[ucDigShow8];
  269. if(ucDigDot8==1)
  270. {
  271. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數(shù)點(diǎn)
  272. }
  273. dig_hc595_drive(ucDigShowTemp,0x7f);
  274. break;
  275. }
  276. ucDisplayDriveStep++;
  277. if(ucDisplayDriveStep>8)//掃描完8個(gè)數(shù)碼管后,重新從第一個(gè)開始掃描
  278. {
  279. ucDisplayDriveStep=1;
  280. }
  281. }
  282. //數(shù)碼管的74HC595驅(qū)動(dòng)函數(shù)
  283. void dig_hc595_drive(unsigned char ucDigStatusTemp16_09,unsigned char ucDigStatusTemp08_01)
  284. {
  285. unsigned char i;
  286. unsigned char ucTempData;
  287. dig_hc595_sh_dr=0;
  288. dig_hc595_st_dr=0;
  289. ucTempData=ucDigStatusTemp16_09;//先送高8位
  290. for(i=0;i<8;i++)
  291. {
  292. if(ucTempData>=0x80)dig_hc595_ds_dr=1;
  293. else dig_hc595_ds_dr=0;
  294. dig_hc595_sh_dr=0; //SH引腳的上升沿把數(shù)據(jù)送入寄存器
  295. delay_short(1);
  296. dig_hc595_sh_dr=1;
  297. delay_short(1);
  298. ucTempData=ucTempData<<1;
  299. }
  300. ucTempData=ucDigStatusTemp08_01;//再先送低8位
  301. for(i=0;i<8;i++)
  302. {
  303. if(ucTempData>=0x80)dig_hc595_ds_dr=1;
  304. else dig_hc595_ds_dr=0;
  305. dig_hc595_sh_dr=0; //SH引腳的上升沿把數(shù)據(jù)送入寄存器
  306. delay_short(1);
  307. dig_hc595_sh_dr=1;
  308. delay_short(1);
  309. ucTempData=ucTempData<<1;
  310. }
  311. dig_hc595_st_dr=0;//ST引腳把兩個(gè)寄存器的數(shù)據(jù)更新輸出到74HC595的輸出引腳上并且鎖存起來
  312. delay_short(1);
  313. dig_hc595_st_dr=1;
  314. delay_short(1);
  315. dig_hc595_sh_dr=0; //拉低,抗干擾就增強(qiáng)
  316. dig_hc595_st_dr=0;
  317. dig_hc595_ds_dr=0;
  318. }
  319. //LED燈的74HC595驅(qū)動(dòng)函數(shù)
  320. void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01)
  321. {
  322. unsigned char i;
  323. unsigned char ucTempData;
  324. hc595_sh_dr=0;
  325. hc595_st_dr=0;
  326. ucTempData=ucLedStatusTemp16_09;//先送高8位
  327. for(i=0;i<8;i++)
  328. {
  329. if(ucTempData>=0x80)hc595_ds_dr=1;
  330. else hc595_ds_dr=0;
  331. hc595_sh_dr=0; //SH引腳的上升沿把數(shù)據(jù)送入寄存器
  332. delay_short(1);
  333. hc595_sh_dr=1;
  334. delay_short(1);
  335. ucTempData=ucTempData<<1;
  336. }
  337. ucTempData=ucLedStatusTemp08_01;//再先送低8位
  338. for(i=0;i<8;i++)
  339. {
  340. if(ucTempData>=0x80)hc595_ds_dr=1;
  341. else hc595_ds_dr=0;
  342. hc595_sh_dr=0; //SH引腳的上升沿把數(shù)據(jù)送入寄存器
  343. delay_short(1);
  344. hc595_sh_dr=1;
  345. delay_short(1);
  346. ucTempData=ucTempData<<1;
  347. }
  348. hc595_st_dr=0;//ST引腳把兩個(gè)寄存器的數(shù)據(jù)更新輸出到74HC595的輸出引腳上并且鎖存起來
  349. delay_short(1);
  350. hc595_st_dr=1;
  351. delay_short(1);
  352. hc595_sh_dr=0; //拉低,抗干擾就增強(qiáng)
  353. hc595_st_dr=0;
  354. hc595_ds_dr=0;
  355. }
  356. void T0_time() interrupt 1
  357. {
  358. TF0=0;//清除中斷標(biāo)志
  359. TR0=0; //關(guān)中斷
  360. display_drive();//數(shù)碼管字模的驅(qū)動(dòng)函數(shù)
  361. TH0=0xfe; //重裝初始值(65535-500)=65035=0xfe0b
  362. TL0=0x0b;
  363. TR0=1;//開中斷
  364. }
  365. void delay_short(unsigned int uiDelayShort)
  366. {
  367. unsigned int i;
  368. for(i=0;i
  369. {
  370. ; //一個(gè)分號(hào)相當(dāng)于執(zhí)行一條空語句
  371. }
  372. }
  373. void delay_long(unsigned int uiDelayLong)
  374. {
  375. unsigned int i;
  376. unsigned int j;
  377. for(i=0;i
  378. {
  379. for(j=0;j<500;j++)//內(nèi)嵌循環(huán)的空指令數(shù)量
  380. {
  381. ; //一個(gè)分號(hào)相當(dāng)于執(zhí)行一條空語句
  382. }
  383. }
  384. }
  385. void initial_myself()//第一區(qū) 初始化單片機(jī)
  386. {
  387. beep_dr=1; //用PNP三極管控制蜂鳴器,輸出高電平時(shí)不叫。
  388. led_dr=0;//關(guān)閉獨(dú)立LED燈
  389. hc595_drive(0x00,0x00);//關(guān)閉所有經(jīng)過另外兩個(gè)74HC595驅(qū)動(dòng)的LED燈
  390. TMOD=0x01;//設(shè)置定時(shí)器0為工作方式1
  391. TH0=0xfe; //重裝初始值(65535-500)=65035=0xfe0b
  392. TL0=0x0b;
  393. //配置串口
  394. SCON=0x50;
  395. TMOD=0X21;
  396. /* 注釋三:
  397. * 為了保證串口中斷接收的數(shù)據(jù)不丟失,必須設(shè)置IP = 0x10,相當(dāng)于把串口中斷設(shè)置為最高優(yōu)先級(jí),
  398. * 這個(gè)時(shí)候,串口中斷可以打斷任何其他的中斷服務(wù)函數(shù)實(shí)現(xiàn)嵌套,
  399. */
  400. IP =0x10;//把串口中斷設(shè)置為最高優(yōu)先級(jí),必須的。
  401. TH1=TL1=-(11059200L/12/32/9600);//串口波特率為9600。
  402. TR1=1;
  403. }
  404. void initial_peripheral() //第二區(qū) 初始化外圍
  405. {
  406. ucDigDot8=0; //初始化小數(shù)點(diǎn)全部不顯示
  407. ucDigDot7=0;
  408. ucDigDot6=0;
  409. ucDigDot5=0;
  410. ucDigDot4=0;
  411. ucDigDot3=0;
  412. ucDigDot2=0;
  413. ucDigDot1=0;
  414. EA=1; //開總中斷
  415. ES=1; //允許串口中斷
  416. ET0=1; //允許定時(shí)中斷
  417. TR0=1; //啟動(dòng)定時(shí)中斷
  418. }
總結(jié)陳詞:
前面我在第48節(jié)里講過用ds1302做的時(shí)鐘程序,但是后來很多網(wǎng)友建議,為了方便初學(xué)者學(xué)習(xí)編程思路,我應(yīng)該用單片機(jī)定時(shí)器做一個(gè)時(shí)鐘程序。因此,我決定下一節(jié)講這方面的內(nèi)容。欲知詳情,請(qǐng)聽下回分解----用單片機(jī)內(nèi)部定時(shí)器做一個(gè)時(shí)鐘。


評(píng)論


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

關(guān)閉