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

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管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版