久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 4842|回復(fù): 5
打印 上一主題 下一主題
收起左側(cè)

超聲波測(cè)距仿真(溫度補(bǔ)償)按鍵代指超聲波測(cè)距

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)


單片機(jī)源程序如下:
  1. #include <reg52.h>     //包括一個(gè)52標(biāo)準(zhǔn)內(nèi)核的頭文件
  2. #include<intrins.h>  //包含_nop_()函數(shù)定義的頭文件
  3. #define uchar unsigned char //定義一下方便使用
  4. #define uint  unsigned int
  5. #define ulong unsigned long

  6. #define RdCommand 0x01 //定義ISP的操作命令
  7. #define PrgCommand 0x02
  8. #define EraseCommand 0x03
  9. #define Error 1
  10. #define Ok 0
  11. #define WaitTime 0x01 //定義CPU的等待時(shí)間

  12. sfr ISP_DATA=0xe2;  //寄存器申明
  13. sfr ISP_ADDRH=0xe3;
  14. sfr ISP_ADDRL=0xe4;
  15. sfr ISP_CMD=0xe5;
  16. sfr ISP_TRIG=0xe6;
  17. sfr ISP_CONTR=0xe7;
  18. char a_a;

  19. sbit key1=P1^1;//參數(shù)加
  20. sbit key3=P1^2;//參數(shù)減
  21. sbit key2=P1^0;//參數(shù)設(shè)置按鍵
  22. sbit DQ=P3^3;
  23. sbit LED=P2^7;
  24. sbit alarm=P3^4;//蜂鳴器管腳定義

  25. sbit TX=P3^5; //超聲波模塊管腳定義(發(fā)射脈沖引腳定義)
  26. sbit RX=P3^6; //超聲波模塊管腳定義 (回波引腳定義)

  27. sbit RS=P2^0;    //液晶寄存器選擇位,將RS位定義為P2.0引腳
  28. sbit RW=P2^1;    //液晶讀寫(xiě)選擇位,將RW位定義為P2.1引腳
  29. sbit E=P2^2;     //液晶使能信號(hào)位,將E位定義為P2.2引腳
  30. sbit BF=P0^7;    //液晶忙碌標(biāo)志位,,將BF位定義為P0.7引腳

  31. unsigned char code digit[ ]={"0123456789"}; //定義字符數(shù)組顯示數(shù)字
  32. uint time=0,timer=0,S=0;
  33. uchar menu;//參數(shù)調(diào)整液晶顯示參數(shù)
  34. uchar ge,shi,bai,qian,flag;  //距離數(shù)據(jù)轉(zhuǎn)換
  35. uchar num1,num2;//上下限參數(shù)定義
  36. uchar H_bai,H_shi,H_ge;//上限參數(shù)值分解顯示定義
  37. uchar L_bai,L_shi,L_ge;//下限參數(shù)值分解顯示定義
  38. uint temp1,temp2;//上下限參數(shù)轉(zhuǎn)換,用于報(bào)警值比較判斷
  39. uchar time0;   //設(shè)置全局變量,專(zhuān)門(mén)用于嚴(yán)格延時(shí)
  40. uchar TL;     //儲(chǔ)存暫存器的溫度低位
  41. uchar TH;    //儲(chǔ)存暫存器的溫度高位
  42. uchar TN;      //儲(chǔ)存溫度的整數(shù)部分
  43. uchar TD;       //儲(chǔ)存溫度的小數(shù)部分
  44. uchar WD_temp;

  45. /* ================ 打開(kāi) ISP,IAP 功能 ================= */
  46. void ISP_IAP_enable(void)
  47. {
  48. EA = 0;       /* 關(guān)中斷   */
  49. ISP_CONTR = ISP_CONTR & 0x18;       /* 0001,1000 */
  50. ISP_CONTR = ISP_CONTR | WaitTime; /* 寫(xiě)入硬件延時(shí) */
  51. ISP_CONTR = ISP_CONTR | 0x80;       /* ISPEN=1  */
  52. }
  53. /* =============== 關(guān)閉 ISP,IAP 功能 ================== */
  54. void ISP_IAP_disable(void)
  55. {
  56. ISP_CONTR = ISP_CONTR & 0x7f; /* ISPEN = 0 */
  57. ISP_TRIG = 0x00;
  58. EA   =   1;   /* 開(kāi)中斷 */
  59. }
  60. /* ================ 公用的觸發(fā)代碼 ==================== */
  61. void ISPgoon(void)
  62. {
  63. ISP_IAP_enable();   /* 打開(kāi) ISP,IAP 功能 */
  64. ISP_TRIG = 0x46;  /* 觸發(fā)ISP_IAP命令字節(jié)1 */
  65. ISP_TRIG = 0xb9;  /* 觸發(fā)ISP_IAP命令字節(jié)2 */
  66. _nop_();
  67. }
  68. /* ==================== 字節(jié)讀 ======================== */
  69. unsigned char byte_read(unsigned int byte_addr)
  70. {
  71. EA = 0;
  72. ISP_ADDRH = (unsigned char)(byte_addr >> 8);/* 地址賦值 */
  73. ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
  74. ISP_CMD   = ISP_CMD & 0xf8;   /* 清除低3位  */
  75. ISP_CMD   = ISP_CMD | RdCommand; /* 寫(xiě)入讀命令 */
  76. ISPgoon();       /* 觸發(fā)執(zhí)行  */
  77. ISP_IAP_disable();    /* 關(guān)閉ISP,IAP功能 */
  78. EA  = 1;
  79. return (ISP_DATA);    /* 返回讀到的數(shù)據(jù) */
  80. }
  81. /* ================== 扇區(qū)擦除 ======================== */
  82. void SectorErase(unsigned int sector_addr)
  83. {
  84. unsigned int iSectorAddr;
  85. iSectorAddr = (sector_addr & 0xfe00); /* 取扇區(qū)地址 */
  86. ISP_ADDRH = (unsigned char)(iSectorAddr >> 8);
  87. ISP_ADDRL = 0x00;
  88. ISP_CMD = ISP_CMD & 0xf8;   /* 清空低3位  */
  89. ISP_CMD = ISP_CMD | EraseCommand; /* 擦除命令3  */
  90. ISPgoon();       /* 觸發(fā)執(zhí)行  */
  91. ISP_IAP_disable();    /* 關(guān)閉ISP,IAP功能 */
  92. }
  93. /* ==================== 字節(jié)寫(xiě) ======================== */
  94. void byte_write(unsigned int byte_addr, unsigned char original_data)
  95. {
  96. EA  = 0;
  97. ISP_ADDRH = (unsigned char)(byte_addr >> 8);  /* 取地址  */
  98. ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
  99. ISP_CMD  = ISP_CMD & 0xf8;    /* 清低3位 */
  100. ISP_CMD  = ISP_CMD | PrgCommand;  /* 寫(xiě)命令2 */
  101. ISP_DATA = original_data;   /* 寫(xiě)入數(shù)據(jù)準(zhǔn)備 */
  102. ISPgoon();       /* 觸發(fā)執(zhí)行  */
  103. ISP_IAP_disable();     /* 關(guān)閉IAP功能 */
  104. EA =1;
  105. }
  106. void write_eeprom()                           //內(nèi)部eeprom寫(xiě)函數(shù)
  107. {
  108. SectorErase(0x2000);                   //清空
  109. SectorErase(0x2c00);
  110. SectorErase(0x2e00);
  111. byte_write(0x2c00,num1);       
  112. byte_write(0x2c01,num2);                          
  113. byte_write(0x2060,0x01);
  114. }
  115. /******************把數(shù)據(jù)從單片機(jī)內(nèi)部eeprom中讀出來(lái)*****************/
  116. void read_eeprom()                                                                                                                                  
  117. {
  118. num1=byte_read(0x2c00);
  119. num2=byte_read(0x2c01);
  120. a_a=byte_read(0x2060);         
  121. }
  122. /**************開(kāi)機(jī)自檢eeprom初始化*****************/
  123. void init_eeprom()
  124. {
  125. a_a=byte_read(0x2060);
  126. if(a_a!=1)                //新的單片機(jī)初始單片機(jī)內(nèi)問(wèn)eeprom
  127. {
  128.   a_a=1;
  129.   write_eeprom();           //保存數(shù)據(jù)
  130. }       
  131. }

  132. //*****************I2C函數(shù)設(shè)置**********************//
  133. /*****************************************************
  134. 函數(shù)功能:將DS18B20傳感器初始化,讀取應(yīng)答信號(hào)
  135. 出口參數(shù):flag
  136. ***************************************************/
  137. bit Init_DS18B20(void)       
  138. {
  139. bit flag;         //儲(chǔ)存DS18B20是否存在的標(biāo)志,flag=0,表示存在;flag=1,表示不存在
  140. DQ = 1;           //先將數(shù)據(jù)線拉高
  141. for(time0=0;time0<2;time0++);//略微延時(shí)約6微秒
  142. DQ = 0;           //再將數(shù)據(jù)線從高拉低,要求保持480~960us
  143. for(time0=0;time0<200;time0++)  //略微延時(shí)約600微秒
  144.      ;         //以向DS18B20發(fā)出一持續(xù)480~960us的低電平復(fù)位脈沖
  145. DQ = 1;           //釋放數(shù)據(jù)線(將數(shù)據(jù)線拉高)
  146.   for(time0=0;time0<10;time0++)
  147.      ;  //延時(shí)約30us(釋放總線后需等待15~60us讓DS18B20輸出存在脈沖)
  148. flag=DQ;          //讓單片機(jī)檢測(cè)是否輸出了存在脈沖(DQ=0表示存在)      
  149. for(time0=0;time0<200;time0++)  //延時(shí)足夠長(zhǎng)時(shí)間,等待存在脈沖輸出完畢
  150.       ;
  151. return (flag);    //返回檢測(cè)成功標(biāo)志
  152. }
  153. /*****************************************************
  154. 函數(shù)功能:從DS18B20讀取一個(gè)字節(jié)數(shù)據(jù)
  155. 出口參數(shù):dat
  156. ***************************************************/
  157. unsigned char ReadOneChar(void)
  158. {
  159. unsigned char i=0;       
  160. unsigned char dat;  //儲(chǔ)存讀出的一個(gè)字節(jié)數(shù)據(jù)
  161. for (i=0;i<8;i++)
  162. {                  
  163.   DQ =1;       // 先將數(shù)據(jù)線拉高
  164.   _nop_();            //等待一個(gè)機(jī)器周期         
  165.   DQ = 0;      //單片機(jī)從DS18B20讀書(shū)據(jù)時(shí),將數(shù)據(jù)線從高拉低即啟動(dòng)讀時(shí)序
  166.   dat>>=1;
  167.   _nop_();     //等待一個(gè)機(jī)器周期                  
  168.   DQ = 1;     //將數(shù)據(jù)線"人為"拉高,為單片機(jī)檢測(cè)DS18B20的輸出電平作準(zhǔn)備
  169.   for(time0=0;time0<2;time0++);      //延時(shí)約6us,使主機(jī)在15us內(nèi)采樣
  170.   if(DQ==1)
  171.   dat|=0x80;  //如果讀到的數(shù)據(jù)是1,則將1存入dat
  172.   else
  173.   dat|=0x00;//如果讀到的數(shù)據(jù)是0,則將0存入dat
  174.   //將單片機(jī)檢測(cè)到的電平信號(hào)DQ存入r[i]       
  175.   for(time0=0;time0<8;time0++);              //延時(shí)3us,兩個(gè)讀時(shí)序之間必須有大于1us的恢復(fù)期       
  176. }                            
  177. return(dat);    //返回讀出的十進(jìn)制數(shù)據(jù)
  178. }
  179. /*****************************************************
  180. 函數(shù)功能:向DS18B20寫(xiě)入一個(gè)字節(jié)數(shù)據(jù)
  181. 入口參數(shù):dat
  182. ***************************************************/  
  183. WriteOneChar(unsigned char dat)
  184. {
  185. unsigned char i=0;
  186. for (i=0; i<8; i++)
  187. {
  188.   DQ =1;         // 先將數(shù)據(jù)線拉高
  189.   _nop_();             //等待一個(gè)機(jī)器周期         
  190.   DQ=0;          //將數(shù)據(jù)線從高拉低時(shí)即啟動(dòng)寫(xiě)時(shí)序      
  191.   DQ=dat&0x01;   //利用與運(yùn)算取出要寫(xiě)的某位二進(jìn)制數(shù)據(jù),
  192.                        //并將其送到數(shù)據(jù)線上等待DS18B20采樣       
  193.   for(time0=0;time0<10;time0++);//延時(shí)約30us,DS18B20在拉低后的約15~60us期間從數(shù)據(jù)線上采樣
  194.   DQ=1;          //釋放數(shù)據(jù)線                    
  195.   for(time0=0;time0<1;time0++);//延時(shí)3us,兩個(gè)寫(xiě)時(shí)序間至少需要1us的恢復(fù)期
  196.   dat>>=1;       //將dat中的各二進(jìn)制位數(shù)據(jù)右移1位
  197. }
  198. for(time0=0;time0<4;time0++); //稍作延時(shí),給硬件一點(diǎn)反應(yīng)時(shí)間
  199. }


  200. //液晶函數(shù)設(shè)置************************************/
  201. /*****************************************************
  202. 函數(shù)功能:延時(shí)1ms
  203. (3j+2)*i=(3×33+2)×10=1010(微秒),可以認(rèn)為是1毫秒
  204. ***************************************************/
  205. void delay1ms()
  206. {
  207.    unsigned char i,j;       
  208.          for(i=0;i<10;i++)
  209.           for(j=0;j<33;j++)
  210.            ;                 
  211. }
  212. /*****************************************************
  213. 函數(shù)功能:延時(shí)若干毫秒
  214. 入口參數(shù):n
  215. ***************************************************/
  216. void delay(unsigned char n)
  217. {
  218.    unsigned char i;
  219.         for(i=0;i<n;i++)
  220.            delay1ms();
  221. }
  222. /*****************************************************
  223. 函數(shù)功能:判斷液晶模塊的忙碌狀態(tài)
  224. 返回值:result。result=1,忙碌;result=0,不忙
  225. ***************************************************/
  226. unsigned char BusyTest(void)
  227.   {
  228.     bit result;
  229.         RS=0;       //根據(jù)規(guī)定,RS為低電平,RW為高電平時(shí),可以讀狀態(tài)
  230.     RW=1;
  231.     E=1;        //E=1,才允許讀寫(xiě)
  232.     _nop_();   //空操作
  233.     _nop_();
  234.     _nop_();
  235.     _nop_();   //空操作四個(gè)機(jī)器周期,給硬件反應(yīng)時(shí)間       
  236.     result=BF;  //將忙碌標(biāo)志電平賦給result
  237.    E=0;         //將E恢復(fù)低電平
  238.     return result;
  239.   }
  240. /*****************************************************
  241. 函數(shù)功能:將模式設(shè)置指令或顯示地址寫(xiě)入液晶模塊
  242. 入口參數(shù):dictate
  243. ***************************************************/
  244. void WriteInstruction (unsigned char dictate)
  245. {   
  246.     while(BusyTest()==1); //如果忙就等待
  247.          RS=0;                  //根據(jù)規(guī)定,RS和R/W同時(shí)為低電平時(shí),可以寫(xiě)入指令
  248.          RW=0;   
  249.          E=0;                   //E置低電平(根據(jù)表8-6,寫(xiě)指令時(shí),E為高脈沖,
  250.                              // 就是讓E從0到1發(fā)生正跳變,所以應(yīng)先置"0"
  251.          _nop_();
  252.          _nop_();             //空操作兩個(gè)機(jī)器周期,給硬件反應(yīng)時(shí)間
  253.          P0=dictate;            //將數(shù)據(jù)送入P0口,即寫(xiě)入指令或地址
  254.          _nop_();
  255.          _nop_();
  256.          _nop_();
  257.          _nop_();               //空操作四個(gè)機(jī)器周期,給硬件反應(yīng)時(shí)間
  258.          E=1;                   //E置高電平
  259.          _nop_();
  260.          _nop_();
  261.          _nop_();
  262.          _nop_();               //空操作四個(gè)機(jī)器周期,給硬件反應(yīng)時(shí)間
  263.           E=0;                  //當(dāng)E由高電平跳變成低電平時(shí),液晶模塊開(kāi)始執(zhí)行命令
  264. }
  265. /*****************************************************
  266. 函數(shù)功能:指定字符顯示的實(shí)際地址
  267. 入口參數(shù):x
  268. ***************************************************/
  269. void WriteAddress(unsigned char x)
  270. {
  271.      WriteInstruction(x|0x80); //顯示位置的確定方法規(guī)定為"80H+地址碼x"
  272. }
  273. /*****************************************************
  274. 函數(shù)功能:將數(shù)據(jù)(字符的標(biāo)準(zhǔn)ASCII碼)寫(xiě)入液晶模塊
  275. 入口參數(shù):y(為字符常量)
  276. ***************************************************/
  277. void WriteData(unsigned char y)
  278. {
  279.     while(BusyTest()==1);  
  280.           RS=1;           //RS為高電平,RW為低電平時(shí),可以寫(xiě)入數(shù)據(jù)
  281.           RW=0;
  282.           E=0;            //E置低電平(根據(jù)表8-6,寫(xiě)指令時(shí),E為高脈沖,
  283.                        // 就是讓E從0到1發(fā)生正跳變,所以應(yīng)先置"0"
  284.           P0=y;           //將數(shù)據(jù)送入P0口,即將數(shù)據(jù)寫(xiě)入液晶模塊
  285.           _nop_();
  286.           _nop_();
  287.           _nop_();
  288.      _nop_();       //空操作四個(gè)機(jī)器周期,給硬件反應(yīng)時(shí)間
  289.           E=1;          //E置高電平
  290.           _nop_();
  291.           _nop_();
  292.           _nop_();
  293.          _nop_();        //空操作四個(gè)機(jī)器周期,給硬件反應(yīng)時(shí)間
  294.          E=0;            //當(dāng)E由高電平跳變成低電平時(shí),液晶模塊開(kāi)始執(zhí)行命令
  295. }
  296. /*****************************************************
  297. 函數(shù)功能:對(duì)LCD的顯示模式進(jìn)行初始化設(shè)置
  298. ***************************************************/
  299. void LcdInitiate(void)
  300. {
  301. delay(15);             //延時(shí)15ms,首次寫(xiě)指令時(shí)應(yīng)給LCD一段較長(zhǎng)的反應(yīng)時(shí)間
  302. WriteInstruction(0x38);  //顯示模式設(shè)置:16×2顯示,5×7點(diǎn)陣,8位數(shù)據(jù)接口
  303. delay(5);               //延時(shí)5ms ,給硬件一點(diǎn)反應(yīng)時(shí)間
  304. WriteInstruction(0x38);
  305. delay(5);
  306. WriteInstruction(0x38); //連續(xù)三次,確保初始化成功
  307. delay(5);
  308. WriteInstruction(0x0c);  //顯示模式設(shè)置:顯示開(kāi),無(wú)光標(biāo),光標(biāo)不閃爍
  309. delay(5);
  310. WriteInstruction(0x06);  //顯示模式設(shè)置:光標(biāo)右移,字符不移
  311. delay(5);
  312. WriteInstruction(0x01);  //清屏幕指令,將以前的顯示內(nèi)容清除
  313. delay(5);
  314. WriteAddress(0);//從第一行開(kāi)始顯示
  315. WriteData('J');  //將萬(wàn)位數(shù)字的字符常量寫(xiě)入LCD
  316. WriteData('L');  //將萬(wàn)位數(shù)字的字符常量寫(xiě)入LCD
  317. WriteData(':');  //將萬(wàn)位數(shù)字的字符常量寫(xiě)入LCD

  318. WriteAddress(7);//從第一行開(kāi)始顯示
  319. WriteData('C');  //將萬(wàn)位數(shù)字的字符常量寫(xiě)入LCD
  320. WriteData('M');  //將萬(wàn)位數(shù)字的字符常量寫(xiě)入LCD

  321. WriteAddress(0x40);
  322. WriteData('H');
  323. WriteData(':');
  324. WriteAddress(0x40+5);
  325. WriteData('C');
  326. WriteData('M');

  327. WriteAddress(0x40+9);
  328. WriteData('L');
  329. WriteData(':');
  330. WriteAddress(0x40+14);
  331. WriteData('C');
  332. WriteData('M');

  333. WriteAddress(15);
  334. WriteData(0xdf);
  335. }
  336. //假如溫度25攝氏度時(shí),聲速位346m/s
  337. //時(shí)鐘周期為T(mén)0=1/11.0592M,則機(jī)器周期為1/11.0592*12us=1.08us,定時(shí)器計(jì)時(shí)為time0(定時(shí)的數(shù)量就是時(shí)鐘周期數(shù))
  338. //實(shí)際時(shí)間t=time0*1.08
  339. //距離S=vt/2=v*time0*1.08/2/1000000=算出來(lái)的值是米
  340. void Conut(void)
  341. {
  342. float vv;
  343. time=TH0*256+TL0;                //TH0左移8位后與TL0相加
  344. TH0=0;
  345. TL0=0;
  346. vv=(331.5+0.607*TN);//聲速VV和聲速TN的關(guān)系
  347. S=((time*vv*1/200)/10); //注意除以10相當(dāng)于算出來(lái)的值單位毫米,*1.08是因?yàn)榫д?1.0592,如果是12MHZ就是*1       
  348. /*time=TH0*256+TL0;                //TH0左移8位后與TL0相加
  349. TH0=0;
  350. TL0=0;
  351. S=((time*1.87)/10); //注意除以10相當(dāng)于算出來(lái)的值單位毫米 */
  352. if((S>=4000)||(flag==1)) //超出測(cè)量范圍(4米)
  353. {         
  354.    flag=0;
  355.    qian=0;
  356.    bai=0;
  357.    shi=0;
  358.    ge=0;
  359.    delay(10);
  360. }
  361. else
  362. {
  363.   qian=S/1000;
  364.   bai=S%1000/100;
  365.   shi=S%1000%100/10;
  366.   ge=S%1000%10 %10;
  367. }
  368. }

  369. /*****************************************************
  370. 函數(shù)功能:顯示溫度的整數(shù)部分
  371. 入口參數(shù):x
  372. ***************************************************/
  373. void display_temp1(unsigned char x)
  374. {
  375. unsigned char j,k,l;     //j,k,l分別儲(chǔ)存溫度的百位、十位和個(gè)位
  376. j=x/100;              //取百位
  377. k=(x%100)/10;    //取十位
  378. l=x%10;             //取個(gè)位  
  379. WriteAddress(11);    //寫(xiě)顯示地址,將在第2行第7列開(kāi)始顯示
  380. //WriteData(digit[j]);    //將百位數(shù)字的字符常量寫(xiě)入LCD
  381. WriteData(digit[k]);    //將十位數(shù)字的字符常量寫(xiě)入LCD
  382. WriteData(digit[l]);    //將個(gè)位數(shù)字的字符常量寫(xiě)入LCD
  383. delay(50);         //延時(shí)1ms給硬件一點(diǎn)反應(yīng)時(shí)間     
  384. }
  385. /*****************************************************
  386. 函數(shù)功能:顯示溫度的小數(shù)數(shù)部分
  387. 入口參數(shù):x
  388. ***************************************************/
  389. void display_temp2(unsigned char x)
  390. {
  391. WriteAddress(14);      //寫(xiě)顯示地址,將在第2行第11列開(kāi)始顯示
  392. WriteData(digit[x]);     //將小數(shù)部分的第一位數(shù)字字符常量寫(xiě)入LCD
  393. delay(50);          //延時(shí)1ms給硬件一點(diǎn)反應(yīng)時(shí)間
  394. }
  395. /*****************************************************
  396. 函數(shù)功能:做好讀溫度的準(zhǔn)備
  397. ***************************************************/
  398. void ReadyReadTemp(void)
  399. {
  400. Init_DS18B20();     //將DS18B20初始化
  401. WriteOneChar(0xCC); // 跳過(guò)讀序號(hào)列號(hào)的操作
  402. WriteOneChar(0x44); // 啟動(dòng)溫度轉(zhuǎn)換          
  403. for(time=0;time<150;time++)
  404. ;         //溫度轉(zhuǎn)換需要一點(diǎn)時(shí)間
  405. Init_DS18B20();     //將DS18B20初始化
  406. WriteOneChar(0xCC); //跳過(guò)讀序號(hào)列號(hào)的操作
  407. WriteOneChar(0xBE); //讀取溫度寄存器,前兩個(gè)分別是溫度的低位和高位       
  408. }

  409. void alarming()//蜂鳴器報(bào)警子函數(shù)
  410. {
  411. alarm=0;
  412. LED=0;
  413. delay(50);
  414. alarm=1;
  415. LED=1;
  416. delay(100);
  417. }
  418. /***************按鍵設(shè)置****************************/
  419. void key_shezhi()
  420. {
  421. if(key2==0)//如果上下限參數(shù)調(diào)整按鍵按下
  422. {
  423.    delay(30);
  424.    if(key2==0)
  425.    {
  426.     menu++;//設(shè)置頁(yè)面調(diào)整
  427.     if(menu>2)//如果設(shè)置完下限值后,液晶回歸正常顯示
  428.     {
  429.      menu=0;
  430.      LcdInitiate();//更新初始化顯示
  431.          delay(20);//適當(dāng)延時(shí)
  432.     }
  433.    }
  434.    while(!key2);
  435. }
  436. if(menu==0)
  437. {
  438.   ET0=1;  //打開(kāi)定時(shí)中斷
  439.   ET1=1;
  440.   WriteAddress(3);
  441.   WriteData(digit[qian]);//更新顯示實(shí)時(shí)測(cè)距的距離  
  442.   delay(20);
  443.   WriteData(digit[bai]);//更新顯示實(shí)時(shí)測(cè)距的距離  
  444.   delay(20);
  445.   WriteData(digit[shi]);//更新顯示實(shí)時(shí)測(cè)距的距離  
  446.   delay(20);
  447.   //WriteData('.');//增加一個(gè)小數(shù)點(diǎn),用于毫米和厘米的切換指示  
  448.   //delay(20);
  449.   //WriteData(digit[ge]); //更新顯示實(shí)時(shí)測(cè)距的距離
  450.   //delay(20);
  451.   ET0=0;  //關(guān)閉定時(shí)中斷,執(zhí)行溫度讀取
  452.   ET1=0;
  453.   ReadyReadTemp();     //讀溫度準(zhǔn)備
  454.   TL=ReadOneChar();    //先讀的是溫度值低位
  455.   TH=ReadOneChar();    //接著讀的是溫度值高位
  456.   TN=TH*16+TL/16;      //實(shí)際溫度值=(TH*256+TL)/16,即:TH*16+TL/16
  457.                                           //這樣得出的是溫度的整數(shù)部分,小數(shù)部分被丟棄了
  458.   TD=(TL%16)*10/16;    //計(jì)算溫度的小數(shù)部分,將余數(shù)乘以10再除以16取整,
  459.                                           //這樣得到的是溫度小數(shù)部分的第一位數(shù)字(保留1位小數(shù))

  460.   if((TN==85)&&(WD_temp==0))//18B20芯片開(kāi)電首次讀取的溫度是85,本程序避開(kāi)85的問(wèn)題
  461.   {
  462.     TN=0;
  463.   }
  464.   else if(TN!=85)
  465.   {
  466.    WD_temp=1;//開(kāi)電首次85避開(kāi)
  467.   }
  468.   ET0=1;  //溫度處理完后打開(kāi)定時(shí)中斷
  469.   ET1=1;
  470.   display_temp1(TN);    //顯示溫度的整數(shù)部分
  471.   display_temp2(TD);    //顯示溫度的小數(shù)部分
  472.   WriteAddress(13);
  473.   WriteData('.');

  474.   H_bai=num1/100;//更新顯示調(diào)整后的上限值
  475.   H_shi=num1%100/10;//更新顯示調(diào)整后的上限值
  476.   H_ge=num1%100%10;        //更新顯示調(diào)整后的上限值
  477.   WriteAddress(0x40+2);//更新顯示調(diào)整后的上限值
  478.   WriteData(digit[H_bai]);//更新顯示調(diào)整后的上限值
  479.   WriteData(digit[H_shi]);//更新顯示調(diào)整后的上限值
  480.   WriteData(digit[H_ge]);//更新顯示調(diào)整后的上限值

  481.   L_bai=num2/100; //更新顯示調(diào)整后的下限值
  482.   L_shi=num2%100/10;//更新顯示調(diào)整后的下限值
  483.   L_ge=num2%100%10;//更新顯示調(diào)整后的下限值
  484.   WriteAddress(0x40+11);//更新顯示調(diào)整后的下限值
  485.   WriteData(digit[L_bai]); //更新顯示調(diào)整后的下限值
  486.   WriteData(digit[L_shi]);//更新顯示調(diào)整后的下限值
  487.   WriteData(digit[L_ge]); //更新顯示調(diào)整后的下限值

  488.   if(S>=temp1)//報(bào)警設(shè)置
  489.   {
  490.    alarming();//如果距離大于上限值報(bào)警
  491.   }
  492.   else if(S<temp2)
  493.   {
  494.    alarming();//如果距離小于下限值報(bào)警
  495.   }
  496.   else
  497.   {
  498.    alarm=1;//關(guān)閉報(bào)警
  499.   }
  500. }
  501. if(menu==1)//切換液晶上限設(shè)置
  502. {
  503.   ET0=0;//把定時(shí)中斷暫時(shí)關(guān)閉
  504.   ET1=0;
  505.   if(key1==0)//加按鍵
  506.   {
  507.     delay(30);
  508.         if(key1==0)
  509.         {
  510.      num1++;
  511.      if(num1==400)//上限4米
  512.      {
  513.           num1=0;
  514.      }
  515.      if(num1<num2)//調(diào)整上限值得時(shí)候,上限值不能小于下限值
  516.      {
  517.       num1=num2;//否則等于下限值
  518.      }
  519.         }
  520.         while(!key1);//等待按鍵釋放
  521.   }
  522.   if(key3==0)//減按鍵
  523.   {
  524.     delay(30);
  525.         if(key3==0)
  526.         {
  527.      if((num1>0)&&(num1>num2))//如果同時(shí)滿(mǎn)足num1大于零和上限值大于下限值,可以減減
  528.      {
  529.       num1--;
  530.      }         
  531.         }
  532.         while(!key3);//等待按鍵釋放
  533.   }
  534.   write_eeprom();
  535.   delay(2);
  536.   delay(2);
  537.   H_bai=num1/100;//上限值轉(zhuǎn)換用于液晶顯示
  538.   H_shi=num1%100/10;//上限值轉(zhuǎn)換用于液晶顯示
  539.   H_ge=num1%100%10;//上限值轉(zhuǎn)換用于液晶顯示
  540.   
  541.   delay(20);//延時(shí)消除光標(biāo)重影
  542.   WriteAddress(0x40+2);//定位位置用于顯示更新上限值
  543.   WriteData(digit[H_bai]);//上限值更新顯示
  544.   WriteData(digit[H_shi]);//上限值更新顯示
  545.   WriteData(digit[H_ge]);//上限值更新顯示

  546.   WriteAddress(0x40+4);//移到上限值得個(gè)位數(shù),用于光標(biāo)顯示
  547.   WriteInstruction(0x0e);//光標(biāo)顯示,不閃爍
  548. }
  549. if(menu==2)//下限值調(diào)整設(shè)置
  550. {
  551.   ET0=0;
  552.   ET1=0;
  553.   if(key1==0)
  554.   {       
  555.     delay(30);
  556.         if(key1==0)
  557.         {
  558.      if(num2<num1)
  559.      {
  560.           num2++;
  561.      }
  562.         }
  563.         while(!key1);
  564.   }
  565.   if(key3==0)
  566.   {       
  567.     delay(30);
  568.         if(key3==0)
  569.         {
  570.      if((num1>=num2)&&(num2>0))
  571.      {
  572.           num2--;
  573.      }
  574.         }
  575.         while(!key3);
  576.        
  577.   }
  578.   write_eeprom();
  579.   delay(2);
  580.   L_bai=num2/100;
  581.   L_shi=num2%100/10;
  582.   L_ge=num2%100%10;
  583.   delay(20);//延時(shí)消除光標(biāo)重影
  584.   WriteAddress(0x40+11);
  585.   WriteData(digit[L_bai]);
  586.   WriteData(digit[L_shi]);
  587.   WriteData(digit[L_ge]);

  588.   WriteAddress(0x40+13);//移到個(gè)位,光標(biāo)閃爍
  589.   WriteInstruction(0x0e);
  590. }  
  591. }
  592. void main(void)   // 主程序
  593. {
  594. LED=1;
  595. key1=1;//按鍵初始化
  596. key2=1;//按鍵初始化
  597. key3=1;//按鍵初始化
  598. TMOD=0x11;                                                //設(shè)置定時(shí)器0和1工作方式為1(0001 0001)
  599. TH0=0;                                                     //裝初值
  600. TL0=0;                                                        //裝初值
  601. TH1=(65536-50000)/256;
  602. TL1=(65536-50000)%256;
  603. EA=1;                                                        //開(kāi)總中斷
  604. ET0=1;                                                          //開(kāi)定時(shí)器0中斷
  605. ET1=1;                                                          //開(kāi)定時(shí)器1中斷
  606. TR1=1;                                                         //啟動(dòng)定時(shí)器1
  607. TX=0;
  608. RX=0;
  609. LcdInitiate();         //調(diào)用LCD初始化函數(shù)  
  610. delay(10);             //延時(shí)10ms,給硬件一點(diǎn)反應(yīng)時(shí)間
  611. init_eeprom();                                  //初始化eeprom
  612. delay(10);
  613. read_eeprom();                                  //讀取eeprom數(shù)據(jù)
  614. delay(10);
  615. while(1)         //程序循環(huán)
  616. {
  617.   key_shezhi();        //循環(huán)調(diào)用按鍵設(shè)置函數(shù)
  618.   temp1=num1*10;//由于num1單位是厘米,S單位是毫米,要*10轉(zhuǎn)換成統(tǒng)一單位進(jìn)行比較,用于報(bào)警設(shè)置
  619.   temp2=num2*10;
  620. }
  621. }
  622. void zd0() interrupt 1                         //T0中斷用來(lái)計(jì)數(shù)器溢出,超過(guò)測(cè)距范圍
  623. {
  624. flag=1;                                                //中斷溢出標(biāo)志
  625. }
  626. void zd3() interrupt 3                                          //T1中斷
  627. {
  628. TH1=(65536-50000)/256;        //重新裝初值高8位  約0.05s
  629. TL1=(65536-50000)%256;//重新裝初值低8位
  630. timer++;//
  631. if(timer>=5)//中斷5次約0.25s
  632. {
  633.   TR1=0;                         //關(guān)閉定時(shí)器1
  634.   TH1=(65536-50000)/256;
  635.   TL1=(65536-50000)%256;
  636.   timer=0;
  637.   TX=1;//先吧TX拉高//給個(gè)高位脈沖
  638.   _nop_();//延時(shí)
  639.   _nop_();//延時(shí)
  640.   _nop_();//延時(shí)
  641.   _nop_();//延時(shí)
  642.   _nop_();//延時(shí)
  643.   _nop_();//延時(shí)
  644.   _nop_();//延時(shí)
  645.   _nop_();//延時(shí)
  646.   _nop_();//延時(shí)
  647.   _nop_();//延時(shí)
  648.   TX=0;        //拉低
  649.   while(!RX);                 //當(dāng)RX為零時(shí)等待
  650.   TR0=1;                          //啟動(dòng)定時(shí)器0,開(kāi)啟計(jì)數(shù)
  651.   while(RX);                         //當(dāng)RX為1計(jì)數(shù)并等待
  652.   TR0=0;                         //關(guān)閉定時(shí)器0  關(guān)閉計(jì)數(shù)//計(jì)時(shí)完畢
  653.   Conut();                        //調(diào)用距離計(jì)算函數(shù),計(jì)算距離
  654.   TR1=1;                           //啟動(dòng)定時(shí)器1
  655. }
  656. }


