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

HAL库如何设置SPI2一直使能接收中断?

[复制链接]
any012 提问时间:2016-11-24 09:28 /
5ST金币
本帖最后由 any012 于 2016-11-24 09:34 编辑

利用STM32的SPI2作为从设备,想中断接收数据,一直没调通。
现在使这样的,再主函数while(1)循环前,调用一次
HAL_SPI_Receive_IT(&hspi2, (uint8_t *)&spi2RecvBuff[0],2);
主循环里,现在基本清空了。SPI的接收回调函数里,通过串口发送一组数据,然后再调用
HAL_SPI_Receive_IT(&hspi2, (uint8_t *)&spi2RecvBuff[0],2);
想通过这种方法,使SPI2一直处于中断接收使能状态。

结果串口一直没有数据发送过来。用示波器测量SCK和MOSI,是有波形的,和主设备发过来的数据一致。

然后将以上的接收中断函数改成,发送中断函数,使设备不停的发送。
结果测量SCK和MISO,有对应波形,串口也有数据发过来。

是不是调用中断接收函数,还需要做些其他操作?

主函数部分:
  1. int main(void)
  2. {
  3. ...
  4. MX_SPI2_Init();
  5. ...
  6.         HAL_SPI_Receive_IT(&hspi2, (uint8_t *)&spi2RecvBuff[0],2);
  7. ...
  8.         while (1)
  9.         {
  10. ...
  11.         }
  12.         }
  13. }
复制代码



回调函数部分:

  1. void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
  2. {
  3.         printf("\r\nspi2 recive over.");
  4.         HAL_SPI_Receive_IT(&hspi2, (uint8_t *)&spi2RecvBuff[0],1);
  5.         printf("\r\nspi2RecvNum: %d", spi2RecvNum);
  6. }
复制代码

SPI2初始化部分:
  1. <div>/* SPI2 init function */
  2. void MX_SPI2_Init(void)
  3. {
  4.         hspi2.Instance = SPI2;
  5.         hspi2.Init.Mode = SPI_MODE_SLAVE;
  6.         hspi2.Init.Direction = SPI_DIRECTION_2LINES;
  7.         hspi2.Init.DataSize = SPI_DATASIZE_16BIT;
  8.         hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH;
  9.         hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;
  10.         hspi2.Init.NSS = SPI_NSS_SOFT;
  11.         hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
  12.         hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
  13.         hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
  14.         hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  15.         hspi2.Init.CRCPolynomial = 10;
  16.         if (HAL_SPI_Init(&hspi2) != HAL_OK)
  17.         {
  18.                 Error_Handler();
  19.         }
  20. }</div><div>
  21. </div><div>void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
  22. {
  23. GPIO_InitTypeDef GPIO_InitStruct;
  24. </div><div>if(spiHandle->Instance==SPI2)
  25. {
  26. /* USER CODE BEGIN SPI2_MspInit 0 */</div><div> /* USER CODE END SPI2_MspInit 0 */
  27.   /* Peripheral clock enable */
  28.   __HAL_RCC_SPI2_CLK_ENABLE();</div><div>  /**SPI2 GPIO Configuration   
  29.   PB13     ------> SPI2_SCK
  30.   PB14     ------> SPI2_MISO
  31.   PB15     ------> SPI2_MOSI
  32.   */
  33.   GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_15;
  34.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  35.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  36.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);</div><div>  GPIO_InitStruct.Pin = GPIO_PIN_14;
  37.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  38.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  39.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  40.   
  41.   /* Peripheral interrupt init */
  42.   HAL_NVIC_SetPriority(SPI2_IRQn, 0, 0);
  43.   HAL_NVIC_EnableIRQ(SPI2_IRQn);
  44.   /* USER CODE BEGIN SPI2_MspInit 1 */</div><div>  /* USER CODE END SPI2_MspInit 1 */
  45. }
  46. }</div>
复制代码



最佳答案

查看完整内容

我也组数据包,一包传过来,收进去解析检验,正确就进行下一步,出错则要求重发。定长数据包,不满整包的用无效数据补,就不用一个一个去判断了。虽然数据多传了一点,但是DMA速度比中断快。又或者你传包头,从机收到之后解析再决定下次收多少数据。
收藏 2 评论35 发布时间:2016-11-24 09:28

