Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Аппаратный I2C в LPC2124
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
MixEr
помогите пожалуйста: надо написать класс I2C для общения с EEPROM.
Смотрел апноты, техноты и даташит. В результете родилось вот это:

void TI2C::Transfer(unsigned char Addr, unsigned char Data)
{
DATA = Data;
I2ADR = Addr;
I2CONCLR = 0xFF;
I2CONSET = 0x40;
I2CONSET = 0x20;
busy = true;
while(busy)
{
};
I2CONSET = 0x10;
}

void TI2C::I2C_ISR(void)
{
switch(I2STAT)
{

case 0x08: //Условие СТАРТ было передано
I2DAT = WRITE_ROM;
I2CONCLR = 0x28;
break;
case 0x10: //Повторное условие СТАРТ было передано
break;
case 0x18: //Slave-адрес и флаг записи были переданы, АСК получен
I2DAT = I2ADR; //Записываем первый байт данных
adr_transmit = true; //Флаг передачи адреса
break;
case 0x20: //Slave-адрес и флаг записи были переданы, АСК не получен
I2DAT = WRITE_ROM; //Повторная передача
break;
case 0x28: //Байт был передан, АСК получен
if(count)
{
I2DAT = 0xaa;
count--;
};
if(!count)
{
I2CONSET = 0x10; //условие СТОП
};
busy = false;
break;
case 0x30: //Байт был передан, АСК не получен
break;

default:
break;
}

I2CONCLR = 0x08;
VICVectAddr = 0x00;
}
это только для записи по I2C в EEPROM байта данных по адресу WORD_ADDRESS.
Как я понимаю посылка должна состоять из 3 байт DEVICE_ADDRESS+WORD_ADDRESS+DATA_BYTE?
Если в case 0x28: оставить только I2CONSET = 0x10; то все работает ( на экране осцилографа видна вся посылка вместе условиями СТАРТ и СТОП), но пересылается только DEVICE_ADDRESS+WORD_ADDRESS. Если оставить как есть, то посылку не видно, никаких СТАРТ и СТОП, а высвечивается только DATA_BYTE. Как заставить отослать все три байта? Подскажите плиз....
Nixon
Вот вам пример реализации i2c интерфейса для eeprom. Написано правда для 214х. Рабочая, только без подробного обработчика ошибок. Не забывать после записи паузу делать.
klen
Толькочто научил LPC2103 передавать слово и считывать слово, уменя обмен с устройство - я ему команду 4 байта, и сразу же читаю его состояне тоже 4 байта (DEV_CMD_SIZE, DEV_STATE_SIZE)

Посмотрите и лишнее выкиньте.

Код
void twi_0_ISR(void)
{
//portBASE_TYPE Tmp = I2C0STAT;
switch (I2C0STAT)    //чтение состояния шины TWI #0
  {
    portBASE_TYPE pbTmp;
    // режим ВЕДУЩИЙ-ПРЕДЕТЧИК
    // СТАРТ and Send byte условие
    case ( 0x08 ):            //сформировано состояние СТАРТ
       I2C0CONCLR = 0x20; // сброс состояния СТАРТ
       I2C0DAT = twi_0_SlaveAddress; // запись SLA+W
       break;
    case (0x10):     // сформировано состояние ПОВСТАР
       twi_0_Data = (char*)&TwiDebugWordRx;
       I2C0CONCLR = 0x20; // сброс состояния ПОВСТАР
       I2C0DAT = twi_0_SlaveAddress + 1; // запись SLA+R
       break;
    case (0x18):        //передан address+W, получен ACK
       I2C0DAT       = twi_0_Data[0];    //запись на шину data первого байта пердаваймого сообщения
       break;
    case (0x20):
    //передан пакет address+W, получен NACK
       I2C0CONSET     = 0x10;    //установка состояния СТОП
       xQueueSendFromISR( qhTwi_0_SignaledQueue , (void*)&I2C0STAT , 0 );
       break;
    case (0x28):        //передан data, получен ASK
       if (twi_0_ByteTransfered < DEV_CMD_SIZE - 1 )
        {
          twi_0_ByteTransfered ++;
      I2C0DAT = twi_0_Data[twi_0_ByteTransfered];    //запись на шину data
        }
       else
        {
  
          // начинаем прием 4 байтов
          //сформируем состояние ПОВСТАР, разрешение подтверждения
              I2C0CONSET = I2C1CONSET_STA;
             }
       break;
    case (0x30)    :        //передан data, получен NASK
       I2C0CONSET     = 0x10;    //установка состояния СТОП
       xQueueSendFromISR( qhTwi_0_SignaledQueue , (void*)&I2C0STAT , 0 );
       break;

    
    // режим ВЕДУЩИЙ-ПРИЕМНИК
    case (0x40) :        //передан address+R, получен ACK
       twi_0_ByteTransfered = 0;
       I2C0CONSET     = 0x04;    //разрешение подтверждения ASK ведомым
       break;
    case (0x48) :        //передан address+R, получен NACK
       I2C0CONSET     = 0x10;    //установка состояния СТОП
       xQueueSendFromISR( qhTwi_0_SignaledQueue , (void*)&I2C0STAT , 0 );
       break;
    case (0x50) :        //принят data, получен ASK
       twi_0_Data[twi_0_ByteTransfered] = I2C0DAT;      //чтение байта
       twi_0_ByteTransfered++;
       if ( twi_0_ByteTransfered == DEV_STATE_SIZE )
        {
          I2C0CONSET     = 0x10;    //установка состояния СТОП
               xQueueSendFromISR( qhTwi_0_SignaledQueue , (void*)&I2C0STAT , 0 );
        }
       break;
    case (0x58):        //ринят data, получен NASK
       I2C0CONSET     = 0x10;    //установка состояния СТОП
       xQueueSendFromISR( qhTwi_0_SignaledQueue , (void*)&I2C0STAT , 0 );
       break;


   default :
       break;
}
// сброс флага прерывания TWI
I2C0CONCLR    = 0x08;
// сброс прерывания в VIC контроллере
VICVectAddr = 0;
}
MixEr
Спасибо всем кто откликнулся - ваши материалы мне очень помогают.
Получается вот такая штука:
если объявляю переменную вот так - volatile unsigned char i2c_slav = 0xFF; (значение любое)
то в обработчике прерывания все нормально и значение передается
...
case 0x18:
I2DAT = i2c_slav;
break;
...
а вот если вот так

volatile unsigned char i2c_slav;
...
void TI2C::Transfer(unsigned char Addr, unsigned char Data)
{
DATA = Data;
i2c_slav = Addr;
.....................
}

то в обработчике прерывания
...
case 0x18:
I2DAT = i2c_slav;
break;
...
в регистр записывается 0 и ето при любом значении Addr
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.