;利用超声波测距,都是统计超声波发出_到_接收的时间,然后再换算成距离
;对于时间的统计,通常都是使用计数器完成
;超声波发射后,启动计数器,收到回波后,取出计数值进行换算
;
;51单片机内部的计数器,是对机器周期进行计数的
;它的数值,和距离之间,有什么关系呢 ?
;--------------------------------------------------------
;当晶振频率是 12MHz,它的机器周期正好是 1us
;所以,单片机计数器中的计数值即代表微秒的个数
;
;假设声波的速度是 333m/s,那么,用微秒数除以 6,马上即可得到距离的毫米数
;即,计数器中的值为: 0~65535,除以 6 后,距离即为: 0~10922(mm)
;
;推导如下:
;
; 1s 对应路程 0.333 km = 1/3 km
; 1ms 对应路程 0.333 m = 1/3 m
; 1us 对应路程 0.333 mm = 1/3 mm
;
; 1us : 距离 1/6 mm
; 6us : 距离 1 mm
;
; 1/6,即为每个机器周期T(即微秒)代表的距离数值(mm)
;
;--------------------------------------------------------
;当晶振频率是 11.0592MHz,它的机器周期则是 1.085us
;(T = 12 / 11.0592 = 1 / 0.9216 = 1.0850694444...us)
;
;时间长了,路程就远了,如果仍然按照除以 6 计算,得出的结果将偏小
;仍然这么算,好像是把声速降低了,降为:0.3072mm/us
;
;那么,用机器周期的个数乘以 1.085/6,才能得出正确的距离毫米数值
;
; 1.085/6,即为每个机器周期T(@11.0592MHz)的距离(mm)
;
;--------------------------------------------------------
;空气中的声速和环境温度、气压都有关系,并不一定总是 333m/s
;一般来说,310~345m/s 都是合理的数值
;因此,计算距离,算法并不是唯一的
;
;在网上,可以买到多种超声波测距的实验板,其中的程序的算法,花样百出
;有除以 59 (或 60) 得出厘米数的;也有先乘以 17,再除以 100 的;
;还有一个是乘以 12,再除以 58 的,这么算,其声速已经是 400 多米了 !
;只是因为它的测距范围较小,误差虽大,也难以看出来。
;
;其实,除以 6,是最简单、准确的算法
;已经用了多年,在网上却没有见到一个 ! 呵呵
;--------------------------------------------------------
;很多人都是用 C 语言编程,编程虽省事,单片机执行起来却要多费时
;网上的多数程序,算出来距离,再送去显示,都要用几个甚至上百毫秒
;这么低的效率,使得多检测几次取平均值的想法,都不好实现
;
;其实,用汇编语言编程,效率是最高的
;两个字节除以 6,编写一个两字节除以一字节的程序,仅仅用 300 多微秒(12MHz)即可
;
;两个字节乘以 1.085/6,这就要费点心思,仔细琢磨琢磨算法了...
;最好是把分子、分母同时扩大多少多少倍,找个好算的数字...
;除以 6,并非是容易计算的,学过二进制的都知道,右移一位,就是除以 2
;除以 2、4、...,2 的整数倍,计算起来才是最简单的
;除以 256,那就最简单了
;
;好吧,那就先乘以 43,再除以 256,这就和乘以 1/6 相差无几了
;这种算法,声速是 335m/s;在 11.0592MHz 时,声速相当于 309.6m/s,偏小
;
;乘以 1.085/6,又该怎样算呢?
;看看下表吧:
;---------------------------------------------------
; 算法 | 结果距离(mm) | 相当于声速(m/s)
;----------+--------------+---@12MHz----+-@11.0592--
; 1 / 6 | 0.16666... | 333.333... | 307.2
; 41 / 256 | 0.16015625 | 320.3125 | 295.2
; 42 / 256 | 0.1640625 | 328.125 | 302.4
; 43 / 256 | 0.16796875 | 335.9375 | 309.6
; 44 / 256 | 0.171875 | 343.75 | 316.8
; 45 / 256 | 0.17578125 | 351.5625 | 324.0
; 46 / 256 | 0.1796875 | 359.375 | 331.2
; 47 / 256 | 0.18359375 | 367.1875 | 338.4
; 48 / 256 | 0.1875 | 375.00 | 345.6
; 49 / 256 | 0.19140625 | 382.8125 | 352.8
;---------------------------------------------------
;
;这个表,表示出了计算因子和声速的关系
;这个表,是用 EXCEL 算出来的,百度的格式有点乱,能看明白吗 ?
;如果是 12MHz,可以乘以 42、43 或 44
;如果是 11.0592MHz,可以乘以 46、47 或 48
;在表中,可看出不同的取值所对应的声速
;
;把两个字节的计数值,乘以 47,可以得到三个字节
;除以 256,那就太简单了,算都不用算,直接把最低 8 位扔掉就完了
;剩下的两个字节,就是乘以 47,再除以 256 的结果
;程序如下:
;--------------------------------------------------------
VAR_SOUND EQU 47 ;42, 43, 44 适用于 12MHz
;46, 47, 48 适用于 11.0592MHz
;入口:R2R3 = 0~65535
;出口:R2R3 = R2R3 * 47 / 256 ≈ R2R3 * 1.085/6
R23DIV6:
MOV A, R3
MOV B, #VAR_SOUND
MUL AB
; MOV R3, A ;低八位就不要了
MOV R3, B ;R3 = (R3 * 47)的高八位
MOV A, R2
MOV B, #VAR_SOUND
MUL AB ;R2 * 47
ADD A, R3 ;加上刚才的
MOV R3, A ;R3 = (R2R3 * 47)的中八位
CLR A
ADDC A, B
MOV R2, A ;R2 = (R2R3 * 47)的高八位
RET ;全部程序共 23T
;--------------------------------------------------------
;这是计算距离的最快算法
;仅仅才用了 23 微秒(12MHz),就能达到别人需要几千微秒才能达到的目的
;
;这个程序,甚至比前面所说的除以 6,还要快近十倍
;
;程序中,VAR_SOUND 的数值,可以根据实际情况的需要进行选择
;也可以用一个寄存器,根据当时检测的温度进行变化,进行温度修正
;
;本程序,距离计算的精度是最高的
;合理选择 VAR_SOUND 的值,如 46、47、48,再按照这个算法来计算
;理论上的量化误差是 (1/256)/2 = 1/512,即小于千分之二
;其它的算法,虽然各有各的理由,但是计算的结果,精度绝不会比这个用汇编写的高
;--------------------------------------------------------