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

標題: 超聲波測距仿真(溫度補償)按鍵代指超聲波測距 [打印本頁]

作者: lxmlcr    時間: 2018-6-6 10:59
標題: 超聲波測距仿真(溫度補償)按鍵代指超聲波測距
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)


單片機源程序如下:
  1. #include <reg52.h>     //包括一個52標準內核的頭文件
  2. #include<intrins.h>  //包含_nop_()函數定義的頭文件
  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的等待時間

  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;//參數加
  20. sbit key3=P1^2;//參數減
  21. sbit key2=P1^0;//參數設置按鍵
  22. sbit DQ=P3^3;
  23. sbit LED=P2^7;
  24. sbit alarm=P3^4;//蜂鳴器管腳定義

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

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

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

  45. /* ================ 打開 ISP,IAP 功能 ================= */
  46. void ISP_IAP_enable(void)
  47. {
  48. EA = 0;       /* 關中斷   */
  49. ISP_CONTR = ISP_CONTR & 0x18;       /* 0001,1000 */
  50. ISP_CONTR = ISP_CONTR | WaitTime; /* 寫入硬件延時 */
  51. ISP_CONTR = ISP_CONTR | 0x80;       /* ISPEN=1  */
  52. }
  53. /* =============== 關閉 ISP,IAP 功能 ================== */
  54. void ISP_IAP_disable(void)
  55. {
  56. ISP_CONTR = ISP_CONTR & 0x7f; /* ISPEN = 0 */
  57. ISP_TRIG = 0x00;
  58. EA   =   1;   /* 開中斷 */
  59. }
  60. /* ================ 公用的觸發代碼 ==================== */
  61. void ISPgoon(void)
  62. {
  63. ISP_IAP_enable();   /* 打開 ISP,IAP 功能 */
  64. ISP_TRIG = 0x46;  /* 觸發ISP_IAP命令字節1 */
  65. ISP_TRIG = 0xb9;  /* 觸發ISP_IAP命令字節2 */
  66. _nop_();
  67. }
  68. /* ==================== 字節讀 ======================== */
  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; /* 寫入讀命令 */
  76. ISPgoon();       /* 觸發執行  */
  77. ISP_IAP_disable();    /* 關閉ISP,IAP功能 */
  78. EA  = 1;
  79. return (ISP_DATA);    /* 返回讀到的數據 */
  80. }
  81. /* ================== 扇區擦除 ======================== */
  82. void SectorErase(unsigned int sector_addr)
  83. {
  84. unsigned int iSectorAddr;
  85. iSectorAddr = (sector_addr & 0xfe00); /* 取扇區地址 */
  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();       /* 觸發執行  */
  91. ISP_IAP_disable();    /* 關閉ISP,IAP功能 */
  92. }
  93. /* ==================== 字節寫 ======================== */
  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;  /* 寫命令2 */
  101. ISP_DATA = original_data;   /* 寫入數據準備 */
  102. ISPgoon();       /* 觸發執行  */
  103. ISP_IAP_disable();     /* 關閉IAP功能 */
  104. EA =1;
  105. }
  106. void write_eeprom()                           //內部eeprom寫函數
  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. /******************把數據從單片機內部eeprom中讀出來*****************/
  116. void read_eeprom()                                                                                                                                  
  117. {
  118. num1=byte_read(0x2c00);
  119. num2=byte_read(0x2c01);
  120. a_a=byte_read(0x2060);         
  121. }
  122. /**************開機自檢eeprom初始化*****************/
  123. void init_eeprom()
  124. {
  125. a_a=byte_read(0x2060);
  126. if(a_a!=1)                //新的單片機初始單片機內問eeprom
  127. {
  128.   a_a=1;
  129.   write_eeprom();           //保存數據
  130. }       
  131. }

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


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

  318. WriteAddress(7);//從第一行開始顯示
  319. WriteData('C');  //將萬位數字的字符常量寫入LCD
  320. WriteData('M');  //將萬位數字的字符常量寫入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攝氏度時,聲速位346m/s
  337. //時鐘周期為T0=1/11.0592M,則機器周期為1/11.0592*12us=1.08us,定時器計時為time0(定時的數量就是時鐘周期數)
  338. //實際時間t=time0*1.08
  339. //距離S=vt/2=v*time0*1.08/2/1000000=算出來的值是米
  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的關系
  347. S=((time*vv*1/200)/10); //注意除以10相當于算出來的值單位毫米,*1.08是因為晶振11.0592,如果是12MHZ就是*1       
  348. /*time=TH0*256+TL0;                //TH0左移8位后與TL0相加
  349. TH0=0;
  350. TL0=0;
  351. S=((time*1.87)/10); //注意除以10相當于算出來的值單位毫米 */
  352. if((S>=4000)||(flag==1)) //超出測量范圍(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. 函數功能:顯示溫度的整數部分
  371. 入口參數:x
  372. ***************************************************/
  373. void display_temp1(unsigned char x)
  374. {
  375. unsigned char j,k,l;     //j,k,l分別儲存溫度的百位、十位和個位
  376. j=x/100;              //取百位
  377. k=(x%100)/10;    //取十位
  378. l=x%10;             //取個位  
  379. WriteAddress(11);    //寫顯示地址,將在第2行第7列開始顯示
  380. //WriteData(digit[j]);    //將百位數字的字符常量寫入LCD
  381. WriteData(digit[k]);    //將十位數字的字符常量寫入LCD
  382. WriteData(digit[l]);    //將個位數字的字符常量寫入LCD
  383. delay(50);         //延時1ms給硬件一點反應時間     
  384. }
  385. /*****************************************************
  386. 函數功能:顯示溫度的小數數部分
  387. 入口參數:x
  388. ***************************************************/
  389. void display_temp2(unsigned char x)
  390. {
  391. WriteAddress(14);      //寫顯示地址,將在第2行第11列開始顯示
  392. WriteData(digit[x]);     //將小數部分的第一位數字字符常量寫入LCD
  393. delay(50);          //延時1ms給硬件一點反應時間
  394. }
  395. /*****************************************************
  396. 函數功能:做好讀溫度的準備
  397. ***************************************************/
  398. void ReadyReadTemp(void)
  399. {
  400. Init_DS18B20();     //將DS18B20初始化
  401. WriteOneChar(0xCC); // 跳過讀序號列號的操作
  402. WriteOneChar(0x44); // 啟動溫度轉換          
  403. for(time=0;time<150;time++)
  404. ;         //溫度轉換需要一點時間
  405. Init_DS18B20();     //將DS18B20初始化
  406. WriteOneChar(0xCC); //跳過讀序號列號的操作
  407. WriteOneChar(0xBE); //讀取溫度寄存器,前兩個分別是溫度的低位和高位       
  408. }

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

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

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

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

  488.   if(S>=temp1)//報警設置
  489.   {
  490.    alarming();//如果距離大于上限值報警
  491.   }
  492.   else if(S<temp2)
  493.   {
  494.    alarming();//如果距離小于下限值報警
  495.   }
  496.   else
  497.   {
  498.    alarm=1;//關閉報警
  499.   }
  500. }
  501. if(menu==1)//切換液晶上限設置
  502. {
  503.   ET0=0;//把定時中斷暫時關閉
  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)//調整上限值得時候,上限值不能小于下限值
  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))//如果同時滿足num1大于零和上限值大于下限值,可以減減
  528.      {
  529.       num1--;
  530.      }         
  531.         }
  532.         while(!key3);//等待按鍵釋放
  533.   }
  534.   write_eeprom();
  535.   delay(2);
  536.   delay(2);
  537.   H_bai=num1/100;//上限值轉換用于液晶顯示
  538.   H_shi=num1%100/10;//上限值轉換用于液晶顯示
  539.   H_ge=num1%100%10;//上限值轉換用于液晶顯示
  540.   
  541.   delay(20);//延時消除光標重影
  542.   WriteAddress(0x40+2);//定位位置用于顯示更新上限值
  543.   WriteData(digit[H_bai]);//上限值更新顯示
  544.   WriteData(digit[H_shi]);//上限值更新顯示
  545.   WriteData(digit[H_ge]);//上限值更新顯示

  546.   WriteAddress(0x40+4);//移到上限值得個位數,用于光標顯示
  547.   WriteInstruction(0x0e);//光標顯示,不閃爍
  548. }
  549. if(menu==2)//下限值調整設置
  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);//延時消除光標重影
  584.   WriteAddress(0x40+11);
  585.   WriteData(digit[L_bai]);
  586.   WriteData(digit[L_shi]);
  587.   WriteData(digit[L_ge]);

  588.   WriteAddress(0x40+13);//移到個位,光標閃爍
  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;                                                //設置定時器0和1工作方式為1(0001 0001)
  599. TH0=0;                                                     //裝初值
  600. TL0=0;                                                        //裝初值
  601. TH1=(65536-50000)/256;
  602. TL1=(65536-50000)%256;
  603. EA=1;                                                        //開總中斷
  604. ET0=1;                                                          //開定時器0中斷
  605. ET1=1;                                                          //開定時器1中斷
  606. TR1=1;                                                         //啟動定時器1
  607. TX=0;
  608. RX=0;
  609. LcdInitiate();         //調用LCD初始化函數  
  610. delay(10);             //延時10ms,給硬件一點反應時間
  611. init_eeprom();                                  //初始化eeprom
  612. delay(10);
  613. read_eeprom();                                  //讀取eeprom數據
  614. delay(10);
  615. while(1)         //程序循環
  616. {
  617.   key_shezhi();        //循環調用按鍵設置函數
  618.   temp1=num1*10;//由于num1單位是厘米,S單位是毫米,要*10轉換成統一單位進行比較,用于報警設置
  619.   temp2=num2*10;
  620. }
  621. }
  622. void zd0() interrupt 1                         //T0中斷用來計數器溢出,超過測距范圍
  623. {
  624. flag=1;                                                //中斷溢出標志
  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;                         //關閉定時器1
  634.   TH1=(65536-50000)/256;
  635.   TL1=(65536-50000)%256;
  636.   timer=0;
  637.   TX=1;//先吧TX拉高//給個高位脈沖
  638.   _nop_();//延時
  639.   _nop_();//延時
  640.   _nop_();//延時
  641.   _nop_();//延時
  642.   _nop_();//延時
  643.   _nop_();//延時
  644.   _nop_();//延時
  645.   _nop_();//延時
  646.   _nop_();//延時
  647.   _nop_();//延時
  648.   TX=0;        //拉低
  649.   while(!RX);                 //當RX為零時等待
  650.   TR0=1;                          //啟動定時器0,開啟計數
  651.   while(RX);                         //當RX為1計數并等待
  652.   TR0=0;                         //關閉定時器0  關閉計數//計時完畢
  653.   Conut();                        //調用距離計算函數,計算距離
  654.   TR1=1;                           //啟動定時器1
  655. }
  656. }


