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

STM32G070的SPI DMA配置传输数据总数为奇数的功能怎么实现

[复制链接]
huahuahnu 提问时间:2021-8-2 14:31 / 未解决
有人用过这个功能吗?按照示例修改配置,结果通信不对

spi配置

hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 7;
  hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }

DMA配置

hdma_spi1_tx.Instance = DMA1_Channel1;
    hdma_spi1_tx.Init.Request = DMA_REQUEST_SPI1_TX;
    hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi1_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_
HALFWORD;
    hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;//DMA_MDATAALIGN_BYTE;//
    hdma_spi1_tx.Init.Mode = DMA_NORMAL;
    hdma_spi1_tx.Init.Priority = DMA_PRIORITY_LOW;
    if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(hspi,hdmatx,hdma_spi1_tx);

    /* SPI1_RX Init */
    hdma_spi1_rx.Instance = DMA1_Channel2;
    hdma_spi1_rx.Init.Request = DMA_REQUEST_SPI1_RX;
    hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_
HALFWORD;
    hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;//DMA_MDATAALIGN_BYTE;//
    hdma_spi1_rx.Init.Mode = DMA_NORMAL;
    hdma_spi1_rx.Init.Priority = DMA_PRIORITY_HIGH;
    if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(hspi,hdmarx,hdma_spi1_rx);

主函数调用:

if (HAL_SPI_TransmitReceive_DMA(&hspi1, (uint8_t *)spimater_send_array, (uint8_t *)spimater_receive_array, 11) != HAL_OK)
            {
                /* Transfer error in transmission process */
                Error_Handler();
            }


无标题.png
收藏 评论9 发布时间:2021-8-2 14:31

举报

9个回答
huahuahnu 回答时间:2021-8-3 14:52:34
MemDataAlignment 为byte时是正确传输的,看了封装的函数要使用到LDMA_TX或LDMA_RX时MemDataAlignment是为HALFWORD,且传输数据总数为奇数,有没有大神使用过啊?
butterflyspring 回答时间:2021-8-3 15:03:56
如果数据宽度选择8位时,格式为字节,这样就是传统字节发送和接收,不存在奇数字节的特殊处理问题。
如果数据宽度小于或等于8位,格式选择halfword 时,这时候位PACKING 模式,如你所说还要另外设置最后的DMA处理方式LDMA_TX/LDMA_RX,这样芯片才知道最后一个是奇数且变回单字节处理。
其实用传统的单字节传输方式,也用了DMA,并不影响多少效率,应该够用了。packing模式没用过,看起来对软件处理上会快一些,但用了DMA就没看出多少优势了。如果有谁用过,可以分享一下它的优势。
STM32G0 PACKING DATA SPI.PNG
huahuahnu 回答时间:2021-8-3 18:19:24
butterflyspring 发表于 2021-8-3 15:03
如果数据宽度选择8位时,格式为字节,这样就是传统字节发送和接收,不存在奇数字节的特殊处理问题。
如果数 ...

修改了PSIZE为16位,有这个功能就想验证一下,官方都没有相关的示例,按照手册说明进行了配置修改固定发送0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA,0xAB

接收数据0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA,0xAB,0xA8
出错了也不知道什么原因,毕竟是HAL库实现的
yr 回答时间:2021-8-4 10:54:44
mumu_hnu 发表于 2021-8-3 18:19
修改了PSIZE为16位,有这个功能就想验证一下,官方都没有相关的示例,按照手册说明进行了配置修改固定发 ...

PSIZE=16位的话,MSIZE=?,此时传输次数为多少?乍看起来像是A1没发,直接从A2开始,最后收了个垃圾数据,实际上是这样吗?可以尝试使能dma传输一半的中断,看看传输一半时,收到的第一个数是a1还是a2?
huahuahnu 回答时间:2021-8-4 11:37:55
yr 发表于 2021-8-4 10:54
PSIZE=16位的话,MSIZE=?,此时传输次数为多少?乍看起来像是A1没发,直接从A2开始,最后收了个垃圾数据 ...

MSIZE也是配置16位,实际传输个数是函数里面已经封装好的,看代码是(个数/2)+1

if (hspi->hdmatx->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD)
    {
      if ((hspi->TxXferSize & 0x1U) == 0x0U)
      {
        CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMATX);
        hspi->TxXferCount = hspi->TxXferCount >> 1U;
      }
      else
      {
        SET_BIT(hspi->Instance->CR2, SPI_CR2_LDMATX);
        hspi->TxXferCount = (hspi->TxXferCount >> 1U) + 1U;
      }
    }

    if (hspi->hdmarx->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD)
    {
      /* Set RX Fifo threshold according the reception data length: 16bit */
      CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);

      if ((hspi->RxXferCount & 0x1U) == 0x0U)
      {
        CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMARX);
        hspi->RxXferCount = hspi->RxXferCount >> 1U;
      }
      else
      {
        SET_BIT(hspi->Instance->CR2, SPI_CR2_LDMARX);
        hspi->RxXferCount = (hspi->RxXferCount >> 1U) + 1U;
      }
    }

huahuahnu 回答时间:2021-8-4 13:12:00
已经找到问题了,虽然是奇数,但是DMA传输写到接收buffer时仍然是多写一个字节,所以接收buffer大小要额外多一个字节,否则就越界溢出了
butterflyspring 回答时间:2021-8-4 15:12:13
mumu_hnu 发表于 2021-8-4 13:12
已经找到问题了,虽然是奇数,但是DMA传输写到接收buffer时仍然是多写一个字节,所以接收buffer大小要额外 ...

我做的结果和你的稍稍不同,我需要将PSIZE 和 MSIZE都设置成16位,这样定义的发送和接收buffer都是11个,数据就都是收全了。可能代码哪里稍有不同吧。
STM32G0 PACKING DATA SPI 2.PNG
huahuahnu 回答时间:2021-8-4 16:37:26
butterflyspring 发表于 2021-8-4 15:12
我做的结果和你的稍稍不同,我需要将PSIZE 和 MSIZE都设置成16位,这样定义的发送和接收buffer都是11个, ...

是要把PSIZE和MSIZE都设成16位,我发送11个byte,接收数组buff[11],要定义成buff[12]才可以
huahuahnu 回答时间:2021-8-6 09:15:54
观察了MISO上的波形是正确的,正好是11个数据,最终原因是因为定义的接收BUFFER的sram地址不是4字节对齐,刚好是奇数,造成接收数据出错了
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版