zhiyaormb 2024-03-26 14:21 采纳率: 25%
浏览 92
已结题

STM32F4,HAL库SPI接收出问题

用了3块ADC芯片,均采用SPI口Receive Only Master模式进行读操作
其中SPI1的初始化部分(另外两个相同):

  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES_RXONLY;
  hspi1.Init.DataSize = SPI_DATASIZE_16BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
  hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }

    __HAL_RCC_SPI1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**SPI1 GPIO Configuration
    PA5     ------> SPI1_SCK
    PA6     ------> SPI1_MISO
    */
    GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* SPI1 interrupt Init */
    HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(SPI1_IRQn);

然后通过HAL_SPI_Receive_IT读数据。

img


用逻辑分析仪就发现了这样的波形:

信号1:ADC的convst指令,这个指令是在SPI的接收完成回调函数HAL_SPI_RxCpltCallback里面操作的,这个时间点显然接收还没完成,居然进了接收回调。
信号2:SPI的时钟,注意,这个结尾部分,短暂的空闲时间居然被拉低了。
信号3:ADC片选,这个是软件控制的,低有效。
信号4:ADC转换的busy信号,高有效。
现在的问题是:
1 接收数据未完成的时候居然会提前进入接收callback;
2 时钟在接收完成之后短暂被拉低。
由于这两个问题,导致读取数据的错位

  • 写回答

19条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-03-26 14:29
    关注
    获得0.60元问题酬金

    引自免费微信小程序:皆我百晓生

    针对您遇到的STM32F4 HAL库SPI接收问题,我们逐一分析并提出解决方案:

    1. 提前进入接收回调: 在HAL_SPI_Receive_IT中触发中断后,提前进入接收完成回调函数HAL_SPI_RxCpltCallback可能是由于SPI中断配置不当或SPI传输过程中存在异常。确保在调用HAL_SPI_TransmitReceive_ITHAL_SPI_Receive_IT之前正确清除中断标志,并且在回调函数内部处理好数据的同时重新启动接收(如果需要连续接收)。

      您可以在回调函数开始处加入对SPI状态的检查,确保数据接收完毕后再进行后续操作,例如:

      void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
      {
          // 确保数据接收完成
          if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)) == RESET)
          {
              // 此处执行错误处理逻辑,比如打印错误信息等
              return;
          }
      
          // ...此处进行正常的数据处理...
      
          // 如果需要连续接收,则重新启动接收
          HAL_SPI_Receive_IT(&hspi1, rxBuffer, bufferLength);
      }
      
    2. SPI时钟在接收完成之后短暂被拉低: 这种现象可能与SPI总线管理不善有关,特别是在数据接收完成后没有及时停止SPI时钟输出。您可以通过调整SPI的NSS(片选)信号来解决这个问题,确保在每次数据接收完成后及时释放从设备(ADC),从而停止SPI时钟输出。

      修改您的主函数或相关处理函数,在数据接收完成后立即设置NSS为高电平(对于低有效的片选信号):

      void DataReceiveComplete()
      {
          // 处理接收到的数据...
      
          // 结束SPI事务,取消片选
          HAL_GPIO_WritePin(NSS_GPIO_Port, NSS_Pin, GPIO_PIN_SET);
      }
      

    同时,也请检查硬件连接和SPI外设配置,确保它们符合ADC芯片的数据手册要求,尤其是时钟极性和相位以及数据帧格式。另外,如果SPI控制器支持,可以尝试启用DMA接收模式替代中断接收,这样能更稳定地接收数据,减少中断处理过程中的干扰。

    综上所述,上述建议旨在帮助您定位并解决SPI通信中的问题。请根据实际情况对代码进行相应调整,并仔细检查SPI及ADC的工作模式、时序要求等关键参数是否匹配。

    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 4月3日
  • 修改了问题 3月26日
  • 赞助了问题酬金15元 3月26日
  • 修改了问题 3月26日
  • 展开全部

悬赏问题

  • ¥15 代码在keil5里变成了这样怎么办啊,文件图像也变了,
  • ¥20 Ue4.26打包win64bit报错,如何解决?(语言-c++)
  • ¥15 clousx6整点报时指令怎么写
  • ¥30 远程帮我安装软件及库文件
  • ¥15 关于#自动化#的问题:如何通过电脑控制多相机同步拍照或摄影(相机或者摄影模组数量大于60),并将所有采集的照片或视频以一定编码规则存放至规定电脑文件夹内
  • ¥20 深信服vpn-2050这台设备如何配置才能成功联网?
  • ¥15 Arduino的wifi连接,如何关闭低功耗模式?
  • ¥15 Android studio 无法定位adb是什么问题?
  • ¥15 C#连接不上服务器,
  • ¥15 angular项目错误