Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: LPC2478 SPI Slave
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
-= Александр =-
Пытаюсь заставить работать LPC2478 как SPI Slave - вылазят глюки...
Прерывание происходит только первый раз, байт принимаетсмя и все.
После приема картина такая:

S0SPSR=0xC0
Тоесть Write collision

Если отправлять еще - прерывания не происходит, зато вылазит вот это:
S0SPSR=0xE0
Тоесть Write collision + Read overrun

Что эта хрень значит и как с ней бороться?

Инициализация выглядит так: (Пишу в uVision4)
Код
void init_SPI( void )
{
  PCONP |= (1 << 8);    //SPI0 Power ON
  //S0SPCR = 0x00;
  PINSEL0|=(1U<<30)|(1U<<31); //SCK
  PINSEL1|=(1U<<0 )|(1U<<1 ); //SSEL
  PINSEL1|=(1U<<2 )|(1U<<3 ); //MISO
  PINSEL1|=(1U<<4 )|(1U<<5 ); //MOSI
  S0SPCCR = 0x8;         //Clock select - max clock speed = PLCK/8
  S0SPCR = 0x089C;         // 8 bit, CPHA=1, CPOL=1, slave mode, MSB first, interrupt enabled
             //0898
  if ( install_irq( SPI0_INT, (void *)SPI0Handler, HIGHEST_PRIORITY) == FALSE ) //Install IRQ
    {
    while(1);
    }
  
}


Обработчик прерывания такой:

Код
void SPI0Handler (void) __irq
{
  DWORD regValue;
  unsigned int data_spi;

  S0SPINT = SPI0_INT_FLAG;        /* clear interrupt flag */
  data_spi=S0SPDR;
  //IENABLE;                        /* handles nested interrupt */
  S0SPDR=spi_counter;
  spi_counter++;
  
  regValue = S0SPSR;
  if ( regValue & WCOL )
  {
    //SPI0Status |= SPI0_COL;
  }
  if ( regValue & SPIF )
  {
    //SPI0Status |= SPI0_TX_DONE;
    //TxCounter++;
  }
  
  //IDISABLE;
  VICVectAddr = 0;        /* Acknowledge Interrupt */
}


Еще такой момент: нужно ли после каждого передаооного байта дергать селект или можно его один раз выставить и пачку байт прогнать? По даташиту вроде как в режиме CPHA=1 синхронизация идет только по тактам...
-= Александр =-
Разобрался - косяк был в статусном регистре. Его надо вычитывать ДО того как прочитаешь данные.

Теперь обработчик выглядит так:

Код
void SPI0Handler (void) __irq
{
  DWORD regValue;
  unsigned int data_spi;
  
  if (S0SPSR);                  // (dummy) read status register

  data_spi = S0SPDR;             // read data received
  S0SPDR   = spi_counter;        // next data to transmit

  S0SPINT  = 0x01;               // reset interrupt flag
  VICVectAddr = 0;               // reset VIC


  SPIdata=data_spi;
  SPIflag=1;
  spi_counter++;
}
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.