Jump to content

    

Проблема с SPI.

я работаю с MK10FN1M0xxx12

посылаю-принимаю по СПИ

uint32_t SPI_TransferByte(uint32_t spi_num, uint8_t tx_data, uint8_t *rx_data)
{
     uint32_t timeout;
     uint32_t value;


    // Assert CS0, Use config 0
   SPIx[spi_num]->PUSHR = SPI_PUSHR_CTAS(0) | SPI_PUSHR_TXDATA((uint32_t)tx_data);

    timeout = 0;
    // while transfer complete
    while (!(SPIx[spi_num]->SR & SPI_SR_TCF_MASK))
    {
       timeout++;
       if (timeout > SPI_TIMEOUT)
       {
         // clear flag
         SPIx[spi_num]->SR = SPI_SR_TCF_MASK;
         return SPI_TIMEOUT_ERROR;
       }
    };

    // clear flag
    SPIx[spi_num]->SR = SPI_SR_TCF_MASK;
    *rx_data = (uint8_t)SPIx[spi_num]->POPR;

    return 0;
}

вижу фигня какя то - раз получил байт в ответ, раз не получил. а на скопе на пине SIN все четко, байты приходят. думал-гадал - добавил задержку

uint32_t SPI_TransferByte(uint32_t spi_num, uint8_t tx_data, uint8_t *rx_data)
{
     uint32_t timeout;
     uint32_t value;


    // Assert CS0, Use config 0
   SPIx[spi_num]->PUSHR = SPI_PUSHR_CTAS(0) | SPI_PUSHR_TXDATA((uint32_t)tx_data);

    timeout = 0;
    // while transfer complete
    while (!(SPIx[spi_num]->SR & SPI_SR_TCF_MASK))
    {
       timeout++;
       if (timeout > SPI_TIMEOUT)
       {
         // clear flag
         SPIx[spi_num]->SR = SPI_SR_TCF_MASK;
         return SPI_TIMEOUT_ERROR;
       }
    };

    // clear flag
    SPIx[spi_num]->SR = SPI_SR_TCF_MASK;

  for (timeout = 0; timeout < 100; timeout++);

    //while (!(SPIx[spi_num]->SR & SPI_SR_RFDF_MASK))  //dosen't work

    *rx_data = (uint8_t)SPIx[spi_num]->POPR;

    return 0;
}

и все работает как часики.

фига се думаю - байт ушел но нужно ждать пока пришедший байт готов. но не задержками же.

начал перебирать флаги в статусном регистре - этот вроде подходит - while (!(SPIx[spi_num]->SR & SPI_SR_RFDF_MASK)) но я не выхожу из while. Че там твориться вообще с Кинетисовским СПИ? Или я что то не так настроил?

Edited by Jenya7

Share this post


Link to post
Share on other sites

Может не учитываете буферизацию SPI (регистр передачи и сдвиговый регистр), и читаете до освобождения регистра сдвига.

А если таймаут - то "попадает". Смотрите бит "сдвиговый регистр свободен".

С Kinetis не работал. Но это вроде-как типовая структура. (есть биты пустоты для буферного регистра и регистра сдвига.)

 

Share this post


Link to post
Share on other sites

Тут, судя по ветке про таймер и по "...перебирать флаги в статусном регистре...", проблема в прочитать RefMan.

 

Я уже почти влюбился ;) (в самом хрошем смысле этого слова) в K10.

Share this post


Link to post
Share on other sites
Тут, судя по ветке про таймер и по "...перебирать флаги в статусном регистре...", проблема в прочитать RefMan.

В Kinetis все операции с SPI делаю через DMA. Тогда получается надежно.

А без DMA, да, есть такая проблема, как чтение раньше времени или слишком поздно. :laughing:

Share this post


Link to post
Share on other sites
В Kinetis все операции с SPI делаю через DMA. Тогда получается надежно.

А без DMA, да, есть такая проблема, как чтение раньше времени или слишком поздно. :laughing:

 

Александр, Вам как главному специалисту по Кинетису вопросы

1. почему флаг while (!(SPIx[spi_num]->SR & SPI_SR_RFDF_MASK)) не работает?

2. Можете показать пример с DMA? У меня не заработало.

 

я вообще в шоке от Кинетивского СПИ. что это за FIFO в котором нельзя настроить глубину. где флаг дата пришла в POPR. я уже несколько дней танцы с бубнами устраиваю.

пока что единственное решение которое работает for (timeout = 0; timeout < 10; timeout++); перед тем как читать из POPR.

STMовский СПИ просто мерседес в сравнении с Кинетисовским.

Edited by Jenya7

Share this post


Link to post
Share on other sites
Александр, Вам как главному специалисту по Кинетису вопросы