举报

35个回答
衔胆栖冰 回答时间:2016-11-24 09:28:40
any012 发表于 2016-11-25 16:33
没接触过DMA,也曾考虑过DMA。但有个疑问,我这个是作为接收设备,需要判断帧首,长度的。用DMA的话,只 ...

我也组数据包,一包传过来,收进去解析检验,正确就进行下一步,出错则要求重发。定长数据包,不满整包的用无效数据补,就不用一个一个去判断了。虽然数据多传了一点,但是DMA速度比中断快。又或者你传包头,从机收到之后解析再决定下次收多少数据。
any012 回答时间:2016-11-24 09:41:39
又仔细观察了下串口发送上来的数据,接收回调函数,只执行了一次。没有再循环调用接收中断函数。
any012 回答时间:2016-11-24 09:54:54
现在怀疑是没有满足spi2中断接收完成的条件,没有调用回调函数。
any012 回答时间:2016-11-24 10:36:29
放到SPI2_IRQHandler(void)函数里,就可以正常再次调用了。
void SPI2_IRQHandler(void)
{
  /* USER CODE BEGIN SPI2_IRQn 0 */

  /* USER CODE END SPI2_IRQn 0 */
  HAL_SPI_IRQHandler(&hspi2);
        HAL_SPI_Receive_IT(&hspi2, (uint8_t *)&spi2RecvBuff[0],1);
  /* USER CODE BEGIN SPI2_IRQn 1 */

  /* USER CODE END SPI2_IRQn 1 */
}
any012 回答时间:2016-11-24 14:20:26
本帖最后由 any012 于 2016-11-24 14:34 编辑

跟踪 HAL_SPI_Receive_IT(&hspi2, (uint8_t *)&spi2RecvBuff[0],1)函数的调用过程,发现是启动后,执行了一次这个函数后,回调函数也被执行了,然后回调函数再调用这个函数时,没有执行到回调函数这里。感觉是不是嵌套了?
SPI_Receive_IT function is called.
SPI interrupt enable.
SPI enable.
1ms时间到

SPI_RxCloseIRQHandler function is called.
SPI RX interrupt disable.
SPI ERR interrupt disable.
spi2 recive over.
SPI_Receive_IT function is called.
SPI interrupt enable.
1ms时间到

1ms时间到

1ms时间到

-----------------------------------------


进一步,发现HAL_SPI_Receive_IT(&hspi2, (uint8_t *)&spi2RecvBuff[0],1)函数第二次被调用时,只是使能了SPI中断,没有使能SPI。
__HAL_SPI_ENABLE(hspi)没有被执行。
if((hspi->Instance->CR1 &SPI_CR1_SPE) != SPI_CR1_SPE)
    {
      /* Enable SPI peripheral */
      __HAL_SPI_ENABLE(hspi);
  printf("\r\nSPI enable.");
    }

SPI_CR1_SPE是SPI的使能位,这句话应该是,如果SPI没有使能,使能SPI。
但是检查串口输出的数据,SPI是在调用回调函数前,被关闭了的。

---------------------------------

刚才看错了,SPI被使能后,就没有被关闭过。
那么,第二次调用HAL_SPI_Receive_IT(&hspi2, (uint8_t *)&spi2RecvBuff[0],1)后,就一直处于等待接收中断状态。
但奇怪为什么没有触发接收中断。SPI中断已设为最高优先级,主设备是每秒给一次信号。


any012 回答时间:2016-11-24 14:46:55
本帖最后由 any012 于 2016-11-24 14:48 编辑

HAL_SPI_Receive_IT(&hspi2, (uint8_t *)&spi2RecvBuff[0],1)放在回调函数里:

SPI_Receive_IT function is called.
SPI interrupt enable.
SPI enable.
1ms时间到

SPI_RxCloseIRQHandler function is called.
SPI RX interrupt disable.
SPI ERR interrupt disable.
SPI rx callback.
spi2 recive over.
SPI_Receive_IT function is called.
SPI interrupt enable.
1ms时间到

1ms时间到

1ms时间到

----------------------------------------

HAL_SPI_Receive_IT(&hspi2, (uint8_t *)&spi2RecvBuff[0],1)放在中断函数里:

