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

SPI DMA接收数据产生偏移。

[复制链接]
any012 提问时间:2017-5-8 11:46 /
悬赏10ST金币已解决
本帖最后由 any012 于 2017-5-8 16:15 编辑

PC6上升沿的话,开启SPI DMA接收函数,接收9个16位数据,PC6下降沿的话,调用DMA关闭函数。

  1. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
  2. {

  3.     if (HAL_GPIO_ReadPin(EN_3V3_GPIO_Port, EN_3V3_Pin) == GPIO_PIN_SET)
  4.         HAL_SPI_Receive_DMA(&hspi2, (uint8_t *) spi2RecvDate, 0x09);
  5.     else
  6.     {
  7.         HAL_SPI_DMAStop(&hspi2);
  8.         HAL_GPIO_TogglePin(ERR_GPIO_Port, ERR_Pin);
  9.     }

  10. }
复制代码


利用spi的DMA接收:
接收到正确的数据是: Spi2 DMA recived OK. 3a08, 010a, 0200, 01ff, 03ff, 07ff, 0fff, 5d71, 0000
接收到错误的数据是: Spi2 DMA recived OK. 03a0, 8010, a020, 001f, f03f, f07f, f0ff, f5d7, 1000

接收错误的原因,可能是我用表笔触碰sclk引脚产生了波形,结果接收的数据偏了...
但一旦出错,以后接收的数据都是错的。
可是我每次都是重新调用DMA接收函数啊。


最佳答案

查看完整内容

HAL库的串口接收发送函数都有类似问题,不要多字节发送和接收。应该改成1字节的发送接收,再封装成多字节函数
收藏 1 评论5 发布时间:2017-5-8 11:46

举报

5个回答
whtt 回答时间:2017-5-8 11:46:49
HAL库的串口接收发送函数都有类似问题,不要多字节发送和接收。应该改成1字节的发送接收,再封装成多字节函数
any012 回答时间:2017-5-8 16:13:42
本帖最后由 any012 于 2017-5-8 16:17 编辑
whtt 发表于 2017-5-8 15:13
HAL库的串口接收发送函数都有类似问题,不要多字节发送和接收。应该改成1字节的发送接收,再封装成多字节函 ...

感谢回复。
我用的是SPI,但无论SPI还是串口,如果单字节接受的话,那和中断就没区别了吧?那就无法发挥DMA的优势了。

还有,我觉得如果是因为干扰引起了多余的数据接收,那么下次调用DMA接收函数时,应该是重新设置了接收地址吧,不应该一直保持错误数据的。但结果却是,一旦出错,以后就一直错...
any012 回答时间:2017-5-9 11:41:11
现在的判断,可能是表笔碰触SCLK引脚,在该引脚上引起了电压变化,造成了多余的数据接收,使其他有效的数据接收向后移了。

主设备现在是1秒发一次数据,在发送前有个片选信号先发送出去的。
我做的这个板子,作为从设备,接收到片选信号后,才调用的DMA接收函数。按说,即使上次接收错误,这次是重新开始DMA接收,应该也会重新配置DMA,但结果也预期的不一样。
any012 回答时间:2017-5-18 13:49:16
DMA由NORMAL模式改成CIRCULAR模式就没事了,但还没搞清楚具体的原因。

  1. static void SPI_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
  2. {
  3.     __IO uint16_t tmpreg = 0;
  4.     SPI_HandleTypeDef* hspi =
  5.     (SPI_HandleTypeDef*) ((DMA_HandleTypeDef*) hdma)->Parent;

  6.     /* DMA Normal mode */
  7.     if ((hdma->Instance->CCR & DMA_CIRCULAR) == 0)
  8.     {
  9.         /* Disable Rx DMA Request */
  10.         CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN);

  11.         /* Disable Tx DMA Request (done by default to handle the case Master RX direction 2 lines) */
  12.         CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN);

  13.         /* CRC Calculation handling */
  14.         if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
  15.         {
  16.             /* Wait until RXNE flag is set (CRC ready) */
  17.             if (SPI_WaitOnFlagUntilTimeout(hspi, SPI_FLAG_RXNE, RESET,
  18.                             SPI_TIMEOUT_VALUE) != HAL_OK)
  19.             {
  20.                 SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
  21.             }

  22.             /* Read CRC */
  23.             tmpreg = hspi->Instance->DR;
  24.             UNUSED(tmpreg);

  25.             /* Wait until RXNE flag is reset */
  26.             if (SPI_WaitOnFlagUntilTimeout(hspi, SPI_FLAG_RXNE, SET,
  27.                             SPI_TIMEOUT_VALUE) != HAL_OK)
  28.             {
  29.                 SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
  30.             }

  31.             /* Check if CRC error occurred */
  32.             if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET)
  33.             {
  34.                 /* Check if CRC error is valid or not (workaround to be applied or not) */
  35.                 if (SPI_ISCRCErrorValid(hspi) == SPI_VALID_CRC_ERROR)
  36.                 {
  37.                     SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);

  38.                     /* Reset CRC Calculation */
  39.                     SPI_RESET_CRC(hspi);
  40.                 }
  41.                 __HAL_SPI_CLEAR_CRCERRFLAG(hspi);
  42.             }
  43.         }

  44.         if ((hspi->Init.Mode == SPI_MODE_MASTER)
  45.                 && ((hspi->Init.Direction == SPI_DIRECTION_1LINE)
  46.                         || (hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
  47.         {
  48.             /* Disable SPI peripheral */
  49.             __HAL_SPI_DISABLE(hspi);
  50.         }

  51.         hspi->RxXferCount = 0;
  52.         hspi->State = HAL_SPI_STATE_READY;

  53.         /* Check if Errors has been detected during transfer */
  54.         if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
  55.         {
  56.             HAL_SPI_ErrorCallback(hspi);
  57.         }
  58.         else
  59.         {
  60.             HAL_SPI_RxCpltCallback(hspi);
  61.         }
  62.     }
  63.     else
  64.     {
  65.         HAL_SPI_RxCpltCallback(hspi);
  66.     }
  67. }
复制代码
any012 回答时间:2017-5-18 14:28:32
额,不是没事了,还是有问题的。
用万用表笔反复碰触SCLK引脚,结果接收的数据还是发生了位移,且位移会一直保持。

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版