Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Про SPI STM32F405
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Vladimir_T
Уважаемые коллеги, посмотрите на этот код. 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()
vlad_new
У меня то же не вышло работать с обоими флагами. Использую только флаг приема, поскольку он то же выставляется после передачи байта.
Golikov A.
TXE, - передающий буфер пустой (TX empty)
RXNE, - приемный буфер не пустой (RX not empty)

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

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

Есть возможно малюсенькая задержка между появлением RX и уходом данных из ТХ в которую вы иногда попадали...
Сергей Борщ
Цитата(Golikov A. @ Jul 1 2014, 17:52) *
Есть, возможно, малюсенькая задержка между появлением RX и уходом данных из ТХ
Задержка в половину бита. RXNE по идее должен выставляться на половину бита раньше - нога RX опрашивается в середине бита.
adnega
Цитата(Golikov A. @ Jul 1 2014, 18:52) *
TXE, - передающий буфер пустой (TX empty)
RXNE, - приемный буфер не пустой (RX not empty)

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

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

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

Советую повнимательнее почитать документацию.
В начальный момент, когда нет передаваемых данных выставлен TXE.
Записываем в DR данные, TXE сбрасывается и через такт устанавливается, т.к. данные из буферного регистра копируются в передатчик и буферный регистр снова свободен. При этом RXNE установится только после приема первого байта причем в момент защелкивания последнего бита. Для побайтовой передачи считаю этот момент существенным. При непрерывной передаче RXNE появляется на один такт раньше, чем TXE. Картинки есть в UM.
Golikov A.
а если как освободился TXE в передатчик подать байт?, при этом SPI slave, то после передачи первого байта если мастер не просит следующий, сколько флагов будет стоять?
jcxz
Мастер в SPI не просит байты, он только выдаёт клоки. Сколько послал клоков, столько и будет передано байт.
Думаю проблемы у ТС в том, что он не учитывает, что при так написанной передаче как у него, в первом
SPI-кадре будет записано в DR на одно слово больше, чем принято. А в дальнейших SPI-кадрах, первым
будет передаваться слово, записанное в прошлом SPI-кадре. И всегда будет сдвиг на одно лишнее слово.

PS: Совет как всегда один - ТС, читай мануал!!!
Vladimir_T
Цитата(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 записывает начало следующего кадра. Вроде все логично. Примерчик, что в начале поста, работает, но иногда появляется рассогласавание: количество переданных слов больше принятых.
jcxz
Возможно у вас баг в той, части исходников что за пределами ISR. Например - в согласовании ISR и обработчика принятых байтов или источника байтов для передачи.
dac
QUOTE (Vladimir_T @ Jul 2 2014, 22:57) *
но иногда появляется рассогласавание: количество переданных слов больше принятых.
а вы часом не в отладчике смотрите? а то там есть мелкая грабля - если отладчик считал данные с регистра раньше программы, флаг сбрасывается
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.