1. почему флаг while (!(SPIx[spi_num]->SR & SPI_SR_RFDF_MASK)) не работает?

2. Можете показать пример с DMA? У меня не заработало.

 

я вообще в шоке от Кинетивского СПИ. что это за FIFO в котором нельзя настроить глубину. где флаг дата пришла в POPR. я уже несколько дней танцы с бубнами устраиваю.

пока что единственное решение которое работает for (timeout = 0; timeout < 10; timeout++); перед тем как читать из POPR.

STMовский СПИ просто мерседес в сравнении с Кинетисовским.

 

Работу с SPI можно посмотреть в моем проекте - https://github.com/Indemsys/Universal3PHalf.../K66BLEZ1_SPI.c

В Kinetis у разных SPI разная глубина и чаще всего она равна 1, увы.

С флагом SPI_SR_RFDF_MASK у меня тоже что-то не поучалось. Уж не помню что именно.

Попробуйте перед приемо-передачей очищать FIFO.

void SPI_clear_FIFO(uint8_t modn)
{
  SPI_Type  *SPI   = spi_mods[modn].spi;

  SPI->MCR |= BIT(HALT); // Остановить модуль
  while (SPI->SR & BIT(TXRXS)); // Ожидание пока бит 30 (TXRXS) не станет равным нулю

  SPI->SR = SPI->SR;
  SPI->MCR |= BIT(CLR_TXF) + BIT(CLR_RXF); // Установить флаги CLR_TXF и CLR_RXF для очистки обоих FIFO
  SPI->MCR &= ~BIT(HALT); // Запустить модуль
}

 

 

Share this post


Link to post
Share on other sites
Работу с SPI можно посмотреть в моем проекте - https://github.com/Indemsys/Universal3PHalf.../K66BLEZ1_SPI.c

В Kinetis у разных SPI разная глубина и чаще всего она равна 1, увы.

С флагом SPI_SR_RFDF_MASK у меня тоже что-то не поучалось. Уж не помню что именно.

Попробуйте перед приемо-передачей очищать FIFO.

void SPI_clear_FIFO(uint8_t modn)
{
   SPI_Type  *SPI   = spi_mods[modn].spi;

   SPI->MCR |= BIT(HALT); // Остановить модуль
   while (SPI->SR & BIT(TXRXS)); // Ожидание пока бит 30 (TXRXS) не станет равным нулю

   SPI->SR = SPI->SR;
   SPI->MCR |= BIT(CLR_TXF) + BIT(CLR_RXF); // Установить флаги CLR_TXF и CLR_RXF для очистки обоих FIFO
   SPI->MCR &= ~BIT(HALT); // Запустить модуль
}

 

а SPI_clear_FIFO перед каждым байтом или блоком данных? у меня есть посылка 4096 байт сразу.

 

вообще я при инициализации отменяю ФИФО

//        Clear TX FIFO               Clear RX FIFO            Disable Receive FIFO        Disable Transmit FIFO
SPI2_MCR |= SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK | SPI_MCR_DIS_RXF_MASK | SPI_MCR_DIS_TXF_MASK;

Edited by Jenya7

Share this post


Link to post
Share on other sites
вообще я при инициализации отменяю ФИФО

Если отменен FIFO, то логично ожидать, что и все сигналы от него не будут работать и флаги не будут взводится.

Тогда все объясняется.

Share this post


Link to post
Share on other sites
Если отменен FIFO, то логично ожидать, что и все сигналы от него не будут работать и флаги не будут взводится.

Тогда все объясняется.

хм...мне на кинетисковском форуме посоветовали отрубить ФИФО.

Share this post


Link to post
Share on other sites
. . . пока что единственное решение которое работает for (timeout = 0; timeout < 10; timeout++); . . .

Метод найти, где "собака порылась" не ахти, но все-же.

Организуйте отладочный массив структур (или класс) для записи "среза" статусных регистров SPI.

static RegsImageSPI MySPI;
MySPI.SaveRegs(0); 
for (timeout = 0; timeout < 10; timeout++); 
MySPI.SaveRegs(1); 
--- BP --- просмотреть какой из флагов изменился

Этот код добавит таймауты, надо будет скорректировать.

 

Share this post


Link to post
Share on other sites
Метод найти, где "собака порылась" не ахти, но все-же.

Организуйте отладочный массив структур (или класс) для записи "среза" статусных регистров SPI.

static RegsImageSPI MySPI;
MySPI.SaveRegs(0); 
for (timeout = 0; timeout < 10; timeout++); 
MySPI.SaveRegs(1); 
--- BP --- просмотреть какой из флагов изменился

Этот код добавит таймауты, надо будет скорректировать.

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

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this