目录
第一部分、前言
1、TOF10120激光测距模块的基本知识
2、TOF的引脚
3、与单片机的接线
第二部分、工程代码
1、代码功能描述
2、tof.h文件
3、tof.c文件
4、main.c文件
第三部分、总结
1、TOF10120的数据参考手册
2、完整的工程代码
模块最佳距离测量范围:10cm~180cm。这里的范围是指这个模块在这个距离范围内测到的数据都非常准确,而不是指我只能测量这个范围的距离,其它距离测量不了,超过这个距离范围,误差会大一点而已。
工作电压:3.3V~5V都可以,不容易烧。
通讯协议:这个模块支持串口协议和IIC协议,串口协议默认波特率9600,但是我这个工程是利用IIC协议调试的,因为单片机的串口毕竟有限。
下图是我模块的样子,从左到右的引脚对应如下表格
绿线 | SCL |
蓝线 | SDA |
白线 | TXD |
黄线 | RXD |
红线 | VCC |
黑线 | GND |
本次调试利用的是IIC协议,没有用到串口,因此白线和黄线就可以不要了,后来我直接把这根线直接给剪掉了。
IIC协议是模拟出来,绿线SCL —— PB12;蓝线SDA —— PB13,注意:单片机用的核心板C8T6。
串口一不断将距离数据打印在电脑的串口助手,每隔1s打印一次,LED闪烁。注意:这里得到的距离数据已经是模块内部滤波后的数据,这种得到的数值比较平滑。如果想要得到实时距离,需要更改寄存器的值,这里请自行参考TOF10120的技术手册。
#ifndef __TOF_H
#define __TOF_H
#include "sys.h"
// 绿线SCL —— PB12
// 蓝线SDA —— PB13
//管脚宏定义
#define I2C_SCL_PIN GPIO_Pin_12
#define I2C_SCL_PORT GPIOB
#define I2C_SCL_CLK RCC_APB2Periph_GPIOB
#define I2C_SDA_PIN GPIO_Pin_13
#define I2C_SDA_PORT GPIOB
#define I2C_SDA_CLK RCC_APB2Periph_GPIOB
//IO操作函数
#define USERI2C_SCL_1 GPIO_SetBits(I2C_SCL_PORT, I2C_SCL_PIN)
#define USERI2C_SCL_0 GPIO_ResetBits(I2C_SCL_PORT, I2C_SCL_PIN)
#define USERI2C_SDA_1 GPIO_SetBits(I2C_SDA_PORT, I2C_SDA_PIN)
#define USERI2C_SDA_0 GPIO_ResetBits(I2C_SDA_PORT, I2C_SDA_PIN)
#define USERI2C_READ_SDA (GPIO_ReadInputDataBit(I2C_SDA_PORT, I2C_SDA_PIN))
#define I2C_DEVID 164//0XA4
//函数声明
void UserI2c_Start(void);
void UserI2c_Init(void);
unsigned char SensorWritenByte(unsigned char Devid, unsigned char *TXBuff, unsigned char SubAdd, unsigned char Size);
unsigned char SensorReadnByte(unsigned char Devid, unsigned char *RXBuff, unsigned char SubAdd, unsigned char Size);
#endif
#include "tof.h"
#include "delay.h"
#include "usart.h"
//变量定义
unsigned char devid;
unsigned int i2cread_interval;
unsigned char dirt_send_flag;
unsigned char dirt_detection_flag;
unsigned short int length_val;
unsigned short int length_aveval;
/*******************************************************************************
* Function Name : UserI2c_Start
* Description : sck stable in H,sda falling edge
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void UserI2c_Start(void)
{
USERI2C_SDA_1;
delay_us(5);
USERI2C_SCL_1;
delay_us(5);
USERI2C_SDA_0; //START:when CLK is high,DATA change form high to low
delay_us(5);
USERI2C_SCL_0; //钳住I2C总线,准备发送或接收数据
delay_us(30); //加30uS延时
}
/*******************************************************************************
* Function Name : UserI2c_Stop
* Description : sck stable in H,sda rising edge
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void UserI2c_Stop(void)
{
USERI2C_SCL_0;
USERI2C_SDA_0;//STOP:when CLK is high DATA change form low to high
delay_us(5);
USERI2C_SCL_1;
delay_us(5);
USERI2C_SDA_1; //发送I2C总线结束信号
delay_us(5);
delay_us(30); //加30uS延时
}
/*******************************************************************************
* Function Name : UserI2c_Wait_Ack
* Description : the 9th clock pulse period wait ack
* Input : None
* Output : None
* Return : =0有ack
* : =1无ack
*******************************************************************************/
unsigned char UserI2c_Wait_Ack(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
unsigned short int ucErrTime = 0;
unsigned char RetValue;
//SDA设置为输入
GPIO_InitStructure.GPIO_Pin = I2C_SDA_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; //上拉输入
GPIO_Init(I2C_SDA_PORT, &GPIO_InitStructure);
USERI2C_SCL_0;
delay_us(5);
USERI2C_SCL_1;
ucErrTime = 10000;
while( ucErrTime-- > 0 )
{
if(USERI2C_READ_SDA )
{
RetValue = 0;
}
else
{
RetValue = 1;
break;
}
}
delay_us(1);
USERI2C_SCL_0;//时钟输出0
//SDA线输出
GPIO_InitStructure.GPIO_Pin = I2C_SDA_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //配置IO的输出速度为50MHz,高低电平状态最高切换频率
GPIO_Init(I2C_SDA_PORT, &GPIO_InitStructure);
USERI2C_SDA_0;
delay_us(30); //加30uS延时
return RetValue;
}
/*******************************************************************************
* Function Name : useri2c_ack
* Description : the 9th clock pulse period, the receiver pulls sda low to
* : acknowledge the receipt of the eight data bits.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void useri2c_ack(void)
{
USERI2C_SCL_0;
USERI2C_SDA_0;
delay_us(5);
USERI2C_SCL_1;
delay_us(5);
USERI2C_SCL_0;
delay_us(30); //加30uS延时
}
/*******************************************************************************
* Function Name : useri2c_nack
* Description : no acknowledge the receipt of the eight data bits.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void useri2c_nack(void)
{
USERI2C_SCL_0;
USERI2C_SDA_1;
delay_us(5);
USERI2C_SCL_1;
delay_us(5);
USERI2C_SCL_0;
delay_us(30); //加30uS延时
}
/*******************************************************************************
* Function Name : UserI2c_Send_Byte
* Description : write one data to i2c bus
* Input : txd-data
* Output : None
* Return : None
*******************************************************************************/
void UserI2c_Send_Byte(unsigned char txd)
{
unsigned char t;
USERI2C_SCL_0;//拉低时钟开始数据传输
delay_us(5);
for(t = 0; t < 8; t++)
{
if((txd & 0x80) >> 0)
USERI2C_SDA_1;
else
USERI2C_SDA_0;
txd <<= 1;
delay_us(5);
USERI2C_SCL_1;
delay_us(5);
USERI2C_SCL_0;
}
}
/*******************************************************************************
* Function Name : UserI2c_Read_Byte
* Description : read one data from i2c bus
* Input : None
* Output : None
* Return : receoved data
*******************************************************************************/
unsigned char UserI2c_Read_Byte(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
unsigned char i, receive = 0;
//SDA设置为输入
GPIO_InitStructure.GPIO_Pin = I2C_SDA_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; //上拉输入
GPIO_Init(I2C_SDA_PORT, &GPIO_InitStructure);
USERI2C_SDA_1;
USERI2C_SCL_0;
delay_us(30);
for(i = 0; i < 8; i++ )
{
receive <<= 1;
USERI2C_SCL_1;
delay_us(5);
if(USERI2C_READ_SDA)
receive++;
USERI2C_SCL_0;
delay_us(5);
}
USERI2C_SCL_0;
//SDA线输出
GPIO_InitStructure.GPIO_Pin = I2C_SDA_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(I2C_SDA_PORT, &GPIO_InitStructure);
return receive;
}
/**************************************************************************************************************************/
/*******************************************************************************
* Function Name :SensorWritenByte
* Description : Sensor read api.
* Input : devid-设备i2c地址
* : *TXBuff-the address of the buffer which to write.
* : SubAdd-the address read to
* : Size-the buffer size
* Output : None
* Return : None
*******************************************************************************/
unsigned char SensorWritenByte(unsigned char Devid, unsigned char *TXBuff, unsigned char SubAdd, unsigned char Size)
{
unsigned char i = 0;
UserI2c_Start();
UserI2c_Send_Byte( Devid | 0x00 );
if( 0 == UserI2c_Wait_Ack() )
{
UserI2c_Stop();
return 0;
}
UserI2c_Send_Byte( SubAdd & 0xff );
if( 0 == UserI2c_Wait_Ack() )
{
UserI2c_Stop();
return 0;
}
for ( i = 0; i < Size; i++)
{
UserI2c_Send_Byte( TXBuff[Size - i - 1] );
if( 0 == UserI2c_Wait_Ack() )
{
UserI2c_Stop();
return 0;
}
}
UserI2c_Stop();
return 1;
}
/*******************************************************************************
* Function Name : SensorReadnByte
* Description : Sensor read api.
* Input : devid-设备i2c地址
* : *RXBuff-the address of the buffer which stores read content.
* : SubAdd-the address read from
* : Size-the buffer size
* Output : None
* Return : None
*******************************************************************************/
unsigned char SensorReadnByte(unsigned char Devid, unsigned char *RXBuff, unsigned char SubAdd, unsigned char Size)
{
unsigned char i = 0;
UserI2c_Start();
// UserI2c_Send_Byte( Devid | 0x00 ); //实时距离地址
UserI2c_Send_Byte( Devid | 0x04 ); //滤波距离地址
if( 0 == UserI2c_Wait_Ack() )
{
UserI2c_Stop();
return 0;
}
UserI2c_Send_Byte( SubAdd & 0xff );
if( 0 == UserI2c_Wait_Ack() )
{
UserI2c_Stop();
return 0;
}
UserI2c_Stop();
UserI2c_Start();
//UserI2c_Send_Byte( Devid | 0x01 ); //实时距离地址
UserI2c_Send_Byte( Devid | 0x05 ); //滤波距离地址
if( 0 == UserI2c_Wait_Ack() )
{
// UserI2c_Stop();
// return 0;
}
for ( i = 0; i < Size; i++)
{
RXBuff[Size - i - 1] = UserI2c_Read_Byte();
if((i + 1) == Size)
useri2c_nack();
else
useri2c_ack();
}
UserI2c_Stop();
return 1;
}
/*******************************************************************************
* Function Name : UserI2c_Init
* Description : config i2c driver gpio
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void UserI2c_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( I2C_SCL_CLK, ENABLE );
RCC_APB2PeriphClockCmd( I2C_SDA_CLK, ENABLE );
GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(I2C_SCL_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = I2C_SDA_PIN;
GPIO_Init(I2C_SDA_PORT, &GPIO_InitStructure);
GPIO_SetBits(I2C_SCL_PORT, I2C_SCL_PIN); //SCL 输出高
GPIO_SetBits(I2C_SDA_PORT, I2C_SDA_PIN); //SDA 输出高
/************************/
/**配置TOF内部寄存器*****/
/**代码改于2022/6/1_dpt**/
/************************/
devid=I2C_DEVID; //设置I2C从机地址 默认164 0xA4
dirt_send_flag=1; //=0串口主动发送 =1串口或者I2C被动读取
SensorWritenByte(devid,(unsigned char *)&dirt_send_flag, 0x09, 1); //0x09设置距离发送方式 1 主机去读取 0 模块发送
delay_ms(100);
dirt_detection_flag=0; //=0滤波值 =1实时值
SensorWritenByte(devid,(unsigned char *)&dirt_detection_flag, 0x08, 1); //0x08设置 距离数据模式 1 实时值 0滤波值
delay_ms(100);
}
/************************END OF FILE*************************/
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"
#include "tof.h"
//变量定义
extern unsigned char devid; //I2C从机地址声明
extern unsigned short int length_aveval; //用来存储长度数据
int main()
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断控制器分组设置
delay_init(); //初始化很重要//用不了的函数一般都是没有初始化 TOF模拟IIC用到,所以放到前面
/*串口*/
Usart1_Init(115200);
/*LED*/
LED_Init();
/*Tof*/
UserI2c_Init(); //TOF模块初始化引脚,配置寄存器
while(1)
{
LED0 = 0;
delay_ms(500);
LED0 = 1;
delay_ms(500);
SensorReadnByte(devid,(unsigned char *)&length_aveval, 0x04,2);//注意:这里我已更改为滤波距离
printf("%d\r\n",length_aveval);
}
}
这是博主看的数据手册,我这里面的很多东西都是从数据手册搬运过来,手册链接:TOF10120数据参考手册(无需积分下载)。
这是博主的完整的代码,可以免费下载,但是你是不是要点个赞,然后再下载?STM32驱动TOF10120激光测距模块的完整代码