STM32H7 SPI通信:FIFO管理问题
Posted
技术标签:
【中文标题】STM32H7 SPI通信:FIFO管理问题【英文标题】:STM32H7 SPI communication: FIFO management problem 【发布时间】:2020-09-27 07:19:53 【问题描述】:我已经在 SPI 设置上苦苦挣扎了一段时间。
设置如下:
SPI Slave 是单工模式下的 Nucleo STM32H743,最大时钟(sysclk 400MHz,hclck 200Mhz,APB 时钟 100MHz) SPI 主控是另一个相同的 Nucleo,处于单工模式,时钟除以 2:sysclk 200MHz 等...且 spi_ker_clk = 100MHz 预分频器为 16 的 SPI 主机,即。时钟 SPI 约为 6MHz。启用 CRC。数据帧 8 位。 FIFO 阈值 4 字节 SPI 从机:启用 CRC,8 位。 FIFO 阈值 4 字节没有从机选择信号来控制从机。
这是主人的代码。一切都在轮询中完成,我增加了一些延迟,让奴隶有时间工作。以下函数在循环中被调用,Master 没有做任何其他事情(在我用于调试的这个简化版本中):
uint32_t SPI_EnvoiCommandeTest(void)
uint32_t resp;
uint8_t statut;
SPI1->CFG2 |= SPI_CFG2_COMM_0;
SPI1->CFG2 &= ~SPI_CFG2_COMM_1;
SPI1->CR2 = 4;
SPI1->CR1 |= SPI_CR1_SPE;
SPI1->CR1 |= SPI_CR1_CSTART;
SPI1->TXDR = 0x12345678;
while ( (SPI1->SR & SPI_SR_EOT) == 0 );
if ( (SPI1->SR & SPI_SR_ERR_MASK) != 0 )
return ( SPI1->SR & SPI_SR_ERR_MASK);
SPI1->IFCR = 0xFFFFFFFF;
SPI1->CR1 &= ~SPI_CR1_SPE;
Delay(1000);
SPI1->CFG2 |= SPI_CFG2_COMM_1;
SPI1->CFG2 &= ~SPI_CFG2_COMM_0;
SPI1->CR2 = 5;
SPI1->CR1 |= SPI_CR1_SPE;
SPI1->CR1 |= SPI_CR1_CSTART;
while ( (SPI1->SR & SPI_SR_EOT) == 0 );
resp = SPI1->RXDR;
statut = *((__IO octet *)&(SPI1->RXDR));
if ( resp != 0x9ABCDEFF)
while(1);
if ( statut != 0x77)
while(1);
while ( (SPI1->SR & SPI_SR_EOT) == 0 );
if ( (SPI1->SR & SPI_SR_ERR_MASK) != 0 )
return ( SPI1->SR & SPI_SR_ERR_MASK);
SPI1->IFCR = 0xFFFFFFFF;
SPI1->CR1 &= ~SPI_CR1_SPE;
Delay(1000);
return 0;
对于从设备,接收由中断处理程序完成。主线程正在等待设置一个标志(由SPI_StopReception()
设置)并发送 5 个字节的应答。
static void SPI_GenericHandler(SpiId_e SpiId)
SPI_TypeDef *Spi = SpiMgt[SpiId].SpiInstance;
uint32_t trigger = Spi->IER & Spi->SR;
uint32_t cmd;
uint8_t stat;
if (trigger & SPI_SR_RXP)
cmd = Spi->RXDR;
if (cmd != 0x12345678)
while(1);
while((Spi->SR & SPI_SR_EOT) == 0);
if (Spi->SR & SPI_SR_CRCE)
while(1);
SPI_StopReception(SpiId);
(...)
我的问题如下。
通信正常工作数十万次,然后在从站端失败:我没有从 SPI FIFO 读取字节 78 56 34 12,而是读取例如 34 12 00 00 或 56 34 12 00。
乍一看,人们会说这只是 Slave 太慢并且丢失了一些字节,但奇怪的是:
我收到一个 RXP 中断,这意味着从设备在 4 个字节期间正确检测到 SPI 时钟并已对 4 个字节进行采样。 没有 CRC 错误,这意味着从站接收到了正确的位。例如,当我从 FIFO 中读取 56 34 12 00 时,RXCRC 为 0x08,这是完整帧 78 56 34 12 的 CRC好像是读取FIFO有问题。
我使用了逻辑分析仪,没有发现任何电气问题。
在接收错误期间(更准确地说,我在 SPI RXP 中断处理程序中中断)期间在从机端注册值如下。在这种情况下,我读到 34 12 00 00:
CR1=1 (SPE) CR2= 4 (TSIZE) CFG1:MBR 0x07,CRCEN,UDRCFG=2,FTHVL=3,DSIZE=7 CFG2:SSM=1,COMM=2 IER=1(RXPIE) SR=0x0001300A 即。 CTSIZE=1(奇怪但参考手册说“当总线上正在进行流量时,值不太可靠”),RXPLVL=1(??),EOT=1(预期),TXP=1(预期) RXCRC=0x08(预期为完整帧)。值得一提的是,调试器 (Keil) 没有正确读取寄存器,我在代码中读取了它。CTSIZE 和 RXPLVL 的值并不是真正一致的(至少我不明白它们):因为 FTHVL=3 (4-data) 和 TSIZE=4 (在主端相同) ,当我收到 RXP 事件时,我应该至少收到 4 个字节。我看不出 CTSIZE 怎么可能是 1 ,也看不出为什么 FIFO 中还会剩下另一个字节(RXPLVL=1)。
有什么想法或建议吗?
【问题讨论】:
比赛条件?服务第一个时,您会受到第二次中断吗?嘿,对于 >1000 的评分,你能用<!-- language: lang-c -->
之类的东西标记你的代码吗?
没有竞争条件。我对轮询中的两个代码进行了相同的测试,并且没有启用其他中断。
不明白您关于评分和标记代码的评论。
【参考方案1】:
我建议将系统时钟速度降低到 250 MHz 以下并进行测试。我在开发过程中遇到了一些 SPI 通信问题,与此速度直接相关。 我相信微机中有一个错误,当速度高于 250 MHz 时它会丢失 SPI 数据包。我的微控制器是 H750VBT6。我希望这会有所帮助。 最好的问候,恩里克·巴索。
【讨论】:
这不是问题。我在 480MHz 上运行 H4 并使用 SPI 没有任何问题。这是您的代码中的问题。 我在 F103cbt6 上运行了我的代码,一切正常。在H7勘误表2.14.2项中,表示频率很高时可以停止传输。以上是关于STM32H7 SPI通信:FIFO管理问题的主要内容,如果未能解决你的问题,请参考以下文章
STM32H7教程第93章 STM32H7的SPI总线应用之驱动ADS1256(8通道24bit ADC, 增益可编程)
STM32H7教程第93章 STM32H7的SPI总线应用之驱动ADS1256(8通道24bit ADC, 增益可编程)
STM32H7教程第75章 STM32H7的SPI总线应用之驱动DAC8501(双路输出,16bit分辨率,0-5V)
STM32H7教程第75章 STM32H7的SPI总线应用之驱动DAC8501(双路输出,16bit分辨率,0-5V)
BSP视频教程STM32H7视频教程第10期:STM32H7的GPIO专题,非阻塞式驱动编程思想,按键FIFO,蜂鸣器驱动的新式玩法(2022-03-23)