Я пытаюсь использовать i2c на черной кости бигля с С ++, но мне все равно возвращается 0x00

Привет, я пытаюсь читать и записывать данные с шины i2c на черную кость бигля. Но я продолжаю читать 0x00 всякий раз, когда пытаюсь получить доступ к регистру Who Am I на MMA84152 (или любом другом регистре, если на то пошло), который является постоянным регистром, что означает, что его значение не изменяется. Я пытаюсь прочитать символьный драйвер i2c-1, расположенный в / dev, и подключаю sda и scl строк MMA852 к контактам 19 и 20 в заголовке p9. Линии sda и scl подтянуты резисторами 10 кОм. Оба контакта 19 и 20 показывают 00000073 для их мультиплексора контактов, что означает, что он настроен на функциональность i2c, и управление нарастанием медленное, приемник активен, на контакте используется подтягивающий резистор, и подтягивание включено. Я запустил i2cdetect -r 1, и мое устройство отображается как 0x1d, что является его правильным адресом. Я также запустил i2cdump 1 0x1d, и 0x2a отображается под 0x0d, который является регистром, который я пытаюсь прочитать с моего устройства, и содержит правильное значение в соответствии с таблицей данных. Но когда я его читаю, он возвращает мне 0x00. Я также использую последний дистрибутив Angstrom, и я вошел в систему под root, поэтому мне не нужно использовать sudo. Я потерялся. Вот код:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string>

using namespace std;

int main(int argc, char **argv){
    int X_orientation=0;
    char buffer1[256];
    string i2cDeviceDriver="/dev/i2c-1";
    int fileHandler;

    if((fileHandler=open(i2cDeviceDriver.c_str(),O_RDWR))<0){
        perror("Failed To Open i2c-1 Bus");
        exit(1);
    }
    if(ioctl(fileHandler,I2C_SLAVE,0x1d)<0){
        perror("Failed to acquire i2c bus access and talk to slave");
        exit(1);
    }

    char buffer[1]={0x0D};
    if(write(fileHandler,buffer,1)!=1){                 
        perror("Failed to write byte to accelerometer");
        exit(1);
    }

    if(read(fileHandler,buffer1,1)!=1){                 
        perror("Failed to read byte from accelerometer");
        exit(1);
    }
    printf("Contents of WHO AM I is 0x%02X\n",buffer1[0]);
}

person Rakib Hasan    schedule 24.03.2014    source источник
comment
Вы пробовали ›i2cget -y 1 0x1D 0x0D? (P9-19 - это SCL, а P9-20 - это SDA, а не P8-19 и P8-20, другими словами, убедитесь, что провода привязаны к заголовку, противоположному USR_LEDS; также убедитесь, что провода SCL и SDA находятся в правильном положении. порядок - это была проблема с датчиком BMP180)   -  person TekuConcept    schedule 15.07.2014


Ответы (1)


Вероятно, ваше устройство I2C не поддерживает использование отдельных команд write() и read() для запроса регистров (или эквивалентных команд i2c_smbus_write_byte() и i2c_smbus_read_byte()). Ядро добавляет «стоповый бит» для разделения ваших сообщений в сети, и некоторые устройства не поддерживают этот режим.

Подтвердить:

Попробуйте использовать команду Linux i2cget с флагом -c (режим 'запись байта / чтение байта', используются отдельные сообщения чтения и записи с промежуточным стоп-битом):

$ i2cget -c 1 0x1d 0x0d
Expected result: 0x00 (Incorrect response)

Затем попробуйте использовать i2cget с флагом -b (режим чтения байтовых данных, который объединяет сообщения чтения и записи без стопового бита):

$ i2cget -b 1 0x1d 0x0d
Expected result: 0x2a (Correct response)

Решить:

Замените команды read() и write() комбинированной командой i2c_smbus_read_byte_data(), если она доступна в вашей системе:

const char REGISTER_ID = 0x0d;
char result = i2c_smbus_read_byte_data(fileHandler, REGISTER_ID);

В качестве альтернативы (если вышеуказанное недоступно) вы можете использовать опцию ioctl I2C_RDWR:

const char SLAVE_ID    = 0x1d;
const char REGISTER_ID = 0x0d;

struct i2c_rdwr_ioctl_data readByteData;
struct i2c_msg messages[2];
readByteData.nmsgs = 2;
readByteData.msgs  = messages;

// Write portion (send the register we wish to read)
char request = REGISTER_ID;
i2c_msg& message = messages[0];
message.addr  = SLAVE_ID;
message.flags = 0;            // 0 = Write
message.len   = 1;
message.buf   = &request;

// Read portion (read in the value of the register)
char response;
message = messages[1];
message.addr  = SLAVE_ID;
message.flags = I2C_M_RD;
message.len   = 1;            // Number of bytes to read
message.buf   = &response;    // Where to place the result

// Submit the combined read+write message
ioctl(fileHandler, I2C_RDWR, &readByteData);

// Output the result
printf("Contents of register 0x%02x is 0x%02x\n", REGISTER_ID, response);

Больше информации:

person slicer    schedule 31.12.2014