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

SPI从设备DMA方式发送数据,发送到一半后故障,如何清掉DR数据?

[复制链接]
any012 提问时间:2017-7-3 17:52 /
悬赏10ST金币已解决
STM32F103作为SPI从设备向主设备发送数据,用的DMA命令:
HAL_SPI_TransmitReceive_DMA(&hspi2, (uint8_t *) spi2SendDate, (uint8_t *) spi2RecvDate, 0x0a);
主设备和从设备同时启动的话,正常。
如果从设备不断电,主设备重新上电,则从设备出现错误,是在
static void SPI_DMATransmitReceiveCplt(DMA_HandleTypeDef *hdma)
这个函数的这部分里:
if (SPI_WaitOnFlagUntilTimeout(hspi, SPI_FLAG_TXE, RESET,
        SPI_TIMEOUT_VALUE) != HAL_OK)
        {
            printf("spi2 cr1: %08x\r\n", hspi->Instance->CR1);
            printf("spi2 cr2: %08x\r\n", hspi->Instance->CR2);
            printf("spi2 sr: %08x\r\n", hspi->Instance->SR);
            printf("spi2 dr: %08x\r\n", hspi->Instance->DR);
            SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
            HAL_UART_Transmit(&huart1, (uint8_t *) &"txe err\r\n", 0x09,
                    0xFFFF);
        }

printf语句是我后加的,串口接收如下:

txe err
spi dma err
spi2 cr1: 00000a3b
spi2 cr2: 00000003
spi2 sr: 00000000
spi2 dr: 00000000

觉得可能是从设备开启了SPI的DMA接收,接收固定长度。接收过程中,主设备重启了,从设备仍在等待,结果出错?
试着在SPI的错误回调函数里关闭DMA,并重新初始化SPI2,想下次接收时能正确,结果错误依旧。

void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
{
    if (hspi == &hspi2)
    {
        HAL_UART_Transmit(&huart1, &"spi dma err\r\n", 0x0d, 0xFFFF);
        HAL_SPI_DMAStop(&hspi2);
//        HAL_SPI_Init(&hspi2);
        MX_SPI2_Init();
    }
}

最佳答案

查看完整内容

在参考手册中,对循环模式模式的描述是: 当启动了循环模式,数据传输的数目变为 0 时, 将会自动地被恢复成配置通道时设置的初值, DMA 操作将会继续进行。
收藏 1 评论5 发布时间:2017-7-3 17:52

举报

5个回答
无薪税绵 回答时间:2017-7-3 17:52:45
在参考手册中,对循环模式模式的描述是:
当启动了循环模式,数据传输的数目变为 0 时,
将会自动地被恢复成配置通道时设置的初值,
DMA 操作将会继续进行。

评分

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

查看全部评分

any012 回答时间:2017-7-4 17:16:42
DMA中断函数:
HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
该函数里又调用:
hdma->XferCpltCallback(hdma)
对应的函数是:
static void SPI_DMATransmitReceiveCplt(DMA_HandleTypeDef *hdma)
在这个函数里,先判断是否有CRC错误,然后是判断TXE是否为高:
if (SPI_WaitOnFlagUntilTimeout(hspi, SPI_FLAG_TXE, RESET,
        SPI_TIMEOUT_VALUE) != HAL_OK)
然后就卡在这里了。
any012 回答时间:2017-7-4 17:41:48
每次都能进DMA中断,并可调用SPI_DMATransmitReceiveCplt()函数,说明DMA算是完成了转换。
而在SPI_DMATransmitReceiveCplt()这个函数里检测TXE出错,TXE为发送非空,说明还有数据。不知道这个数据从那里来的...
any012 回答时间:2017-7-5 09:17:24
用示波器测量,无论哪种情况,主设备发送的MOSI波形都是正确的。
更改了下主设备发送的频率,原来是0.1秒发送一次,修改为1秒和3秒试了试,问题依旧。
为改为3秒发送一次的话,发送过程所占用的时间,只占这3秒时间的很小的一部分,那么给主设备重新上电时,恰好遇到SPI通讯的几率应该很小。可惜现象是,试了很多次,绝大部分都是错误的情况。
any012 回答时间:2017-7-5 14:29:37
本帖最后由 any012 于 2017-7-5 14:31 编辑

试了在HAL_SPI_TxRxCpltCallback()函数里,重启单片机。重启后倒是能正常接收。

后,又试着修改SPI DMA的配置,由DMA_NORMAL改为DMA_CIRCULAR,结果倒是正常了,给主设备重新上电后,从设备开始接收了2帧数据以后就正常了。
这个函数里,检测到DMA不是循环模式的话,就直接调用HAL_SPI_TxRxCpltCallback(hspi)函数了,略过中间的错误判断了。不知道为何时这样,那么判断又有什么用?

  1. static void SPI_DMATransmitReceiveCplt(DMA_HandleTypeDef *hdma)
  2. {
  3.     __IO uint16_t tmpreg = 0;

  4.     SPI_HandleTypeDef* hspi =
  5.             (SPI_HandleTypeDef*) ((DMA_HandleTypeDef*) hdma)->Parent;

  6.     if ((hdma->Instance->CCR & DMA_CIRCULAR) == 0)
  7.     {
  8. ...
  9.     }
  10.     else
  11.     {
  12.         HAL_SPI_TxRxCpltCallback(hspi);
  13.     }
  14. }
复制代码






所属标签

相似问题

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