Ошибка чтения I2C микроконтроллера PIC с кодом, сгенерированным MPLABX

Я использую MPLABX 3.10 и сгенерировал главный интерфейс I2C, используя функцию прерывания главного устройства MSSPI2C. Мне удалось сгенерировать событие записи I2C, которое на осциллографе выглядит нормально. Однако чтения не работают. Когда я смотрю на выходные данные осциллографа, я ясно вижу, что создается условие запуска, а идентификатор устройства с установленным битом чтения создается и подтверждается. Затем я ожидаю, что адрес регистра погаснет, но вместо этого я вижу все нули. Я неправильно использую сгенерированный код? Нужно ли мне выполнять запись устройства, а затем чтение устройства? Я попытался сократить код до следующего:

void I2C_Initialize(void) {
    i2c_object.pTrHead = i2c_tr_queue;
    i2c_object.pTrTail = i2c_tr_queue;
    i2c_object.trStatus.s.empty = true;
    i2c_object.trStatus.s.full = false;

    i2c_object.i2cErrors = 0;

    // BF RCinprocess_TXcomplete; UA dontupdate; SMP Sample At Middle; P stopbit_notdetected; S startbit_notdetected; R_nW write_noTX; CKE Idle to Active; D_nA lastbyte_address; 
    SSP1STAT = 0x00;
    // SSPEN enabled; WCOL no_collision; SSPOV no_overflow; CKP Idle:Low, Active:High; SSPM FOSC/4_SSPxADD; 
    SSP1CON1 = 0x28;
    // BOEN disabled; AHEN disabled; SBCDE disabled; SDAHT 100ns; DHEN disabled; ACKTIM ackseq; PCIE disabled; SCIE disabled; 
    SSP1CON3 = 0x00;
    // Baud Rate Generator Value: SSPADD 3;   
    SSP1ADD = 0x03;

    /* Byte sent or received */
    // clear the master interrupt flag
    PIR1bits.SSP1IF = 0;
    // enable the master interrupt
    PIE1bits.SSP1IE = 1;

}

void I2C_MasterRead(
        uint8_t *pdata,
        uint8_t length,
        uint16_t address,
        I2C_MESSAGE_STATUS *pflag) {
    static I2C_TRANSACTION_REQUEST_BLOCK trBlock;


    // check if there is space in the queue
    if (i2c_object.trStatus.s.full != true) {
        I2C_MasterReadTRBBuild(&trBlock, pdata, length, address);
        I2C_MasterTRBInsert(1, &trBlock, pflag);
    } else {
        *pflag = I2C_MESSAGE_FAIL;
    }

}

void I2C_MasterReadTRBBuild(
        I2C_TRANSACTION_REQUEST_BLOCK *ptrb,
        uint8_t *pdata,
        uint8_t length,
        uint16_t address) {
    ptrb->address = address << 1;
    // make this a read
    ptrb->address |= 0x01;
    ptrb->length = length;
    ptrb->pbuffer = pdata;
}

void main(void) {
    #define BMA222E_BASE_ADDRESS_DEV0 (0x18) // <BMA222E base address
    uint8_t dummy[2];
    I2C_MESSAGE_STATUS pflag;
    /* Configure the oscillator for the device */

    ConfigureOscillator();
    I2C_Initialize();


    dummy[0] = 0x0F;  // I expect to see 0x0F go out as the register value
    dummy[1] = 0x00;
    I2C_MasterRead (&dummy, 2, BMA222E_BASE_ADDRESS_DEV0, &pflag);
}

person Rich Maes    schedule 30.10.2016    source источник


Ответы (1)


Хорошо, вот и разобрался. Мне нужно написать адрес, а затем прочитать данные в два этапа. Я изменил основную функцию следующим образом.

void main(void) {
    #define BMA222E_BASE_ADDRESS_DEV0 (0x18) // <BMA222E base address
    uint8_t dummy[2];
    I2C_MESSAGE_STATUS pflag;
    /* Configure the oscillator for the device */
    ConfigureOscillator();
    I2C_Initialize();


    dummy[0] = 0x0F;  // I expect to see 0x0F go out as the register value
    dummy[1] = 0x00;
    I2C_MasterWrite (&dummy, 1, BMA222E_BASE_ADDRESS_DEV0, &pflag);
    I2C_MasterRead (&dummy, 1, BMA222E_BASE_ADDRESS_DEV0, &pflag);

    // dummy[0] now contains the read data.
}
person Rich Maes    schedule 30.10.2016