Ich versuche, eine SPI-Kommunikation zwischen einem RPi (als MASTER) und einem STM32F410 (als SLAVE, auf einem Nucleo-Board) herzustellen. Mein PoC ist einfach, ich sende 8 Bytes vom Rpi und drucke sie mit dem UART-over-USB auf dem Nucleo aus. Hier ist der Sendecode (in Python), der auf dem Rasberry Pi läuft:
spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 8000000
to_send = [1,2,3,4,5,6,7,8]
#spi.writebytes(to_send)
spi.xfer(to_send)
und der Empfangscode auf dem STM32:
while(1) {
memset(buf, 0, BRAIN_COM_BUF_SIZE);
HAL_SPI_Receive(&hspi5, (uint8_t*)&buf, BRAIN_COM_BUF_SIZE, HAL_MAX_DELAY);
sprintf((char*) dbg_buffer, "[%d][%d][%d][%d][%d][%d][%d][%d]\r\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
HAL_UART_Transmit(&huart2, dbg_buffer, strlen((char const*) dbg_buffer), 1000);
}
und mein SPI-Initialisierungscode (generiert von CubeMX):
/* SPI5 init function */
void MX_SPI5_Init(void)
{
hspi5.Instance = SPI5;
hspi5.Init.Mode = SPI_MODE_SLAVE;
hspi5.Init.Direction = SPI_DIRECTION_2LINES;
hspi5.Init.DataSize = SPI_DATASIZE_8BIT;
hspi5.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi5.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi5.Init.NSS = SPI_NSS_SOFT;
hspi5.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi5.Init.TIMode = SPI_TIMODE_DISABLE;
hspi5.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi5.Init.CRCPolynomial = 15;
if (HAL_SPI_Init(&hspi5) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
Nichts Besonderes, oder? Dies ist eine reine Eins-zu-Eins-Kommunikation, aber ich habe den CS-Pin trotzdem eingestellt und konfiguriert. Mein Problem mit diesem Code ist, dass er höchstens in 5 % der Fälle wie IDK funktioniert. Den Rest der Zeit bekam ich Müll oder noch schlimmer, es sieht so aus, als hätte die Funktion HAL_SPI_Receive() absolut nichts bekommen.
Beispiel für aktuelles Verhalten:
Ich sende: [1][2][3][4][5][6][7][8] und der STM32 empfängt: [0][0][1][1][2][2] [3][3]
Alle Hinweise und/oder Hilfe, um mich freizuschalten, werden sehr nützlich sein, danke!
Das /CS
Signal wird sogar mit nur einem einzigen Peripheriegerät benötigt, da es der Schlüssel zum Erreichen der Wortsynchronisation zwischen Sender und Empfänger ist – der Empfänger weiß, dass der erste Takt nach dem /CS
Low-Pegel dem ersten Datenbit im Wort entspricht. Da SPI
es sich bei einer synchronous
Schnittstelle typischerweise um eine minimale Taktfrequenz handelt, interpretiert der Empfänger ohne Synchronisation einfach den ersten Takt, den er sieht (zu einem Zeitpunkt, zu dem er nach einem sucht), als Beginn eines Wortes.
Alternative Schemata, bei denen der Beginn eines Wortes durch eine Zeitlücke in der Taktung angezeigt wird, sind möglich, aber das sind sie nicht wirklich, SPI
und Ihr Code unternimmt keinen Versuch, so etwas zu implementieren. Kritisch, wenn es jemals zu einer Fehlkoordinierung kommt, z. B. wenn der Sender erneut sendet, während der Empfänger nach einem abgelaufenen Empfangsversuch noch damit beschäftigt ist, eine serielle Ausgabe zu erzeugen oder zu recyceln, kann es durchaus sein, dass er damit beginnt, Bits aus dem falschen Taktzyklus zu empfangen.
Und selbst wenn Sie am Ende nicht mit verschobenen Bits in einem Wort enden, können Sie immer noch mit verschobenen Wörtern in einer Nachricht enden.
Schließlich müssen Sie bei der Kommunikation auf Binärebene zwischen unterschiedlichen Systemen, die verschiedene Sprachen verwenden, darauf achten, dass sie kompatible Datencodierungen verwenden. Python verfügt über Funktionen zum Packen binärer Datenobjekte in so ziemlich jeder gewünschten Kombination aus Elementgröße und Endianness. Es wäre gut, diese zu verwenden, um explizit die Kompatibilität mit dem Datentyp herzustellen, als den der STM32 die empfangenen Informationen interpretiert.
/CS
aktiviert lassen, es aber trennen und hoch binden? Wenn nicht, haben Sie die Dinge nicht wirklich davon abhängig gemacht. Es sieht auch so aus, als ob Sie wahrscheinlich einen Rückgabewert der Lesefunktion auf Erfolg überprüfen sollten oder wie viele Bytes empfangen wurden. Und die "Verdopplung" ist auch verdächtig für eine andere Art von Softwareproblem.hspi5.Init.NSS = SPI_NSS_HARD_INPUT;
und den entsprechenden Code in HAL_SPI_MspInit(), der von CubeMX generiert wurde. Kann ich sonst noch etwas tun? Oh, und ich habe vorhin einen Fehler gemacht, mit CS, das auf STM32 (Slave) an HIGH gebunden ist, habe ich tatsächlich nichts gelesen. Sieht so aus, als ob auf STM32 alles in Ordnung ist, also ... Python-Seite?HAL_StatusTypeDef ret = HAL_SPI_Receive_DMA(&hspi5, (uint8_t*)&buf, BRAIN_COM_BUF_SIZE); while (HAL_SPI_GetState(&hspi5) != HAL_SPI_STATE_READY) {}
und aber es funktioniert... Warum? Das ist in der Tat eine gute Frage...
Chris Stratton
Herr Patate
gustavovelascoh
Herr Patate