我正在使用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;
}
我做错了什么?有什么我没有正确配置?提前致谢。 问候, 哈维尔
答案 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)
问题指向几个错误,这些错误可以解释为什么未观察到接收到的情况:
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
将直接知道不满意的开发人员在谈论什么。
其他时钟激活可能会丢失: 问题证实了
寄存器
APB1ENR
也已正确配置。
这是正确的(只要设置了位14)。
此外,必须为GPIOB供电。例如,必须设置RCC_AHBENR
的第18位。
再看一遍
Reference Manual,
秒6.4.8和6.4.6。
GPIO引脚在调试过程中可能处于错误模式:
我什至将引脚配置为输入,我知道我可以读取主机可以发送的任何数字信号。在当前配置下,从设备似乎收到了一些东西,因为当主设备发送数据时RXNE被置位,但读取值始终为0x00。
请注意,对于每个GPIO引脚,通过MODER
寄存器选择唯一模式。如果将其设置为“输入”(0b00
),则“备用功能”将断开连接,并且不适用于外部信号。