我使用的是 STM32F072RBuC来接收和传输数据。SPI2
在从属模式下,配置如下。
CR1 = 0x0078
CR2 = 0x0700
AFRH = 0x55353500
MODER = 0xa2a0556a
寄存器 APB1ENR
也是正确配置的。
目前的程序只是检查 RXNE
标志,从 DR
并发送一个随机值写到 DR
.
当我接收数据时,状态寄存器的值如下。
SR = 0x1403
主站正确地发送数据,我检查了从站引脚的信号(两边的时钟相位和极性相同,在通过MOSI发送SCK和数据之前,NSS信号已被清除),我甚至将引脚配置为输入,我知道我可以读取任何主站可以发送的数字信号。
我甚至将这些引脚配置为输入,我知道我可以读取主控发送的任何数字信号。RXNE
是在主站发送数据时设置的,但读取的值总是0x00.我试过不同的配置(软硬件NSS,不同的数据大小等),但我总是得到0x00.此外,我在读取数据后发送的随机值是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;
}
我到底做错了什么? 我有什么地方没有配置好吗?
先谢谢你!Regards,Javier
我改用软件NSS,并从网上找到的STM32CubeMX例子中复制了寄存器值。我不能在这个项目中使用这些库,但我希望有同样的行为。
新的值是
CR1 = 0x0278
这意味着
CR2 = 0x1700
这意味着
RXNE
如果FIFO级别大于或等于14(8位),则会产生事件。AFRH = 0x55303500
MODER = 0xa8a1556a
这意味着
我还是得到了同样的结果,而带有这些库的评估套件在使用这些库时也能正常工作。SPI1
因此,一定有另一个与寄存器值无关的问题。
会不会是时钟的问题,比如说引脚需要一些时钟?
谢谢!我使用的是STM32F072RB的uC。
这个问题指向了几个错误,可能解释了为什么没有观察到接收。
GPIO配置指向一些错误的交替功能模式:问题没有准确说明,但我假设:
AFRH = 0x55303500 MODER = 0xa8a1556a
指的是GPIOB(否则,它与SPI2就没有意义了)。参考手册第8.4.1、8.4.10节和第8.4.2节。8.4.1、8.4.10和《联合国宪章》的规定。技术资料,表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等分配的常量使用speaking macros.使用ST提供的HAL库在SO用户中确实是一个有争议的话题。不过 一个人应该真正考虑使用至少一个头,如 stm32f072xb.h
与宏,如 GPIO_AFRH_AFSEL15
.如果将所有配置寄存器的值表示为这种宏的(位智)OR,则更容易根据数据表重新检查配置,著名的是橡皮鸭会直接知道一个不开心的开发商在说什么。
其他的时钟激活可能会缺失:问题证实了
登记册
APB1ENR
也是正确的配置。
这是正确的(只要位14被设置)。
此外,GPIOB 必须被供电,也就是说,GPIOB 的位 18 必须被设置。RCC_AHBENR
必须设置。参考手册6.4.8和6.4.6。6.4.8 和 6.4.6.
在调试过程中,GPIO引脚可能处于错误的模式下,我甚至将引脚配置为输入,我知道我可以读取任何主站可以发送的数字信号。
我甚至将这些引脚配置为输入,我知道我可以读取主控端发送的任何数字信号。在目前的配置下,似乎从机接收到了一些东西,因为当主机发送数据时,RXNE被设置,但读取值总是0x00。
请注意,每一个GPIO引脚都有一个独特的模式,通过下面的命令来选择 MODER
寄存器,如果将其设置为 "输入"( 如果将其设置为 "输入"(0b00
),备用功能被断开,无法与外部信号配合。