Jetson 使用IIC接口读取TFmini-plus等待传感器数据
最近使用Jetson nx/nano的IIC读取单点激光雷达接口TFmini-plus开发过程记录如下。 首先需要理解IIC通信协议的基本原则可以参考我之前写的博客: https://blog.csdn.net/w1050321758/article/details/108956570?spm=1001.2014.3001.5501
我们将Jetson nano定为主机,TFmini-plus定为IIC协议,我们需要机地址和从机通信协议。 这里我们直接参考北醒光子TFmini-plus您可以看到通信协议的格式。如果我们想从机器上阅读数据,我们需要发送5A 05 00 01 连续几个16进制数据如60引起从机反馈。 从机返回数据后,我们需要根据以下协议分析从机发送的数据:
另外,需要知道从机IIC如下图所示,从机器的默认地址为0x10。 最后,我们也可以从产品说明书中了解其数据顺序(事实上,这部分东西可以从机不给,这是标准的IIC协议的通信时间)。
我们可以观察到主机想要和谐TFmini-plus从机间通信需要以下方式发送数据: (1)首先发送起始位置。如果我们使用标准Linux自带的IIC函数,所以起始位一般不需要我们自己发送,在调用函数时,系统会自动添加起始位。 (2)从机地址 读写位。从机地址一般为7位,加1位读或写形成8位,即IIC一个数据帧通过IIC发送给所有从机器,从机器接收到与其地址相同的数据帧后,将与主机建立连接和通信。读1,写0。所以这个字节可以表示为:从机地址<<1|0(写,0加不加);或者:从机地址;<<1|1(读)。 (3)从机响应位。确认通信正常位置,由从机发出。如果我们调用系统函数,我们通常不需要管理它。 (4)主机和从机通过以上三个步骤建立IIC通信渠道。此时,主机可以通过一个字节和一个字节向从机发送信息。为了实现有意义的通信,这里发送的字节需要参考上述从机通信协议。
最后,如何使用Jetson来实现IIC首先,我们需要知道通信。Jetson的IIC接口,下图可见Jetson nano一共2个IIC外部接口,BOARD 3号和5号以及BOARD 27号和28号,选择一个接口连接自己的设备。 其次,我们需要知道Jetson nx调用IIC函数接口。 Jetson nano内部安装是Linux系统,Linux系统内部提供IIC相关函数。
#include "/usr/include/linux/i2c.h" #include <linux/i2c-dev.h>
事实上,如何使用这些函数?Linux可以通过操作文件来操作IIC设备,因为Linux在系统中,一切都是文件。通过普通文件只需要。ioctl函数声明为IIC设备可以,然后按照操作文件的方式IIC读写设备。 具体的代码如下,参考我上面的讲解,应该可以看懂了,如果不懂的话可以去翻看一下上面的讲解或者补一下IIC通信协议和Linux系统编程相关知识,然后你会突然意识到:
#include <stdio.h> #include <stdint.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> #include "/usr/include/linux/i2c.h" #include <linux/i2c-dev.h> #define LIDAR_SENSOR 0x10 int writeReg(int pt, unsigned char add){
unsigned char w_buff[5];
//地址+写位,写位为0,所以只需要地址左移1位即可
w_buff[0] = add<<1;
//从机的读取协议
w_buff[1] = 0x5a;
w_buff[2] = 0x05;
w_buff[3] = 0x00;
w_buff[4] = 0x01;
w_buff[5] = 0x60;
//文件写操作
if (write(pt, w_buff, 6) != 6){
perror("Failed write to device");
return 1;
}
return 0;
}
int readReg(int pt, unsigned char s_add, char buf[], int size){
char writeBuff[1];
//读,从机地址+读位
writeBuff[0]= (s_add<<1)|1;
//先把读的命令发给从机
if(write(pt, writeBuff, 1)!=1) {
perror("Failed to reset the read address\n");
return 1;
}
//然后利用文件读操作,把读到的数据全部放到buf数组里面
if(read(pt, buf, size)!=size){
perror("Failed to read in the buffer\n");
return 1;
}
return 0;
}
float distance=0;
int main(){
int file;
//打开文件
if((file=open("/dev/i2c-1", O_RDWR)) < 0) {
perror("failed to open the bus\n");
return 1;
}
//声明为IIC设备文件
if(ioctl(file, I2C_SLAVE, LIDAR_SENSOR) < 0) {
perror("Failed to connect to the sensor\n");
return 1;
}
//存储接收到的数据
char distance_buff[9]={
0};
while(1)
{
//先写,引起从机的反馈
if(writeReg(file, LIDAR_SENSOR)==1){
return 1;
}
//再读取从机反馈
if(readReg(file, LIDAR_SENSOR, distance_buff,9)==1){
return 1;
}
//从从机反馈的数据里面根据从机的协议提取我们想要的东西
distance=short(distance_buff[2]|(distance_buff[3]<<8))*0.01;
printf("distance: %.2f\n",distance);
}
close(file);
return 0;
}