找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5096|回复: 5
收起左侧

带温度补偿的单片机超声波测距仪原理图PCB+源程序

[复制链接]
ID:413459 发表于 2018-10-22 19:12 | 显示全部楼层 |阅读模式
带温度补偿的超声波测距仪电路原理图如下:
0.png

Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)
0.png 0.png

元器件清单

带温度补偿的超声波测距仪
序号    元件名称    型号与规格    单位    数量
1    电阻    1KΩ    只    6
        R19     10k    只    1
        R3      200K    只    1
        R4      20Ω    只    1
        R7~R12  R14  R17  R18  R20    470Ω    只    10
2    排针        排    1
3    电解电容    C3         3.3μF    只    1
        C4   1μF    只    1
        C7  10μF    只    1
4    电瓷电容    C1      0.24μF    只    1
        C2       330 pF    只    1
        C5   C6    30 pF    只    1
5    晶振    Y1         12MHz    只    1
6    三级管    VT1~VT4      9012    只    4
7    温度传感器    DX18320    块    1
8    单片机    AT89S52    块    1
9    红外线接收芯片    CX20106A    块    1
10    按钮    S1~S3         只    3
11    发光二级管    VD1    只    1
12    数码管    4位    只    1
13    超声波发射    LS1    只    1
14    超声波接收    LS2    只    1

