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

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管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版