找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机超声波程序(带详细注释)Proteus仿真图

[复制链接]
跳转到指定楼层
楼主
这是我之前做的基于STM32的超声波测距系统,
附件里面包含了keil仿真代码以及Proteus仿真工程
请大家多多指教



单片机源程序如下:
  1. //头文件包含
  2. #include <reg52.h>                //提供单片机寄存器地址
  3. #include <intrins.h>        //提供_nop_()函数

  4. unsigned int code duan_ma[16] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,                //0~9
  5.                                                                  0x77,0x7c,0x39,0x5e,0x79,0x71};        //A~F
  6. unsigned int dis_buf[4];                        //显示缓存的数组
  7. unsigned int S = 0;                                        //距离缓存变量
  8. unsigned long time = 0;                                //时间缓存变量
  9. unsigned int S_H = 400, S_L = 10;        //S_H:报警上限值,默认400cm,S_L:报警下限值,默认10cm

  10. //引脚定义
  11. sbit BEEP = P3^7;                //蜂鸣器控制端口,低电平有效,无源蜂鸣器
  12.                                                                  
  13. #define digDuan                P0                //数码管段控制端口,高电平有效
  14. sbit digWei1 = P2^4;                //第1位数码管控制端口,低电平有效
  15. sbit digWei2 = P2^5;                //第2位数码管控制端口,低电平有效
  16. sbit digWei3 = P2^6;                //第3位数码管控制端口,低电平有效
  17. sbit digWei4 = P2^7;                //第4位数码管控制端口,低电平有效                                                                 
  18.        
  19. sbit KEY1 = P1^0;                        //设置键
  20. sbit KEY2 = P1^1;                        //加键
  21. sbit KEY3 = P1^2;                        //减键                                                                 
  22.                        
  23. sbit Ttig = P1^3;                //触发信号控制端口
  24. sbit Echo = P1^4;                //回响信号接收端口
  25.                                                                  
  26. /* 定时器0和1初始化,定时1ms */
  27. void InitTimer0(void)
  28. {
  29.   TMOD = 0x11;        //配置定时器0为工作方式1,定时器1位工作方式1
  30.         TH0 = 0;
  31.   TL0 = 0;
  32.         TH1 = 0x0EC;        //定时5ms
  33.   TL1 = 0x78;
  34.         EA = 1;                        //打开总中断
  35.         ET1 = 1;                //打开定时器0中断
  36.         TR1 = 1;                //打开定时器1
  37.   TR0 = 0;                //打开定时器0
  38. }

  39. /*
  40. * 数码管扫描
  41. * *dat:以数组的方式传值,使用的时候直接填入数组名即可
  42. */  
  43. void dig_scan(unsigned int *dat)
  44. {
  45.         static unsigned char i = 0;        //循环变量

  46.         /* 数码管扫描处理 */
  47.         digDuan = 0x00;                //消隐
  48.         digWei1 = 1;                       
  49.         digWei2 = 1;                        
  50.         digWei3 = 1;
  51.         digWei4 = 1;
  52.         switch(i)
  53.         {
  54.                 case 0:
  55.                 {
  56.                         digWei1 = 0;                        //选通第1位数码管
  57.                         digDuan = dat[0];                //显示第1位数码管的内容
  58.                         break;
  59.                 }
  60.                 case 1:
  61.                 {
  62.                         digWei2 = 0;                        //选通第2位数码管
  63.                         digDuan = dat[1];                //显示第2位数码管的内容
  64.                         break;
  65.                 }
  66.                 case 2:
  67.                 {
  68.                         digWei3 = 0;                                //选通第3位数码管
  69.                         digDuan = dat[2] + 0x80;        //显示第3位数码管的内容,顺便也显示小数点
  70.                         break;
  71.                 }
  72.                 case 3:
  73.                 {
  74.                         digWei4 = 0;                        //选通第4位数码管
  75.                          digDuan = dat[3];                //显示第4位数码管的内容
  76.                         break;       
  77.                 }
  78.                 default: break;
  79.         }
  80.         ++i;                //数码管位选变量循环
  81.         if(i >= 4)
  82.                 i = 0;                               
  83. }

  84. /* 按键延时函数,单位:ms */
  85. static void key_delayms(unsigned int ms)
  86. {
  87.         unsigned char a,b,c;
  88.         while(--ms)
  89.         {
  90.             for(c=1;c>0;c--)
  91.                 for(b=142;b>0;b--)
  92.                     for(a=2;a>0;a--);
  93.         }
  94. }
  95. /* 按键扫描 */
  96. unsigned char key_scan(void)
  97. {
  98.         if(KEY1 == 0)                        //如果按键1按下
  99.         {
  100.                 key_delayms(10);        //延时10ms,去除按键抖动
  101.                 if(KEY1 == 0)                //再判断一次按键按下
  102.                 {
  103.                         return 1;                 //输出键值1
  104.                 }       
  105.         }
  106.         if(KEY2 == 0)                //如果按键2按下
  107.         {
  108.                 key_delayms(10);        //延时10ms,去除按键抖动
  109.                 if(KEY2 == 0)                //再判断一次按键按下
  110.                 {
  111.                         return 2;                 //输出键值2
  112.                 }
  113.         }
  114.         if(KEY3 == 0)                //如果按键3按下
  115.         {
  116.                 key_delayms(10);        //延时10ms,去除按键抖动
  117.                 if(KEY3 == 0)                //再判断一次按键按下
  118.                 {
  119.                         return 3;                 //输出键值3
  120.                 }
  121.         }

  122.         return 0;                                //如果没有按键按下,则输出0
  123. }

  124. /* 启动超声波程序 */
  125. void StartModule(void)
  126. {
  127.         Ttig = 1;                        //启动一次模块
  128.         _nop_();                        //延时一段时间,至少10us以上
  129.         _nop_();                        
  130.         _nop_();
  131.         _nop_();
  132.         _nop_();
  133.         _nop_();
  134.         _nop_();
  135.         _nop_();
  136.         _nop_();
  137.         _nop_();
  138.         _nop_();
  139.         _nop_();
  140.         _nop_();
  141.         _nop_();
  142.         _nop_();
  143.         _nop_();
  144.         _nop_();
  145.         _nop_();
  146.         _nop_();
  147.         _nop_();
  148.         _nop_();
  149.         Ttig = 0;
  150. }

  151. /* 延时,单位:ms */
  152. void delayms(unsigned int ms)
  153. {
  154.         unsigned char a,b,c;

  155.         while(--ms)
  156.         {
  157.             for(c=1;c>0;c--)
  158.                 for(b=142;b>0;b--)
  159.                     for(a=2;a>0;a--);       
  160.         }
  161. }



  162. /* 计算测距 */
  163. void count(void)
  164. {
  165.         StartModule();        //启动一次超声波
  166.         while(!Echo);                //等待超声波模块输出IO拉高
  167.         TR0 = 1;                        //开启定时器计时
  168.         while(Echo);                //等待超声波模块输出IO拉低
  169.         TR0 = 0;                         //关闭定时器计时
  170.        
  171.         /* 计算距离 */
  172.         time = TH0 * 256 + TL0;        //得到的时间,专业写法应该是这样:time = TH0 << 8 | TL0
  173.         TH0 = 0;                                //定时计数器清零       
  174.         TL0 = 0;
  175.        
  176.         S = (time * 1.7) / 100; //算出来是M                               
  177. }
  178. /* 显示距离 */
  179. void dis_distance(void)
  180. {
  181.         dis_buf[3] = 0x00;
  182.         dis_buf[2] = duan_ma[S / 100 %10];         //取出百位数,并在数码管的第3位显示,从右往左数
  183.         dis_buf[1] = duan_ma[S / 10 %10];        //取出十位数,并在数码管的第2位显示,从右往左数
  184.         dis_buf[0] = duan_ma[S % 10];                 //取出个位数,并在数码管的第1位显示,从右往左数       
  185. }
  186. /* 设置报警功能 */
  187. void key_fuction(void)
  188. {
  189.         unsigned char mode_flag = 1;        //模式切换标记位,1:设置上限值,2:设置下限值,3:退出

  190.         while(1)
  191.         {
  192.                 if(key_scan() == 1)       
  193.                 {
  194.                         BEEP = 0;                        //按键提示音
  195.                         delayms(50);
  196.                         BEEP = 1;
  197.                         delayms(1000);
  198.                         ++mode_flag;
  199.                         if(mode_flag >= 3)        //如果满3了,则退出
  200.                                 break;               
  201.                 }
  202.                 if(key_scan() == 2)                //如果加键按下
  203.                 {
  204.                         BEEP = 0;                        //按键提示音
  205.                         delayms(50);
  206.                         BEEP = 1;
  207.                         delayms(1000);
  208.                         if(mode_flag == 1)        //设置上限值
  209.                         {
  210.                                 ++S_H;
  211.                                 if(S_H > 400)
  212.                                         S_H = 2;       
  213.                         }
  214.                         if(mode_flag == 2)        //设置下限值
  215.                         {
  216.                                 ++S_L;
  217.                                 if(S_L > 400)
  218.                                         S_L = 2;       
  219.                         }
  220.                 }
  221.                 if(key_scan() == 3)                //如果减键按下
  222.                 {
  223.                         BEEP = 0;                        //按键提示音
  224.                         delayms(50);
  225.                         BEEP = 1;
  226.                         delayms(1000);
  227.                         if(mode_flag == 1)        //设置上限值
  228.                         {
  229.                                 --S_H;
  230.                                 if(S_H < 2)
  231.                                         S_H = 400;       
  232.                         }
  233.                         if(mode_flag == 2)        //设置下限值
  234.                         {
  235.                                 --S_L;
  236.                                 if(S_L < 2)
  237.                                         S_L = 400;       
  238.                         }
  239.                 }

  240.                 /* 报警设置显示 */
  241.                 if(mode_flag == 1)         //显示设置上限值内容
  242.                 {
  243.                         dis_buf[3] = 0x76;                                                //第4位数码管显示字母 H
  244.                         dis_buf[2] = duan_ma[S_H / 100 % 10];         //显示百位数
  245.                         dis_buf[1] = duan_ma[S_H / 10 % 10];        //显示十位数
  246.                         dis_buf[0] = duan_ma[S_H % 10];                        //显示个位数
  247.                 }
  248.                 if(mode_flag == 2)                 //显示设置下限值内容
  249.                 {
  250.                         dis_buf[3] = 0x38;        //第4位数码管显示字母 L
  251.                         dis_buf[2] = duan_ma[S_L / 100 % 10];         //显示百位数
  252.                         dis_buf[1] = duan_ma[S_L / 10 % 10];        //显示十位数
  253.                         dis_buf[0] = duan_ma[S_L % 10];                        //显示个位数
  254.                 }               
  255.         }
  256. }

  257. /* 主函数 */
  258. void main(void)
  259. {
  260.         digDuan = 0x40;                //显示"----"
  261.         digWei1 = 0;
  262.         digWei2 = 0;
  263.         digWei3 = 0;
  264.         digWei4 = 0;
  265.         delayms(1000);                //延时大约1s
  266.         InitTimer0();                //定时器0初始化

  267.         while(1)
  268.         {
  269.                 count();                                        //计算距离
  270.                 if(S>=S_H || S<=S_L)                //如果超出设定的范围,则显示"---"
  271.                 {
  272.                         dis_buf[3] = 0x00;
  273.                         dis_buf[2] = 0x40;                 //显示"---"
  274.                         dis_buf[1] = 0x40;
  275.                         dis_buf[0] = 0x40;       
  276.                         BEEP = 0;                        //蜂鸣器鸣叫
  277.                         delayms(1000);
  278.                 }
  279.                 else
  280.                 {
  281.                         BEEP = 1;                        //关闭蜂鸣器
  282.                         dis_distance();                //显示距离
  283.                 }

  284.                 if(key_scan() == 1)                //如果按下设置键,则进入设置报警功能
  285.                 {
  286.                         BEEP = 0;                        //按键提示音
  287.                         delayms(50);
  288.                         BEEP = 1;
  289.                         delayms(100);
  290.                          key_fuction();                //进入设置报警功能
  291.                 }                       
  292.         }
  293. }


  294. /* 定时器0中断服务函数,5ms进一次本中断,用于数码管扫描 */
  295. void Timer1Interrupt(void) interrupt 3
  296. {
  297.                 TH1 = 0x0EC;                //定时5ms,重新赋值
  298.     TL1 = 0x78;

  299.                 dig_scan(dis_buf);        //数码管显示距离
  300. }


复制代码

Proteus8.17仿真程序: 单片机超声波.zip (149.3 KB, 下载次数: 0)

评分

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

查看全部评分

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

使用道具 举报

沙发
ID:102963 发表于 2025-1-6 12:18 | 只看该作者
这是51单片机,不是STM32单片机。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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