2

我发现其他一些人问过这个问题,但他们都在用 Arduino 编码,我正在努力将其转化为我的项目。

我在一个开发用于发射的立方体卫星的研究团队中,我的职责是与包括 IMU (MPU-9250) 在内的外围设备进行通信。我正在使用 uClinux 进行交叉编译,使用 C 进行编码。

到目前为止,我可以成功读取加速度计、陀螺仪和温度,但无法从磁力计获得读数。磁力计 (AK8963) 有自己的地址 (0x0C),我一直在尝试通过写入I2C_SLV0_ADDR (0x25)、I2C_SLV0_REG (0x26) 和I2C_SLV0_CTRL (0x27) 来与其通信。一旦我似乎没有得到任何结果,我尝试通过写入 FIFO Enable (0x23) 和I2C Master Control (0x24)来解决它

数据表和寄存器映射暗示从磁力计获取的值存储在寄存器外部传感器数据(0x49-0x60)中,但是当我尝试这个时,我没有在这些寄存器中得到任何东西。

这是一些代码,显示了我正在写入寄存器的数据:

write_register(0x23, 0x04);
write_register(0x24, 0b11110000);
write_register(0x25,0x8c);
write_register(0x26,0x00);
write_register(0x27,0b11110001);

所以我的问题是: 1. 我是否以正确的方式进行这个过程,还是我完全离开了?

  1. 如果我在正确的轨道上,我是否从正确的寄存器中读取?

谢谢大家的帮助!如果有什么我需要澄清的,请告诉我!

4

1 回答 1

3

好的!我想出了我自己的问题:)

1)我确实以错误的方式进行了这个过程。有一种更简单的方法可以做到这一点,我将详细说明。

2)我没有从正确的寄存器中读取。我将在下面展示该怎么做。

因此,连接到磁力计非常简单,但一点也不直观。它确实像自己的从站一样,有自己的从站地址,但该地址最初是不可访问的。

由于我正在使用 uClinux 进行交叉编译,因此我可以使用 bash 命令i2cdetect 0(在筛选到我的 SmartFusion2 时)检查 i2C 0 总线上的所有从站。当我在重置我的板后执行此命令时,我会打印出以下地址映射:

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- -- 

所以你可以看到只显示 IMU(0x68) 的地址。要使磁力计正确显示,您必须在 INT_PIN_CFG(0x37) 上启用旁路位。我在下面附上了我的代码,以防有人需要复制它。

#include <stdio.h>
//#include <linux/i2c-dev.h>

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>

#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#define IMU_ADDR 0x68 
#define IMU_WHO_AM_I 0x75


int file;

void i2c_init();
void write_register(uint8_t register_address, uint8_t value);
uint8_t read_register(uint8_t register_address);

void i2c_init(address){
    int adapter_nr = 0;
    char filename[20];

    snprintf(filename, 19, "/dev/i2c-%d", adapter_nr);
    file = open(filename, O_RDWR);
    if(file < 0)
        printf("Error: Failed to open file %s\n", filename);
    int success= (ioctl(file, I2C_SLAVE, address));
    if(file < 0) {
        printf("Error: IMU I2C Failed to Open\n");
        //return -1;
    }
}
void write_register(uint8_t register_address, uint8_t value){
    uint8_t data[]={register_address,value};
    write(file, data,ARRAY_SIZE(data));
}
uint8_t read_register(uint8_t register_address){
    uint8_t value;
    if(write(file, &register_address, sizeof(register_address)) !=1)
    {
        printf("%d\n",write(file, &register_address, sizeof(register_address)));
        printf("Failed to send data\n");
    }
    read(file, &value, sizeof(value));
    return value;
}

int main(){
    i2c_init(IMU_ADDR);

    printf("\nNow testing the 'Who am I?' IMU register. Output should be 0x71\n");
    printf("Register 0x75: 0x%02X \n", read_register(IMU_WHO_AM_I));

    write_register(0x37, 0x22);
    i2c_init(0x0C);
        printf("\nNow testing the 'Who am I?' Magnetometer register. Output should be 0x48\n");

    printf("Register 0x00: 0x%02x\n", read_register(0x00));

    return 0;
}

编译并运行代码后,该命令i2cdetect 0将返回以下数据映射。

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- 0c -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- -- 

该程序还返回 0x48,这是从磁力计的“我是谁?”读取时的正确值。登记。现在可以像读取任何其他寄存器一样读取磁力计。希望这可以帮助!!

于 2017-05-12T16:14:53.547 回答