復(fù)制代碼

所有資料51hei提供下載:
211 超聲波測(cè)距仿真(溫度補(bǔ)償).zip (420.11 KB, 下載次數(shù): 74)


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:364667 發(fā)表于 2018-7-18 18:23 | 只看該作者
大佬你的Proteus版本多少 我下了你的仿真文件結(jié)果沒(méi)有Proteus打開(kāi)這一方式 我的是8.6版本的
回復(fù)

使用道具 舉報(bào)

板凳
ID:89286 發(fā)表于 2018-7-25 07:49 | 只看該作者
thanks for sharing
回復(fù)

使用道具 舉報(bào)

地板
ID:545457 發(fā)表于 2020-5-25 16:03 | 只看該作者
dragonraja 發(fā)表于 2018-7-18 18:23
大佬你的Proteus版本多少 我下了你的仿真文件結(jié)果沒(méi)有Proteus打開(kāi)這一方式 我的是8.6版本的

樓主分享真心不錯(cuò),但同樣問(wèn)題打不開(kāi)Proteus文件
回復(fù)

使用道具 舉報(bào)

5#
ID:545457 發(fā)表于 2020-5-25 16:23 | 只看該作者
樓主資源非常好用,Proteus  7.8版本可以打開(kāi)  ,現(xiàn)象明顯
回復(fù)

