有人用过这个功能吗?按照示例修改配置,结果通信不对
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();
}
|
如果数据宽度小于或等于8位,格式选择halfword 时,这时候位PACKING 模式,如你所说还要另外设置最后的DMA处理方式LDMA_TX/LDMA_RX,这样芯片才知道最后一个是奇数且变回单字节处理。
其实用传统的单字节传输方式,也用了DMA,并不影响多少效率,应该够用了。packing模式没用过,看起来对软件处理上会快一些,但用了DMA就没看出多少优势了。如果有谁用过,可以分享一下它的优势。
修改了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库实现的
PSIZE=16位的话,MSIZE=?,此时传输次数为多少?乍看起来像是A1没发,直接从A2开始,最后收了个垃圾数据,实际上是这样吗?可以尝试使能dma传输一半的中断,看看传输一半时,收到的第一个数是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;
}
}
我做的结果和你的稍稍不同,我需要将PSIZE 和 MSIZE都设置成16位,这样定义的发送和接收buffer都是11个,数据就都是收全了。可能代码哪里稍有不同吧。
是要把PSIZE和MSIZE都设成16位,我发送11个byte,接收数组buff[11],要定义成buff[12]才可以