找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2593|回复: 4
打印 上一主题 下一主题
收起左侧

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

  [复制链接]
跳转到指定楼层
楼主
制作出来的实物图如下:


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



单片机源程序如下:

  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.         we0=1;                                          
  117.         timers=0;                                  //将发送次数归零
  118.         TH0=0X00;                                  //定时器装初值
  119.         TL0=0X32;                                  //装0x32是因为发送时也占用了时间
  120.         TR0=1;                                          //打开计时器
  121.         EX0=1;                                          //打开外部中断等待接收返回声波
  122.         delay100us();                          //避盲延时
  123.         delay100us();
  124.         delay100us();
  125. //        delay100us();
  126. //        delay100us();
  127. }
  128. void keyscan()                                   //键盘扫描
  129. {
  130.         if(k1==0)                                   //开关键按下
  131.         {
  132.                 shijian(10);
  133.                 if(k1==0)
  134.                 kaiflag=~kaiflag;           //开关标志位取反
  135.                 while(k1==0);                   //等待按键释放                    
  136.         }
  137.         if(k2==0)                                  //k2按下
  138.         {
  139.                 shijian(10);
  140.                 if(k2==0)
  141.                 temflag=~temflag;          //温度距离标志位取反
  142.                 while(k2==0);                  //等待按键释放
  143.         }
  144. }
  145. void temdisplay()                          //温度显示函数
  146. {
  147.         num=get();                                  //读取当前温度值
  148.         shi=num/100;                          //分离出十位值
  149.         ge=num%100/10;                          //分离出个位值
  150.         shifen=num%10;                          //分离出十分位值


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

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

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

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

  259. }
  260. void timer1() interrupt 3                 //显示测距距离中断
  261. {
  262.         TH1=0x00;                                         //装初值
  263.         TL1=0x00;
  264.         num1++;

  265.         if(num1==5)                                         //如果经过1250us,显示一位
  266.         {

  267.                 num1=0;
  268.                 shijian(2);
  269.                 num2++;
  270.                 if(num2==4)
  271.                 num2=0;



  272.         }

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


  300. }
复制代码


所有资料51hei附件下载:
原理图和pcb.7z (156.28 KB, 下载次数: 93)

评分

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

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏11 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:372579 发表于 2022-2-24 07:44 来自手机 | 只看该作者
这个很不错哦
回复

使用道具 举报

板凳
ID:893997 发表于 2022-2-24 21:22 | 只看该作者
可以但不建议都写在一个文件
回复

使用道具 举报

地板
ID:1086127 发表于 2023-6-27 10:34 | 只看该作者
请问有那个仿真图吗
回复

使用道具 举报

5#
ID:480664 发表于 2023-11-22 16:25 | 只看该作者
这个很不错了,详尽啊!
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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