代码之家  ›  专栏  ›  技术社区  ›  Guillaume Petitjean

在两个传输之间禁用STM32H7上的SPI外围设备?

  •  0
  • Guillaume Petitjean  · 技术社区  · 6 年前

    我还在做两个nuclear STM32H743板之间的SPI实验。

    我在全双工模式下配置了SPI,启用了CRC,SPI频率为25MHz(这样从机可以毫无问题地传输)。

    DSIZE为8位,FIFO阈值为4。

    在主机端,我发送4个字节,然后等待从服务器发送5个字节。我知道我可以使用半双工或单工模式,但我想了解全双工模式下的情况。

    volatile unsigned long *CR1 = (unsigned long *)0x40013000;
    volatile unsigned long *CR2 = (unsigned long *)0x40013004;
    volatile unsigned long *TXDR = (unsigned long *)0x40013020;
    volatile unsigned long *RXDR = (unsigned long *)0x40013030;
    volatile unsigned long *SR = (unsigned long *)0x40013014;
    volatile unsigned long *IFCR = (unsigned long *)0x40013018;
    volatile unsigned long *TXCRC = (unsigned long *)0x40013044;
    volatile unsigned long *RXCRC = (unsigned long *)0x40013048;
    volatile unsigned long *CFG2 = (unsigned long *)0x4001300C;
    
    unsigned long SPI_TransmitCommandFullDuplex(uint32_t Data)
    {
        // size of transfer (TSIZE)
        *CR2 = 4;
    
        /* Enable SPI peripheral */
        *CR1 |= SPI_CR1_SPE;
    
        /* Master transfer start */
        *CR1 |= SPI_CR1_CSTART;
    
        *TXDR = Data;
    
        while ( ((*SR) & SPI_FLAG_EOT)  == 0 );
    
        // clear flags
        *IFCR = 0xFFFFFFFF;
    
        // disable SPI
        *CR1 &= ~SPI_CR1_SPE;
    
        return 0;
    }
    
    void SPI_ReceiveResponseFullDuplex(uint8_t *pData)
    {
        unsigned long temp;
    
        // size of transfer (TSIZE)
        *CR2 = 5;
    
        /* Enable SPI peripheral */
        *CR1 |= SPI_CR1_SPE;
    
        /* Master transfer start */
        *CR1 |= SPI_CR1_CSTART;
    
        *TXDR = 0;
        *((volatile uint8_t *)TXDR) = 0;
    
        while ( ((*SR) & SPI_FLAG_EOT)  == 0 );
    
        *((uint32_t *)pData) = *RXDR;
        *((uint8_t *)(pData+4)) = *((volatile uint8_t *)RXDR);
    
        // clear flags
        *IFCR = 0xFFFFFFFF;
    
        // disable SPI
        *CR1 &= ~SPI_CR1_SPE;
    
        return temp;
    }
    

    这两个函数都是在 main

    然后我试图移除两个步骤之间的SPI禁用(即,我不清除并再次设置位SPE),结果我陷入了函数中 SPI_ReceiveResponseFullDuplex while .

    SPE位的行为在参考手册中不是很清楚。例如,在半双工模式下,必须禁用SPI才能改变通信方向。但是在fuill双工模式下什么都没有(或者我错过了)。

    0 回复  |  直到 6 年前
        1
  •  1
  •   Community Mohan Dere    6 年前

    主数据传输在系统时钟处的暂停比SCK快得多

    由于系统时钟(spi_pclk)远快于SCK(spi_ker_ck除以一个预分频器),spi/I2S主数据传输在EOT事件(EOT flag raise)发出上一次传输结束的信号后,在一个SCK周期内设置CSTART位时,spi/I2S主数据传输会暂停。

    采取下列措施之一:

    每次EOT事件后,禁用然后启用SPI/I2S。

    通过将“传输大小”设置为“未定义”(TSIZE=0),防止发生EOT事件 并通过TXFIFO写操作专门触发传输。

    SPE ,只有这些线在检测后仍然有效 EOT

    *IFCR = 0xFFFFFFFF;
    *CR2 = 5;
    *CR1 |= SPI_CR1_CSTART;
    

    是建议的解决方法之一。

    我就准备好了 TSIZE=9

    请记住,在全双工模式下,接收到另外4个字节,在得到真正的答案之前必须读取并丢弃这些字节。你的原始代码没有问题,因为清除 丢弃仍在接收FIFO中的数据,但如果修改后的代码起作用,它将变为FIFO,例如在启用之前还有一些延迟 CSTART