Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: AT91SAM7X256 - SPI в PDC режиме
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
KolyanV
Подключил к контроллеру AT91SAM7X256 по SPI интерфейсу микросхему CS5368.
Контроллер работает в Master режиме, прием/передача происходит с помощью PDC. Факт окончания операций записи/чтения определяется по прерываниям.
Проблема в следующем: при приеме данные смещаются на один байт. Т.е я программирую PDC на прием/передачу 3 байта данных, но в применом буфере полученные данные оказываются смещенными на один байт. Т.е байт, который должен находится в буфере со смещением 1 реально размещен со смещением 2. Причем смотрю осцилографом - ответ от микросхемы честный, начиная с 9-го клока шины данные добросовестно передаются. Т.е байт данных должен попасть в буфер со смещением 1 , а на практике попадает по смещению 2.

Инициализация SPI0 следующая:
Код
  // Конфигурирование PIO на предмет включения перефирии SPI0 к выводам порта A
  AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA,
                      AT91C_PA12_SPI0_NPCS0 | AT91C_PA16_SPI0_MISO | AT91C_PA17_SPI0_MOSI | AT91C_PA18_SPI0_SPCK,0);
  // Включение клоков для SPI0
  AT91F_SPI0_CfgPMC();
  // Конфигурирование SPI0
  AT91F_SPI_CfgMode(AT91C_BASE_SPI0, AT91C_SPI_MSTR | AT91C_SPI_PS_FIXED);  // Master, CS Fixed not decoded, Mode Fault Detection Enable, PCS=0 (NCS0 Active)
  AT91F_SPI_CfgCs(AT91C_BASE_SPI0, 0, AT91C_SPI_NCPHA | AT91C_SPI_BITS_8 | (16<<8));  // 8 бит, частота SPCK boudrate=MCK/16 = 3 Mhz

  // Конфигурирования прерываний по SPI
  AT91F_AIC_ConfigureIt(AT91C_BASE_AIC,
                        AT91C_ID_SPI0,
                        AT91C_AIC_PRIOR_HIGHEST,
                        AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,
                        SPI0_Interrupt);
//  AT91F_SPI_EnableIt(AT91C_BASE_SPI0, AT91C_SPI_ENDTX);
  // Включение прерываний
  AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SPI0);
  // Включение SPI0
  AT91F_SPI_Enable(AT91C_BASE_SPI0);


Сам код для приема- передчаи данных по SPI:
Код
    CmdSndBuf[0]=CS5368_SPICMD_WRITE;
    CmdSndBuf[1]=Addr;
    // Настройка PDC для SPI
    *AT91C_SPI0_PTCR= AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS;  // Если были PDC трансферы в текущий момент - отключаем
    *AT91C_SPI0_TPR=  (unsigned)CmdSndBuf;
    *AT91C_SPI0_TCR=  2;
    *AT91C_SPI0_TNCR=  0;
    CmdSndFlag=false;
    // Запуск процесса отправки команды к АЦП cs5368
    *AT91C_SPI0_PTCR= AT91C_PDC_TXTEN;
    AT91F_SPI_EnableIt(AT91C_BASE_SPI0, AT91C_SPI_ENDTX);
    // Ожидание выполнения операции
    while (!CmdSndFlag);

    for (int zz=0;zz<20;zz++)
      __no_operation();

    // Подготовка буфера для отправки команды чтения данных
    CmdSndBuf[0]=CS5368_SPICMD_READ;
    CmdSndBuf[1]=0;
    CmdSndBuf[2]=0;
    // Настройка PDC для SPI
    *AT91C_SPI0_PTCR= AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS;
    *AT91C_SPI0_RPR=  (unsigned)CmdRcvBuf;
    *AT91C_SPI0_RCR=  3;
    *AT91C_SPI0_RNCR=  0;
    *AT91C_SPI0_TPR=  (unsigned)CmdSndBuf;
    *AT91C_SPI0_TCR=  3;
    *AT91C_SPI0_TNCR=  0;
    CmdRcvFlag=false;
    // Запуск процесса отправки команды к АЦП cs5368
    *AT91C_SPI0_PTCR= AT91C_PDC_TXTEN | AT91C_PDC_RXTEN;
    AT91F_SPI_EnableIt(AT91C_BASE_SPI0, AT91C_SPI_ENDRX);
    // Ожидание выполнения операции
    while (!CmdRcvFlag);



Обработка прерываний SPI:
Код
//---------------------------------------------------------------------
// Обработчик прерывания от SPI0
void SPI0_Interrupt()
{ if (*AT91C_SPI0_SR & AT91C_SPI_ENDTX)
     { CmdSndFlag=true;
       AT91F_SPI_DisableIt(AT91C_BASE_SPI0, AT91C_SPI_ENDTX);
     }
   if (*AT91C_SPI0_SR & AT91C_SPI_ENDRX)
     { CmdRcvFlag=true;
       AT91F_SPI_DisableIt(AT91C_BASE_SPI0, AT91C_SPI_ENDRX);
     }

   *AT91C_AIC_EOICR=AT91C_ID_SPI0;
}


В errata по данной ситуации никаких упоминаний нет. Не могу понять, где я глючу ?
aaarrr
ИМХО, все правильно: при включении PDC приемника Вы тут же получаете последний байт, принятый при передаче предыдущей команды, когда PDC приемника был отключен. Сбросьте приемник.
KolyanV
Цитата(aaarrr @ Jul 11 2008, 00:20) *
ИМХО, все правильно: при включении PDC приемника Вы тут же получаете последний байт, принятый при передаче предыдущей команды, когда PDC приемника был отключен. Сбросьте приемник.

Спасибо! Действительно, все оказалось до безобразия просто. Включил синхронную запись/чтение через PDC вместо "просто записи" и проблема решилась.
aaarrr
На самом деле достаточно было бы просто прочитать SPI_RDR, но можно и так.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.