STM32F207 SPI从机偶发BSY标志挂起问题求助
STM32F207 Nucleo SPI从机偶发BSY标志持续置位问题
SPI初始化配置
当前使用无硬件NSS的双线仅接收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);
中断服务实现
从机采用中断方式工作,中断服务逻辑简单,额外引出测试引脚用于在逻辑分析仪上观测中断活动:
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); }
选通信号处理与状态检查
未使用SPI硬件NSS信号,主机完成4字节传输后发送选通信号,从机通过EXTI回调中断响应此信号,同样配有测试引脚观测中断活动:
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时钟也无法清除该标志,出现概率无规律——有时在10万次正常传输后触发,有时仅500次传输后就出现。已多次用示波器检查SPI时钟与数据信号,信号干净无尖峰,但发送数百个额外时钟仍无法复位BSY信号。
临时恢复方案
目前唯一可行的恢复方法是强制SPI复位,参考代码如下(注:原代码针对SPI2,实际使用SPI1需对应修改):
__HAL_RCC_SPI2_FORCE_RESET(); __HAL_RCC_SPI2_RELEASE_RESET();
若无法定位问题根源,可能只能在每次传输后执行SPI复位操作。
更新补充
【更新】此前用于生成额外SPI时钟的连接存在异常,现在发现需要发送额外8个时钟才能使BSY标志变低——意味着SPI内部启动了新的帧,但最后一帧传输时并没有输入额外时钟。
逻辑分析仪截图
- 正常传输截图:

- BSY标志挂起截图(更新后):

内容的提问来源于stack exchange,提问作者jokn
相关产品推荐
相关产品推荐

