你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

SPI接收中断溢出后该如何处理?

[复制链接]
any012 提问时间:2017-5-13 10:26 /
20ST金币
本帖最后由 any012 于 2017-5-13 11:04 编辑

用STM32F103的SPI2作为SPI从设备接收主设备发送过来的固定长度的数据。
主设备每秒发送一次。切有个类似片选信号给了从设备的PC6引脚。
那么我在PC6上升沿中断里,开启SPI中断接收函数。

现在主设备先启动后,从设备再启动,接收没问题。
如果主从设备同时启动,则从设备只接收了一次数据就不再接收了,且接收的数据是错误的。(也许主设备启动时发送的数据就是错的)
现在发现出错时是SPI接收溢出了。

我在溢出判断部分那里,加了个printf语句,如果printf语句里有\r\n,则接收错误出现两次后就变正常了。而是其他的字符的话,则一直是溢出错误。
请教,为什么会一直是溢出错误呢?这里明明是判断溢出错误后就把溢出标志清楚了,然后调用了错误处理回调函数(没有处理,也就是空的吧)。那么为什么下次接收数据时还是溢出错误呢?

SPI中断处理函数为:

  1. void SPI2_IRQHandler(void)
  2. {
  3.   /* USER CODE BEGIN SPI2_IRQn 0 */

  4.   /* USER CODE END SPI2_IRQn 0 */
  5.   HAL_SPI_IRQHandler(&hspi2);
  6.   /* USER CODE BEGIN SPI2_IRQn 1 */

  7.   /* USER CODE END SPI2_IRQn 1 */
  8. }
复制代码

然后HAL_SPI_IRQHandler()函数里有:
  1. <div>        /* SPI Overrun error interrupt occurred -----------------------------------*/
  2.         if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_OVR) != RESET)
  3.         {
  4.             printf("hahahaha!");       //这里改为printf("\r\n");则接收错误两次后就正确了。
  5.            if (hspi->State != HAL_SPI_STATE_BUSY_TX)
  6.             {
  7.                 SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_OVR);
  8.                 __HAL_SPI_CLEAR_OVRFLAG(hspi);
  9.                 printf("spi ovr err.");
  10.             }
  11. </div><div>        }</div>
复制代码
下图为溢出错误判断部分,加入了printf("\r\n")语句后的接收数据。是利用串口发送上来的。
QQ图片20170513110003.png

下图为将printf语句中的\r\n去掉后的情况。
QQ图片20170513110138.png


最佳答案

查看完整内容

在中断服务函数里调用printf可真糟糕,中断执行时间太长,来不及处理。
收藏 1 评论9 发布时间:2017-5-13 10:26

举报

9个回答
zoomdy 回答时间:2017-5-13 10:26:04
在中断服务函数里调用printf可真糟糕,中断执行时间太长,来不及处理。
any012 回答时间:2017-5-16 11:19:48
一般出现溢出错误,按说应该会立刻关闭中断,直到下次PC6上升沿来时再开启中断。
可现在的结果是,开机时,第1秒内,有多次溢出错误处理。以后就是每秒一次。难道开机时PC6引脚有多次脉冲?
  1. if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
  2.         {
  3. //            HAL_GPIO_WritePin(ERR_GPIO_Port, ERR_Pin, GPIO_PIN_SET);
  4.             __HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXNE | SPI_IT_TXE | SPI_IT_ERR);
  5.             hspi->State = HAL_SPI_STATE_READY;
  6.             HAL_SPI_ErrorCallback(hspi);
  7.         }
复制代码

any012 回答时间:2017-5-18 09:40:27
本帖最后由 any012 于 2017-5-18 09:47 编辑

找到问题了。
接收的时候,出现异常时,接收数据溢出,中断处理函数里,判断溢出错误后,就清掉溢出错误标志,然后转到错误处理部分。
错误处理部分里关闭了接收中断,但是在关闭接收中断之前,又有新的数据到来,结果又溢出错误了。
最后的结果就是下次开启接收中断时,直接就溢出错误了。以上,周而复始。

在错误处理部分,关闭接收中断后,再清一次溢出错误标志即可。
或者,开启SPI接收的时候,是否应该先把各标志位清一遍?

  1. /* SPI Overrun error interrupt occurred -----------------------------------*/
  2.         if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_OVR) != RESET)
  3.         {
  4.             if (hspi->State != HAL_SPI_STATE_BUSY_TX)
  5.             {
  6.                 SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_OVR);
  7.                 __HAL_SPI_CLEAR_OVRFLAG(hspi);
  8.                 printf("spi ovr err.");
  9.             }
  10.         }

  11.         /* Call the Error call Back in case of Errors */
  12.         if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
  13.         {
  14.             __HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXNE | SPI_IT_TXE | SPI_IT_ERR);
  15.             __HAL_SPI_CLEAR_OVRFLAG(hspi);                                                         //关闭中断后,再清一次溢出错误标志。
  16.             hspi->State = HAL_SPI_STATE_READY;
  17.             HAL_SPI_ErrorCallback(hspi);
  18.         }
复制代码



any012 回答时间:2017-5-18 11:06:23
虽然SPI中断接收遇到的这个问题解决了,但是用DMA方式接收还是没解决...
any012 回答时间:2017-5-18 14:30:08
额,用万用表表笔反复碰触,结果接收数据仍发生位移,且位移会一直保持。和DMA方式接收的现象基本一致。
Qiuliu 回答时间:2020-2-25 12:35:31
DMA的模式解决了么?现在我也遇到这样的问题了,但是一直溢出错误。
非我非非我 回答时间:2020-3-12 14:35:26
xingfudaxia 发表于 2020-2-25 12:35
DMA的模式解决了么?现在我也遇到这样的问题了,但是一直溢出错误。

同溢出错误,请问有解决吗?
Qiuliu 回答时间:2020-6-23 13:49:22
非我非非我 发表于 2020-3-12 14:35
同溢出错误,请问有解决吗?

可以查看溢出错误标志位,根据清除标志位就可。

所属标签

相似问题

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版