单片机源程序如下:
  1. #include<reg52.h>
  2. #define uint unsigned int
  3. #define uchar unsigned char
  4. #define ulong unsigned long
  5. sbit we0=P2^0; //                数码管位定义
  6. sbit we1=P2^1; //
  7. sbit we2=P2^2; //
  8. sbit we3=P2^3;
  9. sbit fasong=P1^0;                 //超生波发送接口
  10. sbit jieshou=P3^2;                 //超声波接受接口
  11. sbit k1=P3^6;                         //开关键
  12. sbit k2=P3^7;                         //温度距离显示切换键
  13. sbit ds=P1^4;                         //温度传感数据接口
  14. uchar timers,mi,fenmi,limi,num2,num1,shi,ge,shifen,shengsu;
  15. bit flag,kaiflag,temflag;         //定义各种标志位
  16. ulong t,s;                                         //接收时间和距离
  17. uint temp,num;
  18. float n;                                         //18b20读取数据时用
  19. uchar code table[]=                         //数码管显示编码(不带小数点and带)
  20. {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
  21. 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
  22. void init();                                 //声明初始化函数
  23. void delay100us()                         //超声波避盲区延时函数
  24. {
  25.         uchar i,j;
  26.         for(i=40;i>0;i--)
  27.                 for(j=248;j>0;j--);       
  28. }
  29. void delay(uchar a)                           //短暂延时函数(用于18B20)
  30. {
  31.          while(a>0)
  32.          a--;
  33. }
  34. void shijian(uint x)                        //一毫秒延时函数
  35. {
  36.         uint i,j;
  37.         for(i=x;i>0;i--)
  38.                  for(j=110;j>0;j--);
  39. }
  40. void reset()                                    //18B20复位
  41. {
  42.         ds=0;
  43.         delay(103);
  44.         ds=1;
  45.         delay(4);       
  46. }
  47. void write(uchar date)                    //18B20写一字节数据
  48. {
  49.          uchar temp,i;
  50.          uint j;
  51.          temp=date;
  52.          for(i=0;i<8;i++)
  53.          {       
  54.                   temp=temp>>1;
  55.                  if(CY)                   //写1
  56.                  {
  57.                          ds=0;
  58.                 j++;j++;
  59.                         ds=1;
  60.                         delay(8);
  61.                  }
  62.                  else
  63.                  {
  64.                          ds=0;
  65.                         delay(8);
  66.                         ds=1;
  67.                         j++;j++;
  68.                  }
  69.          }

  70. }
  71. uchar read()                                        //18B20读一字节数据
  72. {
  73.         uchar j,dat;
  74.         for(j=0;j<8;j++)
  75.         {
  76.                 ds=0;
  77.                 dat>>=1;
  78.                 ds=1;
  79.                 delay(1);
  80.                 if(ds)
  81.                 dat|=0x80;
  82.                 delay(8);
  83.         }
  84.         return(dat);
  85. }
  86. uint get()                                                 //从温度传感器获取数值
  87. {
  88.         uchar gao,di;
  89.         reset();
  90.         shijian(1);
  91.         write(0xcc);
  92.         write(0x44);

  93.         reset();
  94.         shijian(1);
  95.         write(0xcc);
  96.         write(0xbe);
  97.         di=read();
  98.         gao=read();
  99.         temp=gao<<8;
  100.         temp=temp|di;
  101.         n=temp*0.065+0.5;
  102.         temp=n*10;
  103.         return(temp);
  104. }
  105. void send()                                           //超声波发送函数
  106. {
  107.         uchar i;
  108.         while(TF0==0)
  109.         {         we0=0;
  110.                  timers++;                          
  111.                  fasong=~fasong;
  112.                  for(i=12;i>0;i--);          //40hz延时
  113.                  if(timers==4)                  //连续发送两个超声波脉冲
  114.                  break;
  115.                
  116.         }
  117.         we0=1;                                          
  118.         timers=0;                                  //将发送次数归零
  119.         TH0=0X00;                                  //定时器装初值
  120.         TL0=0X32;                                  //装0x32是因为发送时也占用了时间
  121.         TR0=1;                                          //打开计时器
  122.         EX0=1;                                          //打开外部中断等待接收返回声波
  123.         delay100us();                          //避盲延时
  124.         delay100us();
  125.         delay100us();
  126. //        delay100us();
  127. //        delay100us();
  128. }
  129. void keyscan()                                   //键盘扫描
  130. {
  131.         if(k1==0)                                   //开关键按下
  132.         {
  133.                 shijian(10);
  134.                 if(k1==0)
  135.                 kaiflag=~kaiflag;           //开关标志位取反
  136.                 while(k1==0);                   //等待按键释放                   
  137.         }
  138.         if(k2==0)                                  //k2按下
  139.         {
  140.                 shijian(10);
  141.                 if(k2==0)
  142.                 temflag=~temflag;          //温度距离标志位取反
  143.                 while(k2==0);                  //等待按键释放
  144.         }
  145. }
  146. void temdisplay()                          //温度显示函数
  147. {
  148.         num=get();                                  //读取当前温度值
  149.         shi=num/100;                          //分离出十位值
  150.         ge=num%100/10;                          //分离出个位值
  151.         shifen=num%10;                          //分离出十分位值


  152.                 P0=table[shi];                  //十位显示
  153.                 we1=0;
  154.                 we0=1;
  155.                 we2=1;
  156.                 we3=1;
  157.                 shijian(6);

  158.                 P0=table[ge+10];          //个位显示
  159.                 we1=1;
  160.                 we0=1;
  161.                 we2=0;
  162.                 we3=1;
  163.                 shijian(6);

  164.                 P0=table[shifen];          //十分位显示
  165.                 we3=0;
  166.                 we1=1;
  167.                 we0=1;
  168.                 we2=1;
  169.                 shijian(1);
  170. }
  171. void init()                                          //初始化函数
  172. {
  173.         TMOD=0x21;           //定时器1为8位自动重装模式,
  174.                                    //定时器0为十六位计数器       
  175.         TH0=0X00;           //定时器0装初值
  176.         TL0=0X32;          
  177.         TH1=0x00;           //定时器装空值
  178.         TL1=0x00;          
  179.         TR1=0;                   //关闭显示定时
  180.         TR0=0;                   //关闭定时器0计时
  181.         EA=1;                   //打开总中断
  182.         ET0=1;                   //打开计时中断
  183.         ET1=1;                   //打开定时器1中断
  184.         EX0=1;                   //打开外部中断
  185.         IT0=1;                   //外部中断选择下降沿触发
  186.         P2=0xff;
  187.         P0=0xff;           //关闭数码管段选
  188.         kaiflag=0;           //开标志位置0
  189.         temflag=0;           //温度距离标志位置0
  190. }
  191. void main()                   //主函数
  192. {
  193.         init();                   //进行初始化
  194.         while(1)
  195.         {       
  196.                 keyscan();        //键盘扫描
  197.                 if((kaiflag==1)&&(temflag==1))//如果打开并且选择测温
  198.                 {
  199.                         temdisplay();                          //进行温度显示
  200.                         TR1=0;                                          //将定时器都关闭
  201.                     TR0=0;
  202.                         EX0=0;

  203.                 }
  204.                 if((kaiflag==1)&&(temflag==0)) //如果打开并选择测距
  205.                 {       
  206.                         send();                                           //发送脉冲
  207.                         num=get();                                   //读取温度值          
  208.                         TR1=1;                                           //打开测距显示中断
  209.                 }
  210.                 if(kaiflag==0)                                   //如果处于关闭状态
  211.                 {
  212.                         TR1=0;
  213.                         TR0=0;                                                //测距显示关闭
  214.                         init();                                                //进行初始化
  215.                 }
  216.         }
  217. }
  218. /*******************对下面用到的中断的解释************
  219. 1.外部中断0用来接收返回的脉冲,当接收到以后进行中断处理,优先级最高;
  220. 2.定时器0用来计时,选择的是十六位定时模式;用来计算超声波脉冲
  221.   从发射到接受所用的时间。
  222. 3.定时器1用来作为测试距离的显示定时。每中断一次就扫描一位数码管
  223. *********************************************************/
  224. void IN0() interrupt 0                                        //超声波接收中断(外部)
  225. {
  226.         TR0=0;                                                                //关闭设计时器
  227.         EX0=0;                                                                //停止接收返回脉冲
  228.     if(num<=50)                                          //根据当前温度值来调整声速
  229.         {
  230.                 shengsu=165;
  231.         }
  232.         else if(num<=100)
  233.         {
  234.                 shengsu=169;
  235.         }
  236.         else if(num<=200)
  237.         {
  238.                 shengsu=172;
  239.         }
  240.         else if(num<=300)
  241.         {
  242.                 shengsu=175;
  243.         }
  244.         else if(num<=500)
  245.         {
  246.                 shengsu=180;
  247.         }
  248.         t=TH0*256+TL0;                                //计算从发射到接收用时(单位us)
  249.         s=t*shengsu/10000;                                        //根据时间计算距离
  250.         mi=s/100;                                                        //分离出米
  251.         fenmi=s%100/10;                                                //……分米
  252.         limi=s%10;                                                        //……厘米
  253.         EX0=1;                                                //计算完毕允许接收下个脉冲
  254. }
  255. void timer0() interrupt 1
  256. {
  257.         TR0=0;
  258.         TH0=0;
  259.         TL0=0;

  260. }
  261. void timer1() interrupt 3                 //显示测距距离中断
  262. {
  263.         TH1=0x00;                                         //装初值
  264.         TL1=0x00;
  265.         num1++;
  266.        
  267.         if(num1==5)                                         //如果经过1250us,显示一位
  268.         {
  269.                
  270.                 num1=0;
  271.                 shijian(2);
  272.                 num2++;
  273.                 if(num2==4)
  274.                 num2=0;



  275.         }
  276.        
  277.         if(temflag==0)
  278.         {       
  279.                 if(num2==0)
  280.                 {
  281.                         P0=table[mi+10];
  282.                         we1=0;
  283.                         we0=1;
  284.                         we2=1;
  285.                         we3=1;
  286.                 }
  287.                 if(num2==2)
  288.                 {
  289.                         P0=table[fenmi];
  290.                         we1=1;
  291.                         we0=1;
  292.                         we2=0;
  293.                         we3=1;
  294.                 }
  295.                 if(num2==3)
  296.                 {
  297.                         P0=table[limi];
  298.                         we3=0;
  299.                         we1=1;
  300.                         we0=1;
  301.                         we2=1;
  302.                 }
  303.         }          

  304.                
  305. }
复制代码

所有资料51hei提供下载:
Desktop.rar (1.56 MB, 下载次数: 97)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:439461 发表于 2018-12-9 21:29 | 显示全部楼层
十分感谢你。这个真心不错
回复

使用道具 举报

ID:428027 发表于 2018-12-10 09:31 来自手机 | 显示全部楼层
请问:温度补偿是什么意思呀
回复

使用道具 举报

ID:89286 发表于 2018-12-10 10:22 | 显示全部楼层
thanks for sharing
回复

使用道具 举报

ID:480175 发表于 2019-2-26 10:11 | 显示全部楼层
番茄薯条 发表于 2018-12-10 09:31
请问:温度补偿是什么意思呀

环境温度不同对应超声波发射速度不同,通过温度传感器测出环境温度,调用不同温度下超声波发射的速度实现温度补偿的功能。优点:测距更加准确,减小温度变化对超声波测距的影响。
回复

使用道具 举报

ID:488725 发表于 2019-3-12 12:27 | 显示全部楼层
能解释下发送模块的原理吗
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表