久芯网

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

avatar huahuahnu 提问时间: 2023-08-26 19:46:46 / 未解决
有人用过这个功能吗?按照示例修改配置,结果通信不对

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();
            }



如需获得 STM32G070 等器件的更多信息,请点击链接或 点击此处 联系在线客服!

9个回答
  • avatar huahuahnu
    回答时间: 2023-08-26 20:04:31

    MemDataAlignment 为byte时是正确传输的,看了封装的函数要使用到LDMA_TX或LDMA_RX时MemDataAlignment是为HALFWORD,且传输数据总数为奇数,有没有大神使用过啊?

  • avatar butterflyspring
    回答时间: 2023-08-26 20:23:11

    如果数据宽度选择8位时,格式为字节,这样就是传统字节发送和接收,不存在奇数字节的特殊处理问题。 如果数据宽度小于或等于8位,格式选择halfword 时,这时候位PACKING 模式,如你所说还要另外设置最后的DMA处理方式LDMA_TX/LDMA_RX,这样芯片才知道最后一个是奇数且变回单字节处理。 其实用传统的单字节传输方式,也用了DMA,并不影响多少效率,应该够用了。packing模式没用过,看起来对软件处理上会快一些,但用了DMA就没看出多少优势了。如果有谁用过,可以分享一下它的优势。

  • avatar huahuahnu
    回答时间: 2023-08-26 20:50:28
    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库实现的

  • avatar yr
    回答时间: 2023-08-26 21:12:48
    mumu_hnu 发表于 2021-8-3 18:19
    修改了PSIZE为16位,有这个功能就想验证一下,官方都没有相关的示例,按照手册说明进行了配置修改固定发 ...

    PSIZE=16位的话,MSIZE=?,此时传输次数为多少?乍看起来像是A1没发,直接从A2开始,最后收了个垃圾数据,实际上是这样吗?可以尝试使能dma传输一半的中断,看看传输一半时,收到的第一个数是a1还是a2?

  • avatar huahuahnu
    回答时间: 2023-08-26 21:43:01
    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; } }

  • avatar huahuahnu
    回答时间: 2023-08-26 22:06:49

    已经找到问题了,虽然是奇数,但是DMA传输写到接收buffer时仍然是多写一个字节,所以接收buffer大小要额外多一个字节,否则就越界溢出了

  • avatar butterflyspring
    回答时间: 2023-08-26 22:35:12
    mumu_hnu 发表于 2021-8-4 13:12
    已经找到问题了,虽然是奇数,但是DMA传输写到接收buffer时仍然是多写一个字节,所以接收buffer大小要额外 ...

    我做的结果和你的稍稍不同,我需要将PSIZE 和 MSIZE都设置成16位,这样定义的发送和接收buffer都是11个,数据就都是收全了。可能代码哪里稍有不同吧。

  • avatar huahuahnu
    回答时间: 2023-08-26 23:01:12
    butterflyspring 发表于 2021-8-4 15:12
    我做的结果和你的稍稍不同,我需要将PSIZE 和 MSIZE都设置成16位,这样定义的发送和接收buffer都是11个, ...

    是要把PSIZE和MSIZE都设成16位,我发送11个byte,接收数组buff[11],要定义成buff[12]才可以

  • avatar huahuahnu
    回答时间: 2023-08-26 23:19:31

    观察了MISO上的波形是正确的,正好是11个数据,最终原因是因为定义的接收BUFFER的sram地址不是4字节对齐,刚好是奇数,造成接收数据出错了

会员中心 微信客服
客服
回到顶部