Vladimir_T 1 30 июня, 2014 Опубликовано 30 июня, 2014 (изменено) · Жалоба Уважаемые коллеги, посмотрите на этот код. 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() Изменено 1 июля, 2014 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vlad_new 1 1 июля, 2014 Опубликовано 1 июля, 2014 · Жалоба У меня то же не вышло работать с обоими флагами. Использую только флаг приема, поскольку он то же выставляется после передачи байта. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 1 июля, 2014 Опубликовано 1 июля, 2014 · Жалоба TXE, - передающий буфер пустой (TX empty) RXNE, - приемный буфер не пустой (RX not empty) ИМХО эти флаги должны выставляться одновременно. Вы пихаете что-то в ТХ, и стираете RХ, как только TX уйдет, RX наполниться и оба флага должны появиться... Есть возможно малюсенькая задержка между появлением RX и уходом данных из ТХ в которую вы иногда попадали... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 1 июля, 2014 Опубликовано 1 июля, 2014 · Жалоба Есть, возможно, малюсенькая задержка между появлением RX и уходом данных из ТХЗадержка в половину бита. RXNE по идее должен выставляться на половину бита раньше - нога RX опрашивается в середине бита. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 1 июля, 2014 Опубликовано 1 июля, 2014 · Жалоба TXE, - передающий буфер пустой (TX empty) RXNE, - приемный буфер не пустой (RX not empty) ИМХО эти флаги должны выставляться одновременно. Вы пихаете что-то в ТХ, и стираете RХ, как только TX уйдет, RX наполниться и оба флага должны появиться... Есть возможно малюсенькая задержка между появлением RX и уходом данных из ТХ в которую вы иногда попадали... Советую повнимательнее почитать документацию. В начальный момент, когда нет передаваемых данных выставлен TXE. Записываем в DR данные, TXE сбрасывается и через такт устанавливается, т.к. данные из буферного регистра копируются в передатчик и буферный регистр снова свободен. При этом RXNE установится только после приема первого байта причем в момент защелкивания последнего бита. Для побайтовой передачи считаю этот момент существенным. При непрерывной передаче RXNE появляется на один такт раньше, чем TXE. Картинки есть в UM. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 1 июля, 2014 Опубликовано 1 июля, 2014 · Жалоба а если как освободился TXE в передатчик подать байт?, при этом SPI slave, то после передачи первого байта если мастер не просит следующий, сколько флагов будет стоять? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 1 июля, 2014 Опубликовано 1 июля, 2014 · Жалоба Мастер в SPI не просит байты, он только выдаёт клоки. Сколько послал клоков, столько и будет передано байт. Думаю проблемы у ТС в том, что он не учитывает, что при так написанной передаче как у него, в первом SPI-кадре будет записано в DR на одно слово больше, чем принято. А в дальнейших SPI-кадрах, первым будет передаваться слово, записанное в прошлом SPI-кадре. И всегда будет сдвиг на одно лишнее слово. PS: Совет как всегда один - ТС, читай мануал!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vladimir_T 1 2 июля, 2014 Опубликовано 2 июля, 2014 · Жалоба Думаю проблемы у ТС в том, что он не учитывает, что при так написанной передаче как у него, в первом 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 243 3 июля, 2014 Опубликовано 3 июля, 2014 · Жалоба Возможно у вас баг в той, части исходников что за пределами ISR. Например - в согласовании ISR и обработчика принятых байтов или источника байтов для передачи. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dac 0 3 июля, 2014 Опубликовано 3 июля, 2014 · Жалоба но иногда появляется рассогласавание: количество переданных слов больше принятых. а вы часом не в отладчике смотрите? а то там есть мелкая грабля - если отладчик считал данные с регистра раньше программы, флаг сбрасывается Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться