I2 C Slave - проблема прерывания - PullRequest
0 голосов
/ 12 марта 2020

Интересно, есть ли у кого-нибудь пример работающего кода I2 C Slave для PI C 24F (в идеале J64GA106, который я ценю, устарел, но я использовал его раньше в других проектах).

Я потратил неделю, пытаясь заставить работать простую функцию «чтения одного регистра», и все примеры, которые я нашел, как представляется, подразумевают, что I2 C Master должен быть PI C, который изменил синхронизацию и ACK / NACK (тот же самый ведомый код не будет работать с обычным I2 C Master). Люди, кажется, имеют серьезные проблемы с серией PIC24F.

Затем я начал с нуля, используя MPLABX 5.35 (XC16) и Code Configurator v3

Пример i2cl1. c и i2cl1.h используют ту или иную форму эмулятора EEPROM с адресами двухбайтовых регистров, и любая попытка чтения только одного регистра приводит к тому, что PI C отвечает несколькими значениями (прерывание чтения вызывает несколько раз). Я могу только догадываться, что PI C считает, что ему нужно отправить все 64 байта. Я не верю, что адреса двухбайтовых регистров являются нормой во всем. I2 C.

Я ввел здесь только некоторые фрагменты из M CC, сгенерированного i2c1. c кода, потому что файлов, которые создает M CC, много, а некоторые очень длинные и сбивают с толку без реальных примеров того, как вы должны их использовать. Нет даже указания на то, что вам нужно установить адрес подчиненного устройства, и есть примеры кода, которые не указывают ни на какой код. Это похоже на работу в пятницу днем.

bool I2C1_StatusCallback(I2C1_SLAVE_DRIVER_STATUS status)
{

// this emulates the slave device memory where data written to slave
// is placed and data read from slave is taken
/*
 Emulate EEPORM default memory size is 64bytes

 Emulate EEPORM Read/Write Instruction:

 Byte Read Instruction:
 |Start|slave Addr + r|Ack|AddrHighByte|Ack|AddrLowByte|Ack|data|Nack|Stop|

 */

static uint8_t EMULATE_EEPROM_Memory[EMULATE_EEPROM_SIZE] =
        {
            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        };

static uint16_t address, addrByteCount;
static bool     addressState = true;

switch (status)
{
    case I2C1_SLAVE_TRANSMIT_REQUEST_DETECTED:
        // set up the slave driver buffer transmit pointer
        I2C1_ReadPointerSet(&EMULATE_EEPROM_Memory[address++]);
        if(address >= EMULATE_EEPROM_SIZE) {
            address = 0;
        }
        break;

    case I2C1_SLAVE_RECEIVE_REQUEST_DETECTED:

        addrByteCount = 0;
        addressState = true;

        // set up the slave driver buffer receive pointer
        I2C1_WritePointerSet(&i2c1_slaveWriteData);
        break;

    case I2C1_SLAVE_RECEIVED_DATA_DETECTED:

        if (addressState == true)
        {
            // get the address of the memory being written
            if (addrByteCount == 0)
            {
                address = (i2c1_slaveWriteData << 8) & 0xFF00;
                addrByteCount++;
            }
            else if (addrByteCount == 1)
            {
                address = address | i2c1_slaveWriteData;
                addrByteCount = 0;
                addressState = false;
            }

            if(address >= EMULATE_EEPROM_SIZE) {
                address = EMULATE_EEPROM_SIZE;
            }
        }
        else // if (addressState == false)
        {
            // set the memory with the received data
            EMULATE_EEPROM_Memory[address++] = i2c1_slaveWriteData;
            if(address >= EMULATE_EEPROM_SIZE) {
                address = 0;
            }
        }

        break;

    case I2C1_SLAVE_10BIT_RECEIVE_REQUEST_DETECTED:

        // do something here when 10-bit address is detected

        // 10-bit address is detected

        break;

    default:
        break;

}

    return true;
}

Я просто пытаюсь записать состояние порта B в адресуемый регистр, который может прочитать обычный мастер I2 C.

My I2 C Master работает на TI MSP, которая работает с многочисленными периферийными устройствами I2 C от разных производителей в течение почти 15 лет. Я не хочу менять то, что по-прежнему надежно.

Любые мысли приветствуются.

...