i2c - 通过 I2C 读取 Ettus E310 气压计,始终返回无此类设备或地址 (-1)
问题描述
我一直在尝试为 E310 上的BMP 180气压计和温度传感器编写 I2C 设备驱动程序(如原理图的第 9 页所示)。我的代码基于bosch给出的示例驱动程序。
驱动需要函数指针来阻塞读写,以及休眠,这基本上是唯一的原始代码:
int8_t user_i2c_read(uint8_t dev_id, uint8_t reg_addr,uint8_t *data, uint16_t len)
int8_t user_i2c_write(uint8_t dev_id, uint8_t reg_addr,uint8_t *data, uint16_t len)
void user_delay_ms(uint32_t period)
我遇到的问题是这个驱动程序(以及我编写的更简单的仅 SMBUS 命令程序)总是无法读取或写入 i2c 地址 0x77,传感器应该位于总线上的位置。
设备 ID 0x77 的 readBytes:-1 - 没有这样的设备或地址
即使我的代码似乎适用于其他设备所在的位置(尽管我没有做的只是 ping 它们)
运动传感器:
设备 ID 0x69 的 readBytes:0 - 成功
温度感应器:
设备 ID 0x19 的 readBytes:0 - 成功
我想知道我的代码有什么问题导致设备完全没有响应,或者我缺少什么硬件配置来解释在 0x77 时与气压计缺乏通信。
我注意到 BMP-180 气压计放置在 Gyro MPU-9150的辅助 i2c 上,但接线和数据表让我认为它处于直通模式而不是主模式。只是我的一个想法。
这是我拥有的与bmpDriver交互的所有代码。
编译如下
gcc test.c -o test -std=c11 -D _DEFAULT_SOURCE
#include "bmp280.c"
#include <linux/i2c-dev-user.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
int8_t user_i2c_read(uint8_t dev_id, uint8_t reg_addr,uint8_t *data, uint16_t len){
int file;
file = open("/dev/i2c-0", O_RDWR);
if(file < 0)
{
printf("Failed to open /dev/i2c-0\n");
close(file);
return -1;
}
if(ioctl(file, I2C_SLAVE, dev_id) < 0)
{
printf("ioctl failed for /dev/i2c-0 at %x - %s\n", dev_id, strerror(errno));
close(file);
return -2;
}
int readBytes;
readBytes = i2c_smbus_read_block_data(file, reg_addr, data);
printf("readBytes for device ID 0x%x: %d - %s\n", dev_id, readBytes, strerror(errno));
close(file);
return readBytes;
}
int8_t user_i2c_write(uint8_t dev_id, uint8_t reg_addr,uint8_t *data, uint16_t len){
int file;
file = open("/dev/i2c-0", O_RDWR);
if(file < 0)
{
printf("Failed to open /dev/i2c-0\n");
close(file);
return -1;
}
if(ioctl(file, I2C_SLAVE, dev_id) < 0)
{
printf("ioctl failed for /dev/i2c-0 at %x - %s\n", dev_id, strerror(errno));
close(file);
return -2;
}
int writeBytes;
uint8_t shortLen = len;
writeBytes = i2c_smbus_write_block_data(file, reg_addr, shortLen, data);
printf("writeBytes for device ID 0x%x: %d - %s\n", dev_id, writeBytes, strerror(errno));
close(file);
return writeBytes;
}
void user_delay_ms(uint32_t period){
unsigned int sleep = period;
usleep(sleep * 1000);
}
int main(){
int8_t rslt;
struct bmp280_dev user_bmp;
user_bmp.dev_id = BMP280_I2C_ADDR_SEC;
user_bmp.intf = BMP280_I2C_INTF;
user_bmp.read = user_i2c_read;
user_bmp.write = user_i2c_write;
user_bmp.delay_ms = user_delay_ms;
rslt = bmp280_init(&user_bmp);
if (rslt == BMP280_OK) {
printf("Device found with chip id 0x%x\n", user_bmp.chip_id);
}
else {
printf("Device not found, exiting...\n");
return -1;
}
struct bmp280_config conf;
rslt = bmp280_get_config(&conf, &user_bmp);
conf.filter = BMP280_FILTER_COEFF_2;
conf.os_pres = BMP280_OS_16X;
conf.os_temp = BMP280_OS_4X;
conf.odr = BMP280_ODR_1000_MS;
rslt = bmp280_set_config(&conf, &user_bmp);
rslt = bmp280_set_power_mode(BMP280_NORMAL_MODE, &user_bmp);
struct bmp280_uncomp_data ucomp_data;
uint8_t meas_dur = bmp280_compute_meas_time(&user_bmp);
printf("Measurement duration: %dms\r\n", meas_dur);
uint8_t i;
for (i = 0; (i < 10) && (rslt == BMP280_OK); i++) {
printf("Running measurement: %d\n", i+1);
user_bmp.delay_ms(meas_dur);
rslt = bmp280_get_uncomp_data(&ucomp_data, &user_bmp);
int32_t temp32 = bmp280_comp_temp_32bit(ucomp_data.uncomp_temp, &user_bmp);
uint32_t pres32 = bmp280_comp_pres_32bit(ucomp_data.uncomp_press, &user_bmp);
uint32_t pres64 = bmp280_comp_pres_64bit(ucomp_data.uncomp_press, &user_bmp);
double temp = bmp280_comp_temp_double(ucomp_data.uncomp_temp, &user_bmp);
double pres = bmp280_comp_pres_double(ucomp_data.uncomp_press, &user_bmp);
printf("UT: %d, UP: %d, T32: %d, P32: %d, P64: %d, P64N: %d, T: %f, P: %f\r\n", \
ucomp_data.uncomp_temp, ucomp_data.uncomp_press, temp32, \
pres32, pres64, pres64 / 256, temp, pres);
user_bmp.delay_ms(1000);
}
if(rslt != BMP280_OK){
printf("Result not okay at measurement: %d\n", i);
}
}
解决方案
在开始猜测之前,我会确保传输实际上到达了陀螺仪后面的传感器。只需使用任何示波器来测量 SCL 和 SDA。如果设备正在接收传输,则示波器读数将提供有关设备 NAK 位置的附加信息。
BMP 与您能够解决的其他 i2c 设备之间的一个区别在过去让我感到头疼:BMP 似乎需要在设备地址和寄存器读取之间重复启动条件。
据我所知,标准 i2c 库不支持这一点,您通常必须使用 linux/i2c-dev.h 构建自己的读/写函数。
推荐阅读
- python - 如何在多个时间序列图像上绘制矢量图
- angular - 如何创建一个使用自己的白标服务于多个客户的网站?
- java - 无法使用 withNetworkMode("host") 运行 MockServerContainer
- python - Python 科学记数法使用小写字母 'e' 而不是 'E' .to_csv
- jmeter - 如何在 JMeter 中以 CSV 格式保存多个断言失败结果
- java - 顺便说一句,差异。图形 fillRect 和 clearRect
- azure-blob-storage - Azure 机器学习工作室注册模型保存目录
- c - 由于使用 vosk 的分段错误,无法运行 .c
- php - 以ROOT用户在Linux服务器上安装Libreoffice服务后,普通用户无法调用Libreoffice API
- javascript - 使用 Spring Boot 和 Angular 与 Web 套接字进行私人聊天