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

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个回答
涛哥2035 回答时间: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扩展软件包
关注我们
st-img 微信公众号
st-img 手机版