使用道具 舉報(bào)

6#
ID:545457 發(fā)表于 2020-5-25 16:25 | 只看該作者
補(bǔ)充:樓主資料包里還有文檔資料,可供文檔等參考
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 中文字幕精品一区二区三区在线 | 日韩在线资源 | 欧美激情视频一区二区三区在线播放 | 久久成人一区 | www.国产| 亚洲欧美在线一区 | 国产精品性做久久久久久 | 国产一区在线看 | av国产精品 | 日韩av网址在线观看 | 日韩三级视频 | 涩爱av一区二区三区 | 欧美精品网站 | 国产欧美一区二区精品久导航 | 一区二区三区国产在线观看 | 国产精品免费一区二区三区 | 一二区成人影院电影网 | 天天干天天色 | 成人免费一区二区三区视频网站 | av中文天堂 | 国产一区二区三区在线免费观看 | 日韩a视频 | 精品一区电影 | 中文字幕免费中文 | 久久精品亚洲成在人线av网址 | 免费成人高清 | 亚洲高清在线观看 | 狠狠综合网 | 91文字幕巨乱亚洲香蕉 | 国产一区二区在线播放 | 免费观看日韩av | 成人高潮片免费视频欧美 | 成人免费看黄网站在线观看 | 1204国产成人精品视频 | 久久久久免费精品国产小说色大师 | 国产一区久久久 | 国产精品精品视频一区二区三区 | 麻豆va| 亚洲成人av在线 | 精品无码久久久久久国产 | 精品国产乱码久久久久久蜜柚 |