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

QQ登錄

只需一步,快速開始

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

[原創(chuàng)]第八屆藍(lán)橋杯決賽:超聲波測(cè)距機(jī)源程序

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
本帖最后由 Amistad 于 2019-5-12 23:25 編輯

這次分享得是第八屆的題目源碼,我總結(jié)的一下第三屆到底九屆決賽考試考的器件,如下圖所示 ,大家可以看到板子上的lcd12864,1602,紅外,在這幾屆里面一次沒考,但是不代表以后不會(huì)考,參加比賽的同學(xué)還是要看一下這三個(gè)器件,下面給出本次題目,與主文件程序代碼:

單片機(jī)源程序如下:
  1. #include "main.h"
  2. #include "Display.H"
  3. #include "stdio.H"
  4. #include "KEY.h"
  5. #include "TIME.h"
  6. #include "DELAY.h"
  7. #include "i2c.h"
  8. #include "CONFIG.H"
  9. #include "intrins.h"
  10. //發(fā)送40KHz脈沖延時(shí)函數(shù)
  11. #define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();\
  12.                  _nop_();_nop_();_nop_();_nop_(); _nop_();}

  13. union flo_to_ch
  14. {
  15.         u16 f_num;
  16.         u8 u_num[2];//共用內(nèi)存單元,u_num[2]分別為f32數(shù)據(jù)u16的2個(gè)字節(jié)
  17. };

  18. union flo_to_ch diyi_juli_h,dier_juli_h,disan_juli_h,disi_juli_h;//四次距離定義
  19. u16 juli=0,juli_s=0;//這次距離和上次距離
  20. u8 Dis_Buf[10] = {"        "}; //數(shù)碼管顯示緩存
  21. u8 Dis_Mode = 'C';  //數(shù)碼管顯示模式,‘C‘距離顯示,’H’回顯,‘F’盲區(qū)顯示
  22. u8 hx_num = 0;//當(dāng)前回顯得是第幾個(gè)
  23. u16 mq_num = 0;//盲區(qū)數(shù)值

  24. bit job1_flag = 0;//是否調(diào)用job1函數(shù)標(biāo)志,在T1中斷里面置1
  25. bit job2_flag = 0;//是否調(diào)用job2函數(shù)標(biāo)志,在T1中斷里面置1
  26. bit job3_flag = 0;//是否調(diào)用job3函數(shù)標(biāo)志,在T1中斷里面置1
  27. bit job4_flag = 0;//是否調(diào)用job4函數(shù)標(biāo)志,在T1中斷里面置1
  28. bit job5_flag = 0;//是否調(diào)用job5函數(shù)標(biāo)志,在T1中斷里面置1
  29. bit ssbz = 0;//閃爍標(biāo)志

  30. sbit TX = P1^0;  //發(fā)射引腳
  31. sbit RX = P1^1;  //接收引腳

  32. void job1(void); //數(shù)碼管動(dòng)態(tài)顯示處理,每5ms一次
  33. void job2(void); //顯示模式處理,每100ms一次
  34. void job3(void); //按鍵讀取與處理,每50ms一次
  35. void job4(void); //亮燈處理
  36. void job5(void); //電壓輸出
  37. void juli_set(void);//距離存儲(chǔ)
  38. void juli_read(void);//距離讀取
  39. void mq_read(void);//盲區(qū)讀取
  40. void mq_set(void);//盲區(qū)存儲(chǔ)
  41. void jlcl();//距離測(cè)量
  42. void send_wave(void);//發(fā)送超聲波
  43. void dac_shuchu();//電壓輸出函數(shù)

  44. void Sys_Init()//系統(tǒng)初始化
  45. {
  46.         Buzzy_Off;
  47.         Relay_Off;
  48.         Led_Set = 0xff;
  49. }
  50. void main()
  51. {
  52.         Sys_Init();//系統(tǒng)初始化
  53.         Timer0Init();//T0初始化,T0用來測(cè)量距離
  54.         Timer1Init();//T1初始化,T1中斷用來產(chǎn)生調(diào)用函數(shù)標(biāo)志
  55. //        diyi_juli_h.f_num=dier_juli_h.f_num=disan_juli_h.f_num=disi_juli_h.f_num=0;//調(diào)試用
  56. //        juli_set();//調(diào)試用
  57.         juli_read();//讀取eeprom數(shù)據(jù)
  58.         mq_read();//閾值讀取
  59.         juli = disi_juli_h.f_num;//設(shè)置這次距離為第4次測(cè)量的距離
  60.         juli_s = disan_juli_h.f_num;//設(shè)置上次距離為第3次測(cè)量的距離
  61.         init_pcf8591();//初始化
  62.         while (1)//循環(huán)判斷
  63.         {
  64.                 if (job1_flag)//判斷時(shí)候?yàn)?,等于則調(diào)用函數(shù),并將調(diào)用函數(shù)標(biāo)志清0(下同)
  65.                 {
  66.                         job1(); //數(shù)碼管動(dòng)態(tài)顯示處理,每5ms一次
  67.                         job1_flag = 0;//清0
  68.                 }
  69.                 if (job2_flag)
  70.                 {
  71.                         job2(); //顯示模式處理,每100ms一次
  72.                         job2_flag = 0;
  73.                 }
  74.                 if (job3_flag)
  75.                 {
  76.                         job3(); //按鍵讀取與處理,每50ms一次
  77.                         job3_flag = 0;
  78.                 }
  79.                 if (job4_flag)
  80.                 {
  81.                         job4();//LED處理函數(shù)
  82.                         job4_flag = 0;
  83.                 }
  84.                 if (job5_flag)
  85.                 {
  86.                         job5();//電壓輸出處理
  87.                         job5_flag = 0;
  88.                 }               
  89.         }
  90. }

  91. void job1(void) //數(shù)碼管動(dòng)態(tài)顯示處理,每5ms一次
  92. {
  93.         Display(Dis_Buf);
  94. }

  95. void job2(void) //顯示模式處理,每100ms一次,Work_Mode=’U’回顯,其他常規(guī)顯示
  96. {
  97.         switch (Dis_Mode) //判斷當(dāng)前顯示模式
  98.         {
  99.                 case 'C': sprintf(Dis_Buf, "C %03d%03d",juli,juli_s);break;
  100.                 case 'F' : sprintf(Dis_Buf, "F     %02d",mq_num);break;
  101.                 case 'H':
  102.                 {
  103.                         switch (hx_num)
  104.                         {
  105.                                 case 0:
  106.                                 {
  107.                                         sprintf(Dis_Buf, "1    %03d",diyi_juli_h.f_num);        
  108.                                 }break;
  109.                                 case 1:
  110.                                 {
  111.                                         sprintf(Dis_Buf, "2    %03d",dier_juli_h.f_num);        
  112.                                 }break;
  113.                                 case 2:
  114.                                 {
  115.                                         sprintf(Dis_Buf, "3    %03d",disan_juli_h.f_num);        
  116.                                 }break;
  117.                                 case 3:
  118.                                 {
  119.                                         sprintf(Dis_Buf, "4    %03d",disi_juli_h.f_num);        
  120.                                 }break;
  121.                         }
  122.                 }break;
  123.         }
  124. }

  125. void job3(void) //按鍵讀取與處理,每50ms一次
  126. {
  127.         u8 Key_Num = read_keyboard();
  128.         switch (Key_Num)
  129.         {
  130.                 case '1'://測(cè)量距離,循環(huán)覆蓋,距離儲(chǔ)存
  131.                 {
  132.                         juli_s = juli;
  133.                         jlcl();
  134.                         diyi_juli_h.f_num = dier_juli_h.f_num;
  135.                         dier_juli_h.f_num = disan_juli_h.f_num;
  136.                         disan_juli_h.f_num        = juli_s;
  137.                         disi_juli_h.f_num = juli;
  138.                         juli_set();
  139.                         ssbz = 1;
  140.                 }break;
  141.                 case 'C':
  142.                 {
  143.                         Dis_Mode = 'C';
  144.                 }break;
  145.                 case 'H': //S5 存儲(chǔ) (溫度/電壓/頻率 存儲(chǔ)到E2PROM)
  146.                 {
  147.                         Dis_Mode = 'H';
  148.                         juli_read();
  149.                 }break;
  150.                 case 'F':
  151.                 {
  152.                         Dis_Mode = 'F';
  153.                 }break;        
  154.         }        
  155. }

  156. void job4(void) //LED亮燈處理,每200ms一次
  157. {
  158.         static u8 time_num = 0;//時(shí)間標(biāo)志
  159.         static u8 cs_num = 0;//亮滅次數(shù)
  160.         static u8 Led_Set_Temp = 0xff;//LED要顯示的值
  161.         if(ssbz)//閃爍標(biāo)志判斷
  162.         {
  163.                 if(cs_num == 0)Led_Set_Temp = 0XFE;        //亮滅次數(shù)判斷,如果第一次進(jìn)來,就賦值。
  164.                 time_num++;//時(shí)間,如果等于5說明1S到了,要對(duì)亮的燈進(jìn)行取反
  165.                 if(time_num == 5)
  166.                 {
  167.                         time_num = 0;
  168.                         if(Led_Set_Temp == 0XFE)Led_Set_Temp = 0XFF;                                       
  169.                         else if(Led_Set_Temp == 0XFF)Led_Set_Temp = 0XFE;
  170.                         else if(Led_Set_Temp == 0XBF)Led_Set_Temp = 0XBE;
  171.                         else if(Led_Set_Temp == 0XBE)Led_Set_Temp = 0XBF;
  172.                         else if(Led_Set_Temp == 0X7F)Led_Set_Temp = 0X7E;
  173.                         else if(Led_Set_Temp == 0X7E)Led_Set_Temp = 0X7F;
  174.                         cs_num++;//亮滅次數(shù)+1
  175.                         if(cs_num == 5)//如果等于5,說明已經(jīng)亮滅循環(huán)3次,要將閃爍標(biāo)志清零,亮滅次數(shù)清零
  176.                         {
  177.                                 cs_num = 0;
  178.                                 ssbz = 0;
  179.                         }
  180.                 }
  181.                 if(Dis_Mode == 'F')Led_Set_Temp &= 0XBF;
  182.                 else if(Dis_Mode == 'H')Led_Set_Temp &= 0X7F;        
  183.         }
  184.         else if(Dis_Mode == 'F')Led_Set_Temp = 0XBF;        
  185.         else if(Dis_Mode == 'H')Led_Set_Temp = 0X7F;
  186.         else Led_Set_Temp = 0xFF;
  187.         Led_Set=Led_Set_Temp;
  188. }

  189. void job5(void) //電壓輸出處理
  190. {
  191.         unsigned char dy = 0X00;
  192.         if(juli <= mq_num)
  193.         {
  194.                 dac_pcf8591(0X00);
  195.         }
  196.         else if(juli>mq_num)
  197.         {
  198.                 if((juli-mq_num)>=250)
  199.                         dy=255;
  200.                 else
  201.                         dy = (unsigned char)(((juli-mq_num)*0.02)/5.0*255.0);
  202.         }
  203.         dac_pcf8591(dy);               
  204. }


  205. void juli_set(void)//歷史測(cè)量的距離儲(chǔ)存
  206. {        
  207.         write_eeprom(0,diyi_juli_h.u_num[0]);i2c_delay(200);i2c_delay(200);
  208.         write_eeprom(1,diyi_juli_h.u_num[1]);i2c_delay(200);i2c_delay(200);

  209.         write_eeprom(2,dier_juli_h.u_num[0]);i2c_delay(200);i2c_delay(200);
  210.         write_eeprom(3,dier_juli_h.u_num[1]);i2c_delay(200);i2c_delay(200);

  211.         write_eeprom(4,disan_juli_h.u_num[0]);i2c_delay(200);i2c_delay(200);
  212.         write_eeprom(5,disan_juli_h.u_num[1]);i2c_delay(200);i2c_delay(200);

  213.         write_eeprom(6,disi_juli_h.u_num[0]);i2c_delay(200);i2c_delay(200);
  214.         write_eeprom(7,disi_juli_h.u_num[1]);i2c_delay(200);i2c_delay(200);
  215. }
  216. void juli_read(void)//歷史測(cè)量距離讀取
  217. {        
  218.         diyi_juli_h.u_num[0]=read_eeprom(0);i2c_delay(200);i2c_delay(200);
  219.         diyi_juli_h.u_num[1]=read_eeprom(1);i2c_delay(200);i2c_delay(200);
  220.         
  221.         dier_juli_h.u_num[0]=read_eeprom(2);i2c_delay(200);i2c_delay(200);
  222.         dier_juli_h.u_num[1]=read_eeprom(3);i2c_delay(200);i2c_delay(200);
  223.         
  224.         disan_juli_h.u_num[0]=read_eeprom(4);i2c_delay(200);i2c_delay(200);
  225.         disan_juli_h.u_num[1]=read_eeprom(5);i2c_delay(200);i2c_delay(200);        

  226.         disi_juli_h.u_num[0]=read_eeprom(6);i2c_delay(200);i2c_delay(200);
  227.         disi_juli_h.u_num[1]=read_eeprom(7);i2c_delay(200);i2c_delay(200);        
  228. }
  229. void mq_read()//盲區(qū)距離讀取
  230. {
  231.         mq_num = read_eeprom(8);i2c_delay(200);i2c_delay(200);
  232. }

  233. void mq_set()//盲區(qū)距離存儲(chǔ)
  234. {
  235.         write_eeprom(8,mq_num);i2c_delay(200);i2c_delay(200);
  236. }

  237. void jlcl()//距離測(cè)量函數(shù)
  238. {
  239.         unsigned int t = 0;
  240.         TR1 = 0;//停止T1計(jì)時(shí),防止中斷函數(shù),干擾測(cè)距
  241.         send_wave();  //發(fā)送方波信號(hào)
  242.     TR0 = 1;  //啟動(dòng)計(jì)時(shí)
  243.         while((RX == 1) && (TF0 == 0));//等待收到脈沖
  244.         TR0 = 0;  //關(guān)閉計(jì)時(shí)
  245.         //發(fā)生溢出
  246.         if(TF0 == 1)
  247.         {
  248.                 TF0 = 0;
  249.         }
  250.         else
  251.         {
  252.                 /**  計(jì)算時(shí)間  */
  253.                 t = TH0;
  254.                 t <<= 8;
  255.                 t |= TL0;
  256.                 juli = (unsigned int)(t*0.017);  //計(jì)算距離                                
  257.         }
  258.         TH0 = 0;
  259.         TL0 = 0;
  260.         //juli += 10;
  261.         TR1 = 1;//啟動(dòng)T1計(jì)時(shí)
  262. }

  263. void send_wave(void)//發(fā)送脈沖函數(shù)
  264. {
  265.         unsigned char i = 8;  //發(fā)送8個(gè)脈沖
  266.         do
  267.         {
  268.                 TX = 1;
  269.                 somenop;somenop;somenop;somenop;somenop;somenop;
  270.                 somenop;somenop;somenop;somenop;               
  271.                 TX = 0;
  272.                 somenop;somenop;somenop;somenop;somenop;somenop;
  273.                 somenop;somenop;somenop;somenop;               
  274.         }
  275.         while(i--);
  276. }
復(fù)制代碼
我就不把全部的程序貼上了,大家請(qǐng)到附件里面下載,還有就是,參加藍(lán)橋杯比賽的同學(xué)可以關(guān)注我,我會(huì)在藍(lán)橋杯國(guó)賽之前把所有的國(guó)賽題目和程序發(fā)上來(不參加的也可以關(guān)注哦 第8屆:超聲波測(cè)距機(jī).rar (963.25 KB, 下載次數(shù): 80)

評(píng)分

參與人數(shù) 1黑幣 +70 收起 理由
admin + 70 贊一個(gè)!

查看全部評(píng)分

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

使用道具 舉報(bào)

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表