Перейти к содержанию
    

Про SPI STM32F405

Уважаемые коллеги, посмотрите на этот код. Yужно обеспечить обмен по SPI (STM32F405 - Slave) между двумя МК. Поддержка обмена по прерываниям от SPI. Идея в том, чтобы к моменту прихода данных в приемник SPI, в передатчике уже есть ответ. Так все и работает, т.е. первым делом разрешается прерывание от флага TXE и в буфер передатчика передается первый байт ответа, затем прием и буфер приемника опустошается и вновь заполняется следующим байтом ответа. Но надежность этого кода низкая: почему-то при входе в прерывание иногда оба флага установлены и TXE, и RXNE. А ведь эти флаги должны, по моим убеждениям, работать в противофазе.

Если кто разбирался, подскажите.

/*****************************************************************************
SPI_Configuration (); 
******************************************************************************/
void SPI2_Configuration(void)
{
 SPI_InitTypeDef   SPI_InitStructure;

 Config_SPI2_Pin ();		   
 RCC_APB1PeriphResetCmd (RCC_APB1Periph_SPI2, DISABLE);
 RCC_APB1PeriphClockCmd (RCC_APB1Periph_SPI2, ENABLE);

 SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //Config SPI Protocol
 SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
 SPI_InitStructure.SPI_NSS = SPI_NSS_Hard;		//
 SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
 SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;			 // 
 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;		   // 
 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;		 //
 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;  // 
 SPI_Init(SPI2, &SPI_InitStructure);
 SPI_Cmd(SPI2, ENABLE);
 SPI_CalculateCRC(SPI2, DISABLE);
 SPI_SSOutputCmd(SPI2, ENABLE); 

 Cnt_Tx = Cnt_Rx =0;	
 SPI_Protocol_Out.DD = AED_Answer_Prepare (Cmd_Power_ON);		  
 SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, ENABLE);
 SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, ENABLE);

} //  SPI2_Configuration()

/*****************************************************************************
SPI1_IRQHandler (); 
******************************************************************************/
__irq void SPI2_IRQHandler(void)
{
 if (SPI2->SR & SPI_I2S_FLAG_TXE)
  {
  SPI2->DR = SPI_Protocol_Out.D08 [Cnt_Tx]; 

if (++Cnt_Tx == Cnt_Pack) Cnt_Tx = 0;					 // Clear Cnt		
  }

 if (SPI2->SR & SPI_I2S_FLAG_RXNE)
  {
  SPI_Protocol_In.D08 [Cnt_Rx] = SPI2->DR;

 if (++Cnt_Rx == Cnt_Pack) 
  { 

  if (CRC_16((u8 *)SPI_Protocol_In.D08, Cnt_Pack-2) == SPI_Protocol_In.DD.CRC16)  pCtrl-> Link_SPI = True; 
  Cnt_Rx =0;
  } 
 }

} // __irq SPI2_IRQHandler()

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

TXE, - передающий буфер пустой (TX empty)

RXNE, - приемный буфер не пустой (RX not empty)

 

ИМХО эти флаги должны выставляться одновременно.

 

Вы пихаете что-то в ТХ, и стираете RХ, как только TX уйдет, RX наполниться и оба флага должны появиться...

 

Есть возможно малюсенькая задержка между появлением RX и уходом данных из ТХ в которую вы иногда попадали...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Есть, возможно, малюсенькая задержка между появлением RX и уходом данных из ТХ
Задержка в половину бита. RXNE по идее должен выставляться на половину бита раньше - нога RX опрашивается в середине бита.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

TXE, - передающий буфер пустой (TX empty)

RXNE, - приемный буфер не пустой (RX not empty)

 

ИМХО эти флаги должны выставляться одновременно.

 

Вы пихаете что-то в ТХ, и стираете RХ, как только TX уйдет, RX наполниться и оба флага должны появиться...

 

Есть возможно малюсенькая задержка между появлением RX и уходом данных из ТХ в которую вы иногда попадали...

Советую повнимательнее почитать документацию.

В начальный момент, когда нет передаваемых данных выставлен TXE.

Записываем в DR данные, TXE сбрасывается и через такт устанавливается, т.к. данные из буферного регистра копируются в передатчик и буферный регистр снова свободен. При этом RXNE установится только после приема первого байта причем в момент защелкивания последнего бита. Для побайтовой передачи считаю этот момент существенным. При непрерывной передаче RXNE появляется на один такт раньше, чем TXE. Картинки есть в UM.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а если как освободился TXE в передатчик подать байт?, при этом SPI slave, то после передачи первого байта если мастер не просит следующий, сколько флагов будет стоять?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мастер в SPI не просит байты, он только выдаёт клоки. Сколько послал клоков, столько и будет передано байт.

Думаю проблемы у ТС в том, что он не учитывает, что при так написанной передаче как у него, в первом

SPI-кадре будет записано в DR на одно слово больше, чем принято. А в дальнейших SPI-кадрах, первым

будет передаваться слово, записанное в прошлом SPI-кадре. И всегда будет сдвиг на одно лишнее слово.

 

PS: Совет как всегда один - ТС, читай мануал!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Думаю проблемы у ТС в том, что он не учитывает, что при так написанной передаче как у него, в первом

SPI-кадре будет записано в DR на одно слово больше, чем принято. А в дальнейших SPI-кадрах, первым

будет передаваться слово, записанное в прошлом SPI-кадре. И всегда будет сдвиг на одно лишнее слово.

 

Я учитываю эти закономерности. Вот выдержка из RM0090.

The transmit sequence begins when the slave device receives the clock signal and the most

significant bit of the data on its MOSI pin. The remaining bits (the 7 bits in 8-bit data frame

format, and the 15 bits in 16-bit data frame format) are loaded into the shift-register. The

TXE flag in the SPI_SR register is set on the transfer of data from the Tx Buffer to the shift

register and an interrupt is generated if the TXEIE bit in the SPI_CR2 register is set.

 

Но прерывание от TXE формируется сразу, как только его разрешаю и таким образом в DR заносится первое слово текущего кадра. Когда завершен прием текущего кадра, то основная программа в DR записывает начало следующего кадра. Вроде все логично. Примерчик, что в начале поста, работает, но иногда появляется рассогласавание: количество переданных слов больше принятых.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

но иногда появляется рассогласавание: количество переданных слов больше принятых.
а вы часом не в отладчике смотрите? а то там есть мелкая грабля - если отладчик считал данные с регистра раньше программы, флаг сбрасывается

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

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

×
×
  • Создать...