STM32F4 HAL SPI作为从设备/与ESP连接的设备作为主设备
我尝试将Nucleo-STMF411RE作为SPI从/设备运行,并将ESP32作为主设备 单向数据传输运行平稳,但一旦设备将数据传输回主设备,设备就会损坏 我的SPI主控端如下所示:STM32F4 HAL SPI作为从设备/与ESP连接的设备作为主设备,stm32,spi,esp32,hal,Stm32,Spi,Esp32,Hal,我尝试将Nucleo-STMF411RE作为SPI从/设备运行,并将ESP32作为主设备 单向数据传输运行平稳,但一旦设备将数据传输回主设备,设备就会损坏 我的SPI主控端如下所示: void setup() { // put your setup code here, to run once: Serial.begin(9600); pinMode(SPI_MOSI, OUTPUT); //MOSI 23 pinMode(SPI_MISO, INPUT); //MIS
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(SPI_MOSI, OUTPUT); //MOSI 23
pinMode(SPI_MISO, INPUT); //MISO 19
pinMode(SPI_SCK, OUTPUT); //CLK 18
pinMode(SPI_CS, OUTPUT); //SS/CS 5
digitalWrite(SPI_CS, HIGH); // disable Slave Select
SPI.begin ();
SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV64);
SPI.setDataMode(SPI_MODE0);
}
void loop() {
// put your main code here, to run repeatedly:
sendData(a, 0x01020304);
a++;
delay(3000);
}
void sendData(unsigned long address, unsigned long datagram)
{
uint8_t TxBuff[5] = {0,0,0,0,0};
uint8_t RxBuff[5] ={0,0,0,0,0};
TxBuff[0] = address;
TxBuff[1] = (datagram >> 24) & 0xff;
TxBuff[2] = (datagram >> 16) & 0xff;
TxBuff[3] = (datagram >> 8) & 0xff;
TxBuff[4] = (datagram >> 0) & 0xff;
Serial.print("Tx: 0x");
Serial.print(TxBuff[0], HEX);
Serial.print(" 0x");
Serial.print(TxBuff[1], HEX);
Serial.print(TxBuff[2], HEX);
Serial.print(TxBuff[3], HEX);
Serial.println(TxBuff[4], HEX);
digitalWrite(SPI_CS,LOW);
delayMicroseconds(10);
SPI.transferBytes((uint8_t *)&TxBuff,(uint8_t *)&RxBuff, 5);
delayMicroseconds(10);
digitalWrite(SPI_CS,HIGH);
Serial.print("Rx: 0x");
Serial.print(RxBuff[0], HEX);
Serial.print(" 0x");
Serial.print(RxBuff[1], HEX);
Serial.print(RxBuff[2], HEX);
Serial.print(RxBuff[3], HEX);
Serial.print(RxBuff[4], HEX);
Serial.println("");
}
在STM方面,我使用的是HAL和MXCube生成的代码。我已经尝试过中断和阻塞方法,但两者都得到了同样不满意的结果
这是我的SPI2时钟和初始化代码:
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 16;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
RCC_OscInitStruct.PLL.PLLQ = 4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
static void MX_SPI2_Init(void)
{
/* USER CODE BEGIN SPI2_Init 0 */
/* USER CODE END SPI2_Init 0 */
/* USER CODE BEGIN SPI2_Init 1 */
/* USER CODE END SPI2_Init 1 */
/* SPI2 parameter configuration*/
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_SLAVE;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI2_Init 2 */
/* USER CODE END SPI2_Init 2 */
}
在我的while(1)中,我要求提供从机的select引脚,一旦引脚变低,从机就准备好接收/发送:
while (1) {
slave_select = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12);
if (slave_select == 0) {
status = HAL_SPI_Receive(&hspi2, (uint8_t *) aRxBuffer, 5, 5000);
}
}
当我用
status=HAL_SPI_TransmitReceive(&hspi2,(uint8_t*)aTxBuffer,(uint8_t*)aRxBuffer,5,5000)替换HAL接收函数时代码>事情变得不同步,甚至接收到的数据也不再正确。我真的不知道问题出在哪里,因为我已经尝试了多个电路板和平台。经过几周的尝试和失败,我发现这一定是EMI问题。我知道SPI的连接不应该太长,在我的情况下,带状电缆的长度为15厘米。过了一段时间,我发现在带状电缆上使用SPI这样的协议时,信号线之间应该有公共GND,如下所示:
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(SPI_MOSI, OUTPUT); //MOSI 23
pinMode(SPI_MISO, INPUT); //MISO 19
pinMode(SPI_SCK, OUTPUT); //CLK 18
pinMode(SPI_CS, OUTPUT); //SS/CS 5
digitalWrite(SPI_CS, HIGH); // disable Slave Select
SPI.begin ();
SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV64);
SPI.setDataMode(SPI_MODE0);
}
void loop() {
// put your main code here, to run repeatedly:
sendData(a, 0x01020304);
a++;
delay(3000);
}
void sendData(unsigned long address, unsigned long datagram)
{
uint8_t TxBuff[5] = {0,0,0,0,0};
uint8_t RxBuff[5] ={0,0,0,0,0};
TxBuff[0] = address;
TxBuff[1] = (datagram >> 24) & 0xff;
TxBuff[2] = (datagram >> 16) & 0xff;
TxBuff[3] = (datagram >> 8) & 0xff;
TxBuff[4] = (datagram >> 0) & 0xff;
Serial.print("Tx: 0x");
Serial.print(TxBuff[0], HEX);
Serial.print(" 0x");
Serial.print(TxBuff[1], HEX);
Serial.print(TxBuff[2], HEX);
Serial.print(TxBuff[3], HEX);
Serial.println(TxBuff[4], HEX);
digitalWrite(SPI_CS,LOW);
delayMicroseconds(10);
SPI.transferBytes((uint8_t *)&TxBuff,(uint8_t *)&RxBuff, 5);
delayMicroseconds(10);
digitalWrite(SPI_CS,HIGH);
Serial.print("Rx: 0x");
Serial.print(RxBuff[0], HEX);
Serial.print(" 0x");
Serial.print(RxBuff[1], HEX);
Serial.print(RxBuff[2], HEX);
Serial.print(RxBuff[3], HEX);
Serial.print(RxBuff[4], HEX);
Serial.println("");
}
GND-MOSI-GND-GND-MISO-GND-GND-SCK-GND-GND-CS-GND
或者,您可以分开电缆,使用更短的电缆
这为我解决了问题=)