您好,我在使用STM32G0B1RE的SPI1作为从设备,数据收发采用DMA方式,通过STM32CubeIDE配置工程,SPI与DMA均配置为Byte字节传输模式。 与主SPI的交互方式如下: 1、SPI-Master--->发送第一条命令---->SPI-Slave 2、SPI-Master判断SPI-Slave返回的第二、第三个字节,如果符合要求,则读取命令的应答(执行步骤3) 3、SPI-Master<---读取第一条命令应答<----SPI-Slave 在配置好工程后,数据能够正常收发,但步骤3返回给SPI-Master的数据的前3个字节总是上次的数据的结尾3个字节。我的实现逻辑是SPI-Slave端通过CS引脚判断数据传输开始与结束,数据传输的长度不定: /** * @brief SPI启动,CS变低时产生EXTI中断,在中断中开启SPI+DMA传输 */ __inline void bsp_spi_start(void) { uint32_t length; // length = nss_low(); // SPI DMA 通讯使能 HAL_SPI_TransmitReceive_DMA(&hspi2, txbuffer, rxbuffer, TTU_RECV_BUFF_SIZE); // 软件设置SSI hspi2.Instance->CR1 &= 0xFEFF; } /** * @brief SPI停止,在CS拉高时产生EXTI中断,停止SPI+DMA的数据传输 */ __inline void bsp_spi_stop(void) { // 软件设置SSI hspi2.Instance->CR1 |= 0x0100; // 停止SPI DMA通讯 HAL_SPI_DMAStop(&hspi2); // 获取SPI未传输数据长度,并处理为已传输长度 nss_high(hspi2.hdmarx->Instance->CNDTR); } 问题现象: 上图为逻辑分析仪监控的数据,通道4的高电平为上面的bsp_spi_start()函数的执行时间。通过MISO引脚可以看到前3个字节为0xF1,这3个字节实际上为上一个SPI通讯的末尾3字节,后面的"0x01 0x03"为这一次的数据的开始,通过监控txbuffer,数据是正确的。 求教,如何解决该问题? 思考:怀疑是不是手册中,34.5.9 数据发送与接收过程,图366 主器件全双工通讯 后面说明的如果使用DMA,由DMA处理的TX、RX帧的数量设置为3的原因?未看到相关清空数据等操作 |
STM32 SPI从机用DMA方式实现全双工,数据传输过程中出错。
STM32G0B1adc+dma采样数据错位
STM32H7打开DCache后,串口1DMA接受数据位空
关于VN9D5D20F芯片的SPI 的信号脚SDO设计疑问
与HAL_ADC_Start_DMA相关的一个十分怪异的问题
双重ADC的DMA请求
L9663驱动开发
STM32的H5/U5系列处理器内置运放支持负压运算吗?比如输入-1V,放大倍数为2时输出-2V
stm32G030C8T6 官方例程库
PWM+DMA分多次发送缺点明显,会造成脉冲不连续,有解决的办法吗。
1、SPI-Master--->发送第一条命令---->SPI-Slave
2、SPI-Master判断SPI-Slave返回的第二、第三个字节,如果符合要求,则读取命令的应答(执行步骤3)
3、SPI-Master<---读取第一条命令应答<----SPI-Slave
在配置好工程后,数据能够正常收发,但步骤3返回给SPI-Master的数据的前3个字节总是上次的数据的结尾3个字节。我的实现逻辑是SPI-Slave端通过CS引脚判断数据传输开始与结束,数据传输的长度不定:
/**
* @brief SPI启动,CS变低时产生EXTI中断,在中断中开启SPI+DMA传输
*/
__inline void bsp_spi_start(void)
{
uint32_t length;
//
length = nss_low();
// SPI DMA 通讯使能
HAL_SPI_TransmitReceive_DMA(&hspi2, txbuffer, rxbuffer, TTU_RECV_BUFF_SIZE);
// 软件设置SSI
hspi2.Instance->CR1 &= 0xFEFF;
}
/**
* @brief SPI停止,在CS拉高时产生EXTI中断,停止SPI+DMA的数据传输
*/
__inline void bsp_spi_stop(void)
{
// 软件设置SSI
hspi2.Instance->CR1 |= 0x0100;
// 停止SPI DMA通讯
HAL_SPI_DMAStop(&hspi2);
// 获取SPI未传输数据长度,并处理为已传输长度
nss_high(hspi2.hdmarx->Instance->CNDTR);
}
问题:
逻辑分析仪监控
上图为逻辑分析仪监控的数据,通道4的高电平为上面的bsp_spi_start()函数的执行时间。通过MISO引脚可以看到前3个字节为0xF1,这3个字节实际上为上一个SPI通讯的末尾3字节,后面的"0x01 0x03"为这一次的数据的开始,通过监控txbuffer,数据是正确的。
求教,如何解决该问题?
思考:怀疑是不是手册中,34.5.9 数据发送与接收过程,图366 主器件全双工通讯 后面说明的如果使用DMA,由DMA处理的TX、RX帧的数量设置为3的原因?未看到相关清空数据等操作
第一次发,问题发评论区了,没找到怎么删除...
1.2 根据手册,1034页的“关闭SPI的步骤”,在关闭SPI时需要确保TXFIFO/RXFIFO的数据为空(通过SPI状态寄存器FTLVL和FRLVL两个寄存器位判断),这样在再次启动SPI时,才不会影响下一次数据传输,而实际在操作时,由于我在数据未接收到TTU_RECV_BUFF_SIZE长度,就调用HAL_SPI_DMAStop()函数关闭SPI-DMA操作,在该函数中调用HAL_DMA_Abort(),该函数仅检查DMA的BSY状态,未检查FTLVL和FRLVL,在未处于BSY状态时关闭了DMA和SPI,这样,导致TXFIFO中有数据未传输。
1.3 解决办法
暂时采用控制外设RCC_SPBRSTR1寄存器以软件复位SPI2的方式来初始化SPI寄存器,清除FIFO的处理,但复位后,需要重新配置SPI及DMA。
MX_SPI2_Init();
就是说我在CS已经拉高之后,还需要再次读取SPI->DR寄存器,去清除TXFIFO的数据吗?然后再调用HAL_SPI_DMAStop()关闭SPI?我去试一下
您好,我试了一下,没有解决问题,我想是因为现在调试的是从SPI,在CS被主SPI拉高后,操作SPI->DR寄存器已经没有效果,读取出的数据也是RxFIFO中未被清除的数据。
现在已经通过RCC_APBRSTR1寄存器的SPI2RST位复位SPI解决,但感觉这个方法比较差。
谢谢帮助。