在从模式下,STM32072RB不通过SPI接收/发送数据

时间:2017-06-21 13:04:38

标签: stm32 spi

我正在使用uC在从机模式下通过SPI2接收和传输数据,具有以下配置:

CR1 = 0x0078,CR2 = 0x0700,AFRH = 0x55353500,MODER = 0xa2a0556a

APB1ENR也已正确配置。

当前程序只检查RXNE标志,从DR读取接收的数据并向DR发送随机值。

接收数据时的状态寄存器具有以下值:SR = 0x1403 主机正确发送数据并检查从机引脚上的信号(两侧的时钟相位和极性相同,在通过MOSI发送SCK和数据之前NSS信号被清除)。我甚至将引脚配置为输入,我知道我可以读取主机可以发送的任何数字信号。使用当前配置,从设备似乎收到了一些东西,因为当主设备发送数据时RXNE被设置但读取值始终为0x00。我尝试了不同的配置(软件/硬件NSS,不同的数据大小......)但我总是得到0x00。此外,读取DR后发送的随机值不会发送到输出。这是我当前的函数,它被连续调用:

unsigned char spi_rx_slave(unsigned char spiPort, unsigned char *receiveBuffer)
{
uint8_t temp;
static unsigned long sr;
if (!spi_isOpen(spiPort))
{
sendDebug("%s() Error: spiPort not in use!\r\n",__func__);
return false;
}
if (spiDescriptor[spiPort]->powerdown == true)
{
sendDebug("%s() Error: spiPort in powerdown!\r\n",__func__);
return false;
}
/* wait till spi is not busy anymore */
while((spiDescriptor[spiPort]->spiBase->SR) & SPI_SR_BSY)
{
sendDebug("SPI is busy(1)\r\n");
vTaskDelay(2);
}
sendDebug("CR1 = 0x%04x, ", spiDescriptor[spiPort]->spiBase->CR1);
sendDebug("CR2 = 0x%04x, ", spiDescriptor[spiPort]->spiBase->CR2);
sendDebug("AFRH address = 0x%08x, AFRH value = %08x, ", (unsigned long*)(GPIOB_BASE+0x24), *(unsigned long*)(GPIOB_BASE+0x24));
sendDebug("MODER address = 0x%08x, MODER value = %08x\r\n", (unsigned long*)(GPIOB_BASE), *(unsigned long*)(GPIOB_BASE));
sr = spiDescriptor[spiPort]->spiBase->SR;
while(sr & SPI_SR_RXNE)
{
/* get rx byte */
temp = *(uint8_t *)&(spiDescriptor[spiPort]->spiBase->DR);
spiDescriptor[spiPort]->spiBase->DR = 0x53;
sendDebug("-------->DR address = 0x%08x, data received: 0x%02x\r\n", &spiDescriptor[spiPort]->spiBase->DR, temp);
sendDebug("SR = 0x%04x\r\n", sr);
vTaskDelay(1);
sr = spiDescriptor[spiPort]->spiBase->SR;
}
while((spiDescriptor[spiPort]->spiBase->SR) & SPI_SR_BSY)
{
sendDebug("SPI is busy(2)\r\n");
vTaskDelay(2);
}
return true;
}

我做错了什么?有什么我没有正确配置?提前致谢。 问候, 哈维尔

2 个答案:

答案 0 :(得分:0)

我切换到软件NSS并从我在网上找到的CUBE示例中复制了寄存器值。我不能将这些库用于此项目,但我希望具有相同的行为。新值是:

CR1 = 0x0278 这意味着fPCLK / 256(适用于通信速度),SPI启用和SSM = 1(软件NSS)。

CR2 = 0x1700 这意味着如果FIFO级别大于或等于1/4(8位),则会生成8位数据和RXNE事件。

AFRH = 0x55303500,MODER = 0xa8a1556a 这意味着MISO,MOSI和SCK交替功能5(SPI2)。 NSS未配置,因为它现在处于软件模式(始终选择从站)。

我仍然得到相同的结果,使用SPI1的evalkit与这些库工作正常。因此,必须存在与寄存器值无关的另一个问题......可能存在任何时钟问题,例如引脚需要一些时钟? 谢谢!

答案 1 :(得分:0)

问题指向几个错误,这些错误可以解释为什么未观察到接收到的情况:

  1. GPIO配置指向一些错误的备用功能/模式: 这个问题并未准确说明,但我认为

    AFRH = 0x55303500
    MODER = 0xa8a1556a
    

    指的是GPIOB(否则,对于SPI2则没有意义)。 这对应于以下引脚配置(请参见 Reference Manual, 秒8.4.1、8.4.10和 Datasheet, 表16):

    PB15 - Alternate Function - AF5 = [INVALID]
    PB14 - Alternate Function - AF5 = [I2C2_SDA]
    PB13 - Alternate Function - AF3 = [TSC_G6_IO3]
    PB12 - GP Input (reset state)
    PB11 - Alternate Function - AF3 = [TIM_CH4]
    PB10 - Alternate Function - AF5 = [SPI2_SCK / I2S2_CK]
    PB09 - GP Input (reset state)
    PB08 - GP Output
    PB07 - Alternate Function - (unknown which, see register AFRL)
    PB06 - GP Output
    PB05 - Alternate Function - (unknown which, see register AFRL)
    PB04 - GP Output
    PB03 - GP Output
    PB02 - Alternate Function - (unknown which, see register AFRL)
    PB01 - Alternate Function - (unknown which, see register AFRL)
    PB00 - Alternate Function - (unknown which, see register AFRL)
    

    这显然不是软件必须要做的。

    解决方案:确保配置 PB15 => AF0 PB14 => AF0 PB13 => AF0 PB10 => AF0 ,具体取决于您的硬件。

    为了避免这样做的错误,应遵循@P__J__的提示,并对分配给MODER,AFRH等的常量使用语音宏。 使用ST提供的HAL库在SO用户中确实是一个有争议的主题,但是 确实应该考虑至少将stm32f072xb.h之类的标头与GPIO_AFRH_AFSEL15之类的宏一起使用。 如果将所有配置寄存器值都表示为此类宏的(按位)或,则更容易根据数据表重新检查配置,著名的是 rubber duck 将直接知道不满意的开发人员在谈论什么。

  2. 其他时钟激活可能会丢失: 问题证实了

    寄存器APB1ENR也已正确配置。

    这是正确的(只要设置了位14)。

    此外,必须为GPIOB供电。例如,必须设置RCC_AHBENR的第18位。 再看一遍 Reference Manual, 秒6.4.8和6.4.6。

  3. GPIO引脚在调试过程中可能处于错误模式:

    我什至将引脚配置为输入,我知道我可以读取主机可以发送的任何数字信号。在当前配置下,从设备似乎收到了一些东西,因为当主设备发送数据时RXNE被置位,但读取值始终为0x00。

    请注意,对于每个GPIO引脚,通过MODER寄存器选择唯一模式。如果将其设置为“输入”(0b00),则“备用功能”将断开连接,并且不适用于外部信号。