• STC11F04E——HC-SR04


    前几天做了一下电子工艺实习,实现了在数码管上显示温度和时间的功能,还写了篇博客。但当时没有注意到,这款PCB还设计了超声波测距的功能。在实现该功能后,我决定不再增改原来的文章,而写下这篇文章描述HC-SR04的控制方法。

    声明1:我是一个单片机小白,下面有任何说的不对的地方,恳请各位指正,谢谢。
    2. 我还做了一个使用数码管滚动显示学号的程序,就不再写成博客了,代码放在了GitHub

    我已将该项目上传到GitHub,项目地址为: STC11F04E项目。 代码开源,欢迎测试

      单片机实验平台简介等信息,请阅读上一篇文章

    一、HC-SR04

    1.1 简介

      HC-SR04超声波测距模块提供2cm~4m的非接触式测距功能,测距精度可达3mm。

    1.2 电气参数

    电气参数 HC-SR04模块
    工作电压 DC 5V
    工作电流 15mA
    工作频率 40Hz
    最远射程 4m
    最近射程 2cm
    测量角度 15°
    输入触发信号 10us的TTL高电平脉冲
    输出回响信号 输出TTL高电平,时间与射程成正比
    规格尺寸 45×20×15mm

    1.3 时序图

    在这里插入图片描述

    图1 HC-SR04时序图

    通过阅读时序图可以看出HCSR04的工作原理:

    1. 采用IO口TRIG触发测距,给至少10us的高电平信号
    2. 模块自动发送8个40khz的方波,自动检测是否有信号返回
    3. 有信号返回,通过IO口ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间
    4. 测试距离 = (高电平时间 * 声速(340M/S)) / 2

      通过阅读时序图和工作原理,可以了解到:当单片机给TRIG端口一个 >10us 的高电平信号之后,就触发了HC-SR04传感器。此时,HCSR04会自动发出8个4KHz的方波信号,同时自动检测是否有方波信号返回。如果传感器接收到了信号回复,就会通过ECHO输出一个高电平的回响信号,而这个回响信号持续的时间就是超声波从发出到返回所用的时间。得到这个回响时间(t)之后,将其乘以超声波声速(v),就是超声波从发出到接收所含经过的路程(s)。这个路程除以2,就是传感器到被测物体之间的距离。

      虽然时序看起来比较简单,但其实控制它的重点,是对单片机定时器/计时器的控制。为什么呢?因为回响信号输出时间的计算需要用到定时器。因为第一次使用计时器,我大致了解了一下单片机定时器/计时器的使用方式。

    • 1个机器周期 = 12个晶振周期。即 TM=12fosc ext{T}_M =dfrac{12}{ ext{f}_ ext{osc}}

    TM ext{T}_M 表示机器周期
    fosc ext{f}_ ext{osc}表示系统晶振的频率

    • 定时时间 = 计数值 x 机器周期。TC=X×TM ext{T}_C=X× ext{T}_M

    TC ext{T}_C 表示定时时间
    XX 表示计数器计的个数

    在STC官方手册里指出:

      STC11/10xx系列单片有2个定时器,定时器0和定时器1,与传统8051的定时器完全兼容,也可以设置为1T模式,当在定时器1做波特率发生器时,定时器0可以当两个8位定时器用。
      STC11/10xx系列单片机是1T的单片机,为兼容传统8051,定时器0和定时器1复位后是传统12T的速度,即12分频,这是为了兼容传统 。但也可不进行12分频,通过设置新增的特殊功能寄存器AUXR ,可以将T0,T1设置为1T。普通111条机器指令是固定的,快3到24倍,无法改变。

      也就是说,我这款单片机在上电之后,就默认初始化成了12分频的模式(可以通过AUXR调整分频模式),即 TM=12fosc ext{T}_M =dfrac{12}{ ext{f}_ ext{osc}}。通过该公式即可算出晶振一次所消耗的时间。为了保证计数范围,需要设置TMOD计时方式控制寄存器,使用定时器0计时方式1,也就是用两个8位的组成一个16位的计时器。现在知道了这些知识,就可以着手编写程序了。

    二、程序编写

      下面同样只列出主要的测距程序,项目工程文件已上传至GitHub,STC11F04E项目

    /**********************************************************
    *  函数名称:超声波测距函数
    *  修改日期:2019-10-9
    *  修改人:ZhangHJ
    *  说明:1. 采用IO口TRIG触发测距,给至少10us的高电平信号
    *		 2. 模块自动发送8个40khz的方波,自动检测是否有信号返回
    *		 3. 若有信号返回,通过IO口ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间
    *		 4. 测试距离 = (高电平时间*声速(340M/S))/2
    ***********************************************************/
    float GetDistance()
    {
    	float dist = 0.0f;
    	uint count = 0;
    	
    	TMOD = 0x01;						// 计时器0方式1	(16位计数器,TL0、TH0全用)
    	TH0 = TL0 = 0;						// 装入初值
    	Trig = 1;							// 打开触发
    	delay_12us();						// 延时一会儿,保证延时10us时间
    	Trig = 0;							// 关闭触发
    	while(!Echo);						// 测距过程中
    	TR0 = 1;							// 打开中断
    	while(Echo);						// 等待输出电平结束
    	TR0 = 0;							// 关闭中断
    	count = (TH0 << 8) | TL0;			// 读取16位计时器里的数字
    	dist = CYCLE * count * 0.017;		// 0.017cm/us
    	return dist;						// 返回值是一个浮点型数据
    }
    
    1. 首先设置TMOD定时计数器工作模式寄存器,将其设置成计时器0,工作方式1,表示使用的是两个8位的寄存器计数,高八位是TH0,低八位是TL0。将其装入初值为0。
    2. 接着设置Trig触发输入端为高电平,延时12us确保触发成功,然后将其重置为0。此时,传感器已经开始工作。
    3. 等待回响输入端置为低电平,保证记录一次完整的回响信号时间。
    4. 设置TR0为1,打开中断计时器,开始计数。
    5. 当回响信号为高电平时,一直计数,直到回响信号重新回到低电平,关闭计时器。
    6. 现在两个8位的计时器已经记录好数值了,通过移位操作,将高八位和低八位组成16位变量count。
    7. 通过上面分析的公式,可以算出传感器到被测物体之间的距离。
    8. 最后返回一个表示距离的浮点数据。

      其中需要注意的是,计算距离的公式中,需要用到每次计数器计数的时间,也就是上面分析过的一个机器周期。在程序起始位置进行机器周期的宏定义:

    #define FOSC 11059200L					// 晶振频率11.0592MHz(s)
    #define CYCLE (12000000.0/FOSC)			// 系统机器周期(us) 
    

    FOSC : 表示系统晶振频率,我的单片机使用的是11.0592MHz的晶振,所以定义为11059200L
    CYCLE :表示机器周期,按照之前的公式, 12/FOSC 即为系统周期(单位为秒),再乘以106 ext{10}^6,就是以us为单位的机器周期。

      通过数码管显示函数,格式化控制该函数返回的浮点数值,即可实现测距的结果显示。

    三、程序测试

      因为超声波模块需要一个比较稳定的测试环境,所以我做了一个超声波模块测距装置。利用游标卡尺得到正确的距离数值(实际值),与单片机数码管显示的数值(测试值)进行比较,可以得出超声波测距装置是否准确。
    在这里插入图片描述

    图2 超声波测距装置

    上图中,可以看出游标卡尺的数值大概是15cm左右,单片机显示的数值也在15.0附近(单位:cm)。现在使用示波器,测量一下Echo回响信号的高电平时间,如下图3所示。
    在这里插入图片描述

    图3 示波器测量回响信号时间

      可以看到。高电平时间 ΔxDelta x 为872.0us,这样按照公式算一下距离:

    距离 = 回响信号时间(us) * 0.034(cm/us) ÷ 2
       = 872(us) * 0.017(cm/us)
       = 14.824(cm)

      手动计算的数值与单片机上的数值接近,但并不是完全相等,原因是:这一次上升沿的时间也许并不是我们此次单片机显示的时间对应的高电平。。有点绕嘴。因为示波器上的这一段高电平,是我在好几个周期的高电平中,随便挑的一个高电平,与单片机显示的数值就近就是正常的了。应该说清楚了吧?
    点击此处查看演示视频

    四、改进

      超声波测距还有很多改进的空间,比如,为了保持测试数据的稳定,可以通过求平均值的方式进行改进。另外中断计时器应该还可以进行改进。。。
      先写到这里吧,以后如果再有好的想法再来记录。

  • 相关阅读:
    段落某些子段高量
    CSS 知识点
    PHP 表单与音频知识点及使用
    PHP 标签、表格的知识点与超链接的结合使用
    PHP课程第一天知识点
    java ArrayList集合
    java 引用数据类型(类)
    java 方法重载
    java 方法
    java 二维数组
  • 原文地址:https://www.cnblogs.com/ZHJ0125/p/12904508.html
Copyright © 2020-2023  润新知