復制代碼

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



作者: dragonraja    時間: 2018-7-18 18:23
大佬你的Proteus版本多少 我下了你的仿真文件結果沒有Proteus打開這一方式 我的是8.6版本的
作者: faridzled    時間: 2018-7-25 07:49
thanks for sharing
作者: 玩卟欺    時間: 2020-5-25 16:03
dragonraja 發表于 2018-7-18 18:23
大佬你的Proteus版本多少 我下了你的仿真文件結果沒有Proteus打開這一方式 我的是8.6版本的

樓主分享真心不錯,但同樣問題打不開Proteus文件
作者: 玩卟欺    時間: 2020-5-25 16:23
樓主資源非常好用,Proteus  7.8版本可以打開  ,現象明顯
作者: 玩卟欺    時間: 2020-5-25 16:25
補充:樓主資料包里還有文檔資料,可供文檔等參考




歡迎光臨 (http://m.zg4o1577.cn/bbs/) Powered by Discuz! X3.1
主站蜘蛛池模板: 日韩少妇视频 | 久久久久久av | 欧美日韩综合 | 欧美日韩综合在线 | 国产又猛又黄又爽 | 97国产视频 | 黄色大片视频 | 在线日韩一区 | 国产精品成人国产乱一区 | 亚洲精品久 | 日本一级淫片 | 日本在线免费观看 | 久草福利资源 | 国产精品tv | 欧美日韩在线免费观看 | 日韩视频精品 | 久久精品小视频 | 亚洲欧美日韩国产 | 欧美日韩色 | 黄色片在线免费观看 | 精品毛片一区二区三区 | h片免费看 | 欧美日韩亚洲一区 | 亚洲高清视频在线观看 | 四虎wz| 国产一区欧美 | 色片网址 | 日日夜夜天天干 | 欧美激情第二页 | 亚洲视频二区 | 三级av在线| 国产在线不卡 | 欧美一级特黄视频 | 成人久久av | 国产黄色免费网站 | 欧美国产日韩视频 | 夜夜嗨av一区二区三区网页 | 黄色av网站在线观看 | av高清在线观看 | 加勒比综合 | 欧美不卡一区二区三区 |