реклама на сайте
подробности

 
 
> Про SPI STM32F405
Vladimir_T
сообщение Jun 30 2014, 17:24
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 517
Регистрация: 7-02-06
Пользователь №: 14 073



Уважаемые коллеги, посмотрите на этот код. Yужно обеспечить обмен по SPI (STM32F405 - Slave) между двумя МК. Поддержка обмена по прерываниям от SPI. Идея в том, чтобы к моменту прихода данных в приемник SPI, в передатчике уже есть ответ. Так все и работает, т.е. первым делом разрешается прерывание от флага TXE и в буфер передатчика передается первый байт ответа, затем прием и буфер приемника опустошается и вновь заполняется следующим байтом ответа. Но надежность этого кода низкая: почему-то при входе в прерывание иногда оба флага установлены и TXE, и RXNE. А ведь эти флаги должны, по моим убеждениям, работать в противофазе.
Если кто разбирался, подскажите.
CODE
/*****************************************************************************
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 - Jul 1 2014, 07:49
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Golikov A.
сообщение Jul 1 2014, 18:42
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



а если как освободился TXE в передатчик подать байт?, при этом SPI slave, то после передачи первого байта если мастер не просит следующий, сколько флагов будет стоять?
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jul 1 2014, 23:08
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Мастер в SPI не просит байты, он только выдаёт клоки. Сколько послал клоков, столько и будет передано байт.
Думаю проблемы у ТС в том, что он не учитывает, что при так написанной передаче как у него, в первом
SPI-кадре будет записано в DR на одно слово больше, чем принято. А в дальнейших SPI-кадрах, первым
будет передаваться слово, записанное в прошлом SPI-кадре. И всегда будет сдвиг на одно лишнее слово.

PS: Совет как всегда один - ТС, читай мануал!!!
Go to the top of the page
 
+Quote Post
Vladimir_T
сообщение Jul 2 2014, 16:57
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 517
Регистрация: 7-02-06
Пользователь №: 14 073



Цитата(jcxz @ Jul 2 2014, 03:08) *
Думаю проблемы у ТС в том, что он не учитывает, что при так написанной передаче как у него, в первом
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 записывает начало следующего кадра. Вроде все логично. Примерчик, что в начале поста, работает, но иногда появляется рассогласавание: количество переданных слов больше принятых.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jul 3 2014, 02:03
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Возможно у вас баг в той, части исходников что за пределами ISR. Например - в согласовании ISR и обработчика принятых байтов или источника байтов для передачи.
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 31st July 2025 - 03:38
Рейтинг@Mail.ru


Страница сгенерированна за 0.03453 секунд с 7
ELECTRONIX ©2004-2016