Интересно, есть ли у кого-нибудь пример работающего кода 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 лет. Я не хочу менять то, что по-прежнему надежно.
Любые мысли приветствуются.