STM32 SPI slave 有时挂在忙标志上

问题描述 投票:0回答:0

我正在 STM32F207 Nucleo 板上测试一个简单的 SPI-Slave。它是没有硬件 NSS 的 2 线仅接收 SPI 从机。这是我的 SPI 初始化:

  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;
  HAL_SPI_Init(&hspi1);

Slave 在 Interrupt 下工作,有一个非常简单的中断服务例程。一个额外的测试引脚显示我的逻辑分析仪上的中断活动。

void SPI1_IRQHandler(void)
{
    HAL_GPIO_WritePin (GPIOE, SPI_IRQ_Pin, GPIO_PIN_SET);
    shift_reg = (shift_reg << 8) | SPI1->DR;
    ++SPI_byte_cnt;
    HAL_GPIO_WritePin (GPIOE, SPI_IRQ_Pin, GPIO_PIN_RESET);
}

主机在 4 字节传输结束时发送选通信号,而不是 SPI-NSS 信号。从站有一个额外的中断服务(EXTI-Callback)来响应这个选通信号。同样,测试引脚显示中断活动。

void vmShiftreg_Latch()
{
    HAL_GPIO_WritePin (GPIOE, STR_IRQ_Pin, GPIO_PIN_SET);
    if (Check_SPI (4)) {
        shift_latch = shift_reg;
    }
    shift_reg = 0;
    HAL_GPIO_WritePin (GPIOE, STR_IRQ_Pin, GPIO_PIN_RESET);
}

此中断服务还检查 SPI 状态和传输的字节数:

int Check_SPI (int bytes_needed)
{
    int byte_read = SPI_byte_cnt;
    SPI_byte_cnt = 0;
    
    if ((SPI1->SR & SPI_SR_OVR ) != 0) {
        shift_reg = SPI1->DR;
        shift_reg = SPI1->SR;
        ++ovr_error_cnt;
        return 0;
    }

    if ((SPI1->SR & SPI_SR_BSY) != 0) {
        HAL_GPIO_WritePin (GPIOE, BSY_ERR_Pin, GPIO_PIN_SET);
        ++bsy_error_cnt;
        Recover_SPI1();
        HAL_GPIO_WritePin (GPIOE, BSY_ERR_Pin, GPIO_PIN_RESET);
        return 0;
    }

    if (byte_read != bytes_needed) {
        ++shift_error_cnt;
        return 0;
    }

    return 1;
}

现在有时会发生 BSY 标志保持活动状态并且没有任何东西,甚至没有额外的 SPI 时钟,可以重置这个忙碌标志。这有时会在 100000 次正确传输之后或有时在 500 次之后非常随机地发生。 是的,我用示波器一次又一次地检查了 SPI 信号(时钟和数据),但它们很干净,没有任何尖峰。对我来说这似乎很疯狂,即使是数百个额外的 SPI 时钟也无法重置 bsy 信号。

让他回来的唯一解决方案是强制重置 SPI,这是我在这篇post中发现的:

__HAL_RCC_SPI2_FORCE_RESET();
__HAL_RCC_SPI2_RELEASE_RESET();

有人见过这么疯狂的行为吗? 如果我无法找出问题所在,我想我别无选择,只能在每次传输后重置 SPI。

这是我的逻辑分析仪的两张截图。第一个正确传输,第二个显示挂着忙标志。

有更新: 我在从站上使用的额外时钟连接来生成 SPI 时钟无法正常工作。现在我可以看到需要额外的 8 个时钟才能使 BSY 标志变低。换句话说,SPI 确实在内部开始了一个新的帧,即使最后一帧没有额外的时钟。

正确传输的截图

第二个屏幕截图,上面挂着忙碌标志(更新)

stm32 communication spi
© www.soinside.com 2019 - 2024. All rights reserved.