linux下读取MPU数据,无法使用linux / i2c-dev.h open()和read()使用rpi3从MPU 6050读取原始数据...

我是I2C的初学者,尝试使用rpi 3从GY-521(MPU-6050)读取数据

起初,我使用了C的WiringPi库,然后使用了python smbus库 . 两者都很好,并给出了一致的读数 . 然后我切换到本文中的方法:https://elinux.org/Interfacing_with_I2C_Devices . 我把所有的地址排成一行,但是我的行为非常奇怪和不一致:

•open()函数几乎每次都成功,但read()函数经常将errno设置为REMOTE I / O ERROR(在成功读取之前,我必须将连接调整大约20-30秒) . 考虑到wiringPi和smbus方法没有这个问题,这对我来说很奇怪 .

•根据数据表(https://www.invensense.com/wp-content/uploads/2015/02/MPU-6000-Datasheet1.pdf),IMU应该通过FIFO缓冲区以“突发”的1024字节包或更频繁的16位包发送数据 . 当我成功读取时,我填充了一个1100字节的无符号短缓冲区 . 但是,read()始终返回一个与缓冲区大小相对应的整数,即使缓冲区大于1024字节(在本例中为1100) . MPU-6050在向文件写入1024字节后是否可能无法发送eof?或者这是标准练习,程序员应该知道在1024处停止阅读?

•我也一直在比较很多有效的输出,我没有看到一个非常明显的模式,用于设置缓冲区中的哪些位 . 从这个文档https://www.invensense.com/wp-content/uploads/2015/02/MPU-6000-Register-Map1.pdf,我假设“从寄存器读取”,例如,从0x3C开始到0x3D(从第7页开始)的ACCEL_XOUT数据,只是从对应于0x3C和0x3D的某个索引中检索数据 . 填充缓冲区...但我似乎无法找到任何明显的线性映射 . 读取寄存器是否完全涉及其他形式的文件映射,缓冲区只是充满了随机的无关数据?

谢谢 .

// from https://elinux.org/Interfacing_with_I2C_Devices

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

void sensors_ADC_init(void) {

int file;

char filename[40];

const char *buffer;

int addr = 0b1101001; // The I2C address of GY-521, LSB == 1 -> read only

sprintf(filename,"/dev/i2c-1");

if ((file = open(filename,O_RDWR)) < 0) {

printf("Failed to open the bus.");

/* ERROR HANDLING; you can check errno to see what went wrong */

exit(1);

}

else if (ioctl(file,I2C_SLAVE,addr) < 0) {

printf("Failed to acquire bus access and/or talk to slave.\n");

/* ERROR HANDLING; you can check errno to see what went wrong */

exit(1);

}

else{ // opened successfully

// GY-521 writes 16 bits or 1024 bytes

unsigned short buf[550] = {0}; // 1100 byte buffer

unsigned short datachunk;

// Using I2C Read

int read_ = read(file,buf,1100);

if (read_ < 0) {

/* ERROR HANDLING: i2c transaction failed */

printf("Failed to read from the i2c bus.\n");

printf("errno = %s\n", strerror(errno));

printf("\n\n");

} else { //successful read

printf("read %d bytes\n", read_);

for(unsigned short i = 0; i < 550; i++){

datachunk = buf[i];

printf("output: %d , %d index of 550\n", datachunk, i);

}

}

}

}

int main(){

while(1){

sensors_ADC_init();

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 设置I2C的时钟频率和GPIO引脚。可以使用STM32 HAL库提供的函数或者直接操作寄存器来设置。 2. 初始化I2C,包括配置I2C的工作模式,使能I2C,以及设置I2C的地址等。 3. 发送起始信号(Start)和设备地址。发送时需要判断设备是否响应,如果没有响应则重试或者退出。 4. 发送要读取的寄存器地址,根据MPU6050数据手册可以得知要读取的寄存器地址。 5. 发送重复起始信号(Repeated Start)和设备地址,并设置I2C为接收模式。 6. 读取数据,并发送停止信号(Stop)。 7. 处理读取到的数据,可以根据MPU6050数据手册来解析数据。 8. 如果需要连续读取多个寄存器,可以重复第四步和第五步。 9. 关闭I2C。 下面是一个简单的示例代码: ``` // 设置I2C的时钟频率和GPIO引脚 RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN; GPIOB->MODER |= GPIO_MODER_MODE6_1 | GPIO_MODER_MODE7_1; GPIOB->AFR[0] |= (4 << GPIO_AFRL_AFSEL6_Pos) | (4 << GPIO_AFRL_AFSEL7_Pos); GPIOB->OTYPER |= GPIO_OTYPER_OT6 | GPIO_OTYPER_OT7; GPIOB->OSPEEDR |= GPIO_OSPEEDR_OSPEED6 | GPIO_OSPEEDR_OSPEED7; GPIOB->PUPDR |= GPIO_PUPDR_PUPD6_0 | GPIO_PUPDR_PUPD7_0; // 初始化I2C I2C1->CR1 &= ~I2C_CR1_PE; I2C1->CR2 &= ~I2C_CR2_FREQ; I2C1->CR2 |= 42; // 设置I2C的时钟频率为42MHz I2C1->CCR &= ~I2C_CCR_FS; I2C1->CCR |= 210; // 设置I2C的时钟频率为100kHz I2C1->TRISE |= 43; // 设置I2C的上升时间 I2C1->CR1 |= I2C_CR1_PE; I2C1->OAR1 &= ~I2C_OAR1_ADD7; I2C1->OAR1 |= (0x68 << 1); // 设置I2C的地址 // 发送起始信号和设备地址 I2C1->CR1 |= I2C_CR1_START; while (!(I2C1->SR1 & I2C_SR1_SB)); I2C1->DR = 0xD0; // 发送设备地址 while (!(I2C1->SR1 & I2C_SR1_ADDR)); I2C1->SR2; // 发送要读取的寄存器地址 I2C1->DR = 0x3B; // 发送寄存器地址 while (!(I2C1->SR1 & I2C_SR1_TXE)); I2C1->CR1 |= I2C_CR1_START; while (!(I2C1->SR1 & I2C_SR1_SB)); I2C1->DR = 0xD1; // 发送设备地址,进入接收模式 while (!(I2C1->SR1 & I2C_SR1_ADDR)); I2C1->SR2; // 读取数据 uint8_t data = 0; I2C1->CR1 &= ~I2C_CR1_ACK; while (!(I2C1->SR1 & I2C_SR1_RXNE)); data = I2C1->DR; I2C1->CR1 |= I2C_CR1_STOP; // 处理数据 // ... // 关闭I2C I2C1->CR1 &= ~I2C_CR1_PE; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值