STM32F4 SPI问题

时间:2015-11-29 13:04:18

标签: c embedded stm32 spi

我正在使用STM32F407vg并且我试图在SPI数据寄存器中写入数据,以下代码显示了配置功能

void init_SPI1(void){

GPIO_InitTypeDef GPIO_InitStruct;
SPI_InitTypeDef SPI_InitStruct;

// enable clock for used IO pins
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

/* configure pins used by SPI1
     * PA4 = NSS
 * PA5 = SCK
 * PA6 = MISO
 * PA7 = MOSI
 */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_6 | GPIO_Pin_5|GPIO_Pin_4;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStruct);

// connect SPI1 pins to SPI alternate function
GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);

//Set chip select high 
GPIOA->BSRRL |= GPIO_Pin_4; // set PE4 high

// enable peripheral clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

/* configure SPI1 in Mode 0 
 * CPOL = 0 --> clock is low when idle
 * CPHA = 0 --> data is sampled at the first edge
 */
SPI_StructInit(&SPI_InitStruct); // set default config 
SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // set to full duplex mode, seperate MOSI and MISO lines
SPI_InitStruct.SPI_Mode = SPI_Mode_Master;     // transmit in master mode, NSS pin has to be always high
SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b; // one packet of data is 8 bits wide
SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;        // clock is low when idle
SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;      // data sampled at first edge
SPI_InitStruct.SPI_NSS = SPI_NSS_Soft ; // set the NSS management to internal and pull internal NSS high
SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; // SPI frequency is APB2 frequency / 4
SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;// data is transmitted MSB first
SPI_Init(SPI1, &SPI_InitStruct); 

SPI_Cmd(SPI1, ENABLE); // enable SPI1
} 

这是发送数据的功能

 uint8_t SPI1_send(uint8_t data){

SPI1->DR = data; // write data to be transmitted to the SPI data register
while( !(SPI1->SR & SPI_I2S_FLAG_TXE) ); // wait until transmit complete
while( !(SPI1->SR & SPI_I2S_FLAG_RXNE) ); // wait until receive complete
while( SPI1->SR & SPI_I2S_FLAG_BSY ); // wait until SPI is not busy anymore
return SPI1->DR; // return received data from SPI data register
}

我认为我已经设置了良好的配置(我认为引脚的选择没有错误以及所用总线的配置)以下图片是从STM32F407 DataSheet中提取的 SPI_Alternate_Function_Mapping enter image description here

问题是DR注册表中的数据与作为参数Debug_Figure传递的数据不同。我不知道为什么会发生这种情况。任何人都可以指导我到正确的位置

3 个答案:

答案 0 :(得分:4)

SPI DR寄存器不是正常的存储器位置,写入和读取访问同一存储器。

相反,写入加载输出移位寄存器,而读取读取接收的输入。根据设备的详细信息,阅读也可以"声明"输入,从寄存器中清除它直到收到另一个字。

由于这些原因,尝试使用调试器观察SPI DR不仅不会向您提供您寻找的信息,甚至可能会损坏您将收到的数据。

答案 1 :(得分:2)

this book读取SPI部分后,我的问题解决了,我只需将SPI MOSI连接到SPI MISO引脚(PA6和PA7),然后使用以下功能:

int spiReadWrite(SPI_TypeDef* SPIx, uint8_t *rbuf,
const uint8_t *tbuf, int cnt, enum spiSpeed speed)
{
int i;
SPIx->CR1 = (SPIx->CR1 & ~SPI_BaudRatePrescaler_256) |
speeds[speed];
for (i = 0; i < cnt; i++){
  if (tbuf) {
  SPI_I2S_SendData(SPIx, *tbuf++);
  } else {
  SPI_I2S_SendData(SPIx, 0xff);
  }
while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET);
  if (rbuf) {
  *rbuf++ = SPI_I2S_ReceiveData(SPIx);
  } else {
  SPI_I2S_ReceiveData(SPIx);
  }
}
return i;
}

通过使用调试器,我可以看到发送的数据(来自tbuf)已成功接收(在rbuf中)

答案 2 :(得分:0)

请注意SCLK_freq = APB2_freq /(BaudRatePrescaler + 1)