SPI_RxCloseIRQHandler function is called.
SPI RX interrupt disable.
SPI ERR interrupt disable.
SPI rx callback.
spi2 recive over.
SPI_Receive_IT function is called.
SPI interrupt enable.
SPI_Receive_IT function is called.
SPI interrupt enable.
1ms时间到

SPI_RxCloseIRQHandler function is called.
SPI RX interrupt disable.
SPI ERR interrupt disable.
SPI rx callback.
spi2 recive over.
SPI_Receive_IT function is called.
SPI interrupt enable.
SPI_Receive_IT function is called.
SPI interrupt enable.
1ms时间到

SPI_RxCloseIRQHandler function is called.
SPI RX interrupt disable.
SPI ERR interrupt disable.
SPI rx callback.
spi2 recive over.
SPI_Receive_IT function is called.
SPI interrupt enable.
SPI_Receive_IT function is called.
SPI interrupt enable.
1ms时间到
any012 回答时间:2016-11-24 15:11:09
刚才在某些地方加了些printf语句,结果能正常中断接收了。
然后又去掉了调试过程中用到的printf语句,又不行了...
any012 回答时间:2016-11-24 15:32:26
在HAL_StatusTypeDef HAL_SPI_Receive_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)函数里,使中断接收函数指向static void SPI_RxISR(SPI_HandleTypeDef *hspi)函数,并且打开SPI,打开SPI中断,然后该函数结束。

SPI接收中断后,调用static void SPI_RxISR(SPI_HandleTypeDef *hspi)函数。在该函数里,接收够指定字节的数据后,调用SPI_RxCloseIRQHandler(hspi)函数。在该函数里,关闭SPI接收中断,调用接收完成回掉函数。接收回调函数处理完成后,依次结束以上两个函数及中断函数。

回调函数虽然在关闭中断后,但依然在中断函数里内部。
any012 回答时间:2016-11-24 16:52:01
现在是将HAL_SPI_Receive_IT(&hspi2, (uint8_t *)&spi2RecvBuff[0],1)放在void SPI2_IRQHandler(void)内。
发现其实进中断2次才调用一次回调函数。

spi2RecvNum: 0
spi2RecvBuff[2]: 3a0c
1ms时间到

spi2 recive over.
spi2RecvNum: 3
spi2RecvBuff[3]: 3a0c
spi2RecvBuff[4]: 3a0c
1ms时间到

spi2 recive over.
spi2RecvNum: 5
spi2RecvBuff[5]: 3a0c
spi2RecvBuff[6]: 3a0c
1ms时间到

spi2 recive over.
spi2RecvNum: 7
spi2RecvBuff[7]: 3a0c
spi2RecvBuff[8]: 3a0c
1ms时间到

spi2 recive over.
spi2RecvNum: 9
spi2RecvBuff[9]: 3a0c
spi2RecvBuff[10]: 3a0c
衔胆栖冰 回答时间:2016-11-24 19:00:32
楼主,你自己顶了那么多。我也没时间看那么多。你调用的接收函数原型是HAL_StatusTypeDef HAL_SPI_Receive_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)。这个跟标准库不一样的是,你调用这个函数,就会一直等待接收完Size个字节。你调用这个函数之后,再去while轮询访问接收寄存器当然读不到数据了。

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2

查看全部评分

peter001 回答时间:2016-11-25 00:12:43
帮顶
any012 回答时间:2016-11-25 08:45:20
衔胆栖冰 发表于 2016-11-24 19:00
楼主,你自己顶了那么多。我也没时间看那么多。你调用的接收函数原型是HAL_StatusTypeDef HAL_SPI_Receive_ ...

没有在while(1)里轮询访问接收寄存器,而是在接收完成回调函数里,想再次调用这个函数,结果却不行。现在是放到void SPI2_IRQHandler(void)里了,暂时能用了。但想不明白为什么放到回调函数里却不行,从串口发上来的数看,应该是中断了2次才调用了一次回调函数。可能我设置还是有问题。
zbber 回答时间:2016-11-25 11:38:02
放到SPI2_IRQHandler

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2

查看全部评分

any012 回答时间:2016-11-25 11:48:28
zbber 发表于 2016-11-25 11:38
放到SPI2_IRQHandler

现在确实是这样做的,但好奇,为什么放到回调函数里就出问题?
123下一页

所属标签

相似问题

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