在half-duplex/simplex模式STM32F4中停用SPI的正确方法
Correct way to deactivate SPI in half-duplex/simplex mode STM32F4
我正在尝试在一定时间后将 STM32F4 从从机更改为主机,以主机身份发送消息,然后返回到从机。我发现将 SPI 配置为 slave_rxonly 并启用 SPI 将导致时钟在我将设备配置回主控时意外发送时钟。没有我发送任何数据。我假设是因为我错误地初始化了外围设备或错误地取消了它
这是我的主循环。
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
MX_SPI1_Init(); /* This configures master */
HAL_Delay(10);
sendHelloWorld();
configSlave(); /* Configures slave mode */
__HAL_SPI_ENABLE(&hspi1); /* Enabling the device in this mode generates a continous clock during master init */
HAL_Delay(100);
HAL_SPI_DeInit(&hspi1); /* Disables SPI and de-initializes the peripheral */
}
我的主配置:
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
我的奴隶配置:
if(HAL_SPI_DeInit(&hspi1) != HAL_ERROR)
{
/* SPI1 parameter configuration*/
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_SLAVE;
hspi1.Init.Direction = SPI_DIRECTION_2LINES_RXONLY;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
}
这是我的逻辑分析仪的波形。一旦我 运行 函数 MX_SPI1_Init() 在启用 SPI 作为从设备后,就会生成时钟。橙色是时钟,正如您所见 - 从 10 毫秒的延迟开始 - 它在初始化为主机后立即启用。
有什么想法吗?我已经为这个问题奋斗了一个多星期,并尝试了很多东西
可能是垃圾HAL函数不小心暂时变成了master rx-only。各种 HAL 函数在写入寄存器的顺序上都很幼稚,并会产生这样的故障。在重新配置之前尝试调用 HAL_SPI_DeInit
。或者干脆放弃 HAL。
Master RX-only 总是要盲目输出时钟。如果您想控制何时发送时钟,请使用主 tx 和 rx 模式,然后写入与您要读取的相同数量的虚拟数据。如果您希望 MOSI 保持三态并且不发送虚拟数据,那么您可以在执行此操作时将引脚更改为 GPIO 模式。
我正在尝试在一定时间后将 STM32F4 从从机更改为主机,以主机身份发送消息,然后返回到从机。我发现将 SPI 配置为 slave_rxonly 并启用 SPI 将导致时钟在我将设备配置回主控时意外发送时钟。没有我发送任何数据。我假设是因为我错误地初始化了外围设备或错误地取消了它
这是我的主循环。
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
MX_SPI1_Init(); /* This configures master */
HAL_Delay(10);
sendHelloWorld();
configSlave(); /* Configures slave mode */
__HAL_SPI_ENABLE(&hspi1); /* Enabling the device in this mode generates a continous clock during master init */
HAL_Delay(100);
HAL_SPI_DeInit(&hspi1); /* Disables SPI and de-initializes the peripheral */
}
我的主配置:
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
我的奴隶配置:
if(HAL_SPI_DeInit(&hspi1) != HAL_ERROR)
{
/* SPI1 parameter configuration*/
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_SLAVE;
hspi1.Init.Direction = SPI_DIRECTION_2LINES_RXONLY;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
}
这是我的逻辑分析仪的波形。一旦我 运行 函数 MX_SPI1_Init() 在启用 SPI 作为从设备后,就会生成时钟。橙色是时钟,正如您所见 - 从 10 毫秒的延迟开始 - 它在初始化为主机后立即启用。
有什么想法吗?我已经为这个问题奋斗了一个多星期,并尝试了很多东西
可能是垃圾HAL函数不小心暂时变成了master rx-only。各种 HAL 函数在写入寄存器的顺序上都很幼稚,并会产生这样的故障。在重新配置之前尝试调用 HAL_SPI_DeInit
。或者干脆放弃 HAL。
Master RX-only 总是要盲目输出时钟。如果您想控制何时发送时钟,请使用主 tx 和 rx 模式,然后写入与您要读取的相同数量的虚拟数据。如果您希望 MOSI 保持三态并且不发送虚拟数据,那么您可以在执行此操作时将引脚更改为 GPIO 模式。