Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在两次传输之间禁用STM32H7上的SPI外围设备?_Stm32_Spi - Fatal编程技术网

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

在两次传输之间禁用STM32H7上的SPI外围设备?,stm32,spi,Stm32,Spi,我还在两块核子STM32H743板之间做SPI实验 我已经在全双工模式下配置了SPI,启用了CRC,SPI频率为25MHz(因此从机可以无问题传输) DSIZE为8位,FIFO阈值为4 在主机端,我发送4个字节,然后等待从机发送5个字节。我知道我可以使用半双工或单工模式,但我想了解全双工模式下的情况 volatile unsigned long *CR1 = (unsigned long *)0x40013000; volatile unsigned long *CR2 = (unsigned

我还在两块核子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\u receiveresponseSelectalDuplex

是否有必要在两次传输之间禁用SPI,或者我在配置中犯了错误


SPE bit的行为在参考手册中不是很清楚。例如,在半双工模式下,必须禁用SPI以改变通信方向,这一点是否写得很清楚。但在fuill双工模式下没有任何内容(或者我错过了)。

此勘误表项目可能与此相关

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

描述

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

解决方法

采用以下措施之一:

•在每次EOT事件后禁用然后启用SPI/I2S

•在EOT事件发生时,在设置CSTART之前至少等待一个SCK循环

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

您的SCK频率是25 MHz,系统时钟可以是400或480MHz,是SCK的16或19倍。当您删除行清除和设置
SPE
时,只有这些行在检测到
EOT

*IFCR = 0xFFFFFFFF;
*CR2 = 5;
*CR1 |= SPI_CR1_CSTART;
当该序列(很可能)占用少于16个时钟周期时,则存在上述问题。看起来有人又在SPI时钟系统做了一件草率的工作。首先,清除和设置
SPE
是推荐的解决方法之一

我只需在开始时设置
TSIZE=9
,然后一次性写入命令和伪字节,在全双工模式下没有任何区别

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

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

非常有用,谢谢!关于你最后的评论,我认为分两步进行传输是有区别的:我的目标是首先发送一个包含CRC的命令,从机可以检查,然后响应,如果CRC错误,可能会使用错误代码。如果设置TSIZE=9,则末尾只有一个CRC。关于我必须在全双工模式下“刷新”4个虚拟字节这一事实的评论很好。对,我忘记了CRC。为了记录,我在3种模式(全双工、半双工和单工)下进行了一些时间测量,结果非常接近,但在全双工模式下速度稍快,尽管如此,我不必写入TX FIFO以在hald双工或单工模式下接收响应。我认为这是因为在切换方向时,外围设备必须进行一些内部重新配置。