在测量电梯轨距的项目用到了这个模组,我这个是量程8m的,客服只给了两个文档,没有代码,这里分享最简单的三种使用方法,分别是使用官方上位机,串口通信,IIC通信
简单介绍一下模块,更多细看请查看官方文档
这里需要注意供电电压为3.7V-5.2V,有很可能没注意到而直接使用3.3V供电,我是使用5V供电
模块的通信方式有两种,UART和IIC。串口的波特率默认为115200,可发送指令更改,IIC通信速率400k以内,默认从机地址为0x10。
他的接口间距是1.25mm,发货时带了一根双头mx1.25 6p的线,如果想在单片机上调试,需要买一根mx1.25转杜邦线
如果你跟我一样比较急,就直接暴力拆解,焊杜邦线上去,然后打胶
第一种方法,使用官方上位机,直接按照步骤操作即可。连接CH340和模块,这里需要模块启动为UART模式,注意查看上面的引脚图,将5脚悬空或接3.3V即可。然后选择端口,波特率默认为115200,点击connect,就可以看到波形。
第二种方法,不使用上位机,直接使用串口助手或者单片机接收数据。在默认配置下,波特率115200,打开串口
在默认情况下模块串口发送的数据格式为为第一种,这种格式不便于我们在串口助手直观的查看距离数据,单片机通过串口获取数据的步骤也会更加复杂,因此我们选择第二种格式,直接发送距离数据的字符串。发送指令的方式在文档中有介绍,设置为PIX输出需要依次发送 5A 05 05 02 00
5A是帧头,第一个05是指令长度,第二个05是ID,第5个设置项,即设置输出格式,02代表设置第二种输出格式,即PIX输出,00是Check_su
发送这些数据以后,将接收模式改为文本模式就可以接收到数据了
模块掉电以后,再次上电,又会变成默认的配置,如果每次使用的配置无需更改,可以发送保存当前配置指令进行保存,这样再次上电配置也不会改变,如果遇到问题也可以发送指令恢复出厂设置
第三种方法,用单片机通过IIC协议读取距离数据,需要将5脚接地,配置模块为IIC工作模式
从机地址0x10,写操作地址0x20,读操作地址0x21,默认配置下位连续测距模式,只需要读出0x00寄存器的低位数据和0x01寄存器的高位数据,就能够计算出距离,话不多说,上代码,使用stc89c52rc单片机任意两个GPIO模拟IIC通信。
TF_Luna.c
#include <REGX52.H>
#include "TF_Luna.h"
#include "intrins.h"
#include "UART.h"
static unsigned char read_ready=0;
void delay() //8us左右的延时函数
{
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
}
void start()
{
sda=1;
delay();
scl=1;
delay();
sda=0;
delay();
} //起始函数
void stop()
{
sda=0;
delay();
scl=1;
delay();
sda=1;
delay();
} //停止函数
void ack()
{
unsigned char i=0;
scl=1;
delay();
while((sda==1)&&(i<200))
{
i++;
}
scl=0;
delay();
} // 应答函数,在第9个脉冲时,当scl=1,sda应给与一个低电位作为应答
// 如若一直没有应答,则在一段时间后,默认其应答。
void i2c_write(unsigned char dat)
{
unsigned char temp1,i;
temp1=dat;
for(i=0;i<8;i++)
{
temp1<<=1;
scl=0;
delay();
sda=CY;
delay();
scl=1;
delay();
}
scl=0;
delay();
sda=1; //一个字节发送后,应将sda拉高,scl拉低,为应答做准备。
delay();
} //当temp1左移一位时,溢出的那一位将保存在CY中。一个脉冲读一位数。
unsigned char i2c_read()
{
unsigned char temp,i;
scl=0;
delay();
sda=1;
delay();
for(i=0;i<8;i++)
{
scl=1; //读取时,scl=1时,数据sda才是稳定的。
delay();
temp=(temp<<1)|sda;//将temp左移一位再和sda相或,即可将sda保存到temp中
scl=0;
delay();
}
return temp;
}
/*
*发送一个字节的数据到指定寄存器
*/
void Write_Byte(unsigned char reg,unsigned char dat)
{
start();
i2c_write(0x20);
ack();
i2c_write(reg);
ack();
i2c_write(dat);
ack();
stop();
}
/*
*读指定寄存器的值
*/
unsigned char Read_Byte(unsigned char reg)
{
unsigned char res;
start();
i2c_write(0x20);
ack();
i2c_write(reg);
ack();
delay();
start();
i2c_write(0x21);
ack();
res=i2c_read();
scl=0;
sda=1;
delay();
scl=1;
delay();
scl=0;
stop();
return res;
}
void FT_Luna_Init(void)//初始化配置
{
Write_Byte(0x23,0x00);//连续工作模式
}
unsigned int TF_Luna_read(void)//获取距离
{
char s1[16];
unsigned int temp;
unsigned char low,high;
start();
i2c_write(0x20);
ack();
i2c_write(0x00);
ack();
delay();
start();
i2c_write(0x21);
ack();
while(ready==0);
low=i2c_read();
scl=0;
sda=1;
delay();
scl=1;
delay();
scl=0;
stop();
start();
i2c_write(0x20);
ack();
i2c_write(0x01);
ack();
delay();
start();
i2c_write(0x21);
ack();
while(ready==0);
high=i2c_read();
scl=0;
sda=1;
delay();
scl=1;
delay();
scl=0;
stop();
temp = ((unsigned int)high<<8)|low;
return temp;
}
TF_Luna.h
#ifndef __TF_LUNA_H
#define __TF_LUNA_H
sbit scl=P1^0;
sbit sda=P1^1;
sbit ready=P1^7;
void FT_Luna_Init(void);
unsigned int TF_Luna_read(void);
#endif
main.c
#include <REGX52.H>
#include "UART.h"
#include "TF_Luna.h"
#include "string.h"
#include "stdio.h"
unsigned int dis;
char ss[16];
void main()
{
UART_Init();
FT_Luna_Init();
UART_SendString("distance test");
while(1)
{
dis = TF_Luna_read();
sprintf(ss,"high:%dcm\r\n",dis);
UART_SendString(ss);
}
}