STM32F407 SPI при чтении данных LIS3DSH

#spi

#spi

Вопрос:

  uint8_t SPI_Rx(uint8_t address)
    {
     GPIO_ResetBits(GPIOE,GPIO_Pin_3);
     address    =   (0x80) | (address);
        
     while(!SPI_I2S_GetFlagStatus(SPI1,SPI_FLAG_TXE));     
     SPI_I2S_SendData(SPI1,address);
     while(!SPI_I2S_GetFlagStatus(SPI1,SPI_FLAG_RXNE));
     SPI_I2S_ReceiveData(SPI1);
        
     while(!SPI_I2S_GetFlagStatus(SPI1,SPI_FLAG_TXE));     
     SPI_I2S_SendData(SPI1,0x00);
     while(!SPI_I2S_GetFlagStatus(SPI1,SPI_FLAG_RXNE));
     SPI_I2S_ReceiveData(SPI1);
        
     GPIO_SetBits(GPIOE,GPIO_Pin_3);
     return SPI_I2S_ReceiveData(SPI1);
 

Привет, то, что вы видите, это функции чтения SPI для датчика LIS3DSH. Прежде всего, после того, как я отправлю информацию об адресе, буфер SPI RX получает данные датчика LIS3DSH. Но тогда зачем ему нужно получать данные датчика LIS3DSH, отправляя «0x00»? Вкратце, почему нам нужно снова отправлять данные else, когда мы уже получили данные? Заранее благодарю.

Ответ №1:

При чтении данных из регистра LIS3DSH вся транзакция SPI имеет длину в два байта:

  • Байт 1: мастер отправляет адрес регистра (вкл. флаг чтения / записи) к датчику.
  • Байт 2: датчик отправляет значение регистра ведущему устройству.

Однако SPI является полнодуплексным протоколом. Для каждого бита и байта как ведущий, так и ведомый (датчик) отправляют данные. Таким образом, реальное общение на самом деле выглядит так:

  • Байт 1
    • Мастер отправляет адрес регистра.
    • Подчиненное устройство отправляет 0 или любое случайное значение.
  • Байт 2
    • Мастер отправляет 0.
    • Подчиненное устройство отправляет значение регистра.

Это то, что вы видите в коде:

  while(!SPI_I2S_GetFlagStatus(SPI1,SPI_FLAG_TXE));  // Wait for SPI bus to be ready
 SPI_I2S_SendData(SPI1,address);                    // Submit byte 1 to be sent
 while(!SPI_I2S_GetFlagStatus(SPI1,SPI_FLAG_RXNE)); // Wait for byte 1 from slave
 SPI_I2S_ReceiveData(SPI1);                         // Retrieve byte 1 from slave and ignore it
    
 while(!SPI_I2S_GetFlagStatus(SPI1,SPI_FLAG_TXE));  // Wait for SPI bus to be ready
 SPI_I2S_SendData(SPI1,0x00);                       // Send 0 as byte 2
 while(!SPI_I2S_GetFlagStatus(SPI1,SPI_FLAG_RXNE)); // Wait for byte 2 from slave
 SPI_I2S_ReceiveData(SPI1);                         // Retrieve byte 2 and ??

 GPIO_SetBits(GPIOE,GPIO_Pin_3);                    // Deassert CS?
 return SPI_I2S_ReceiveData(SPI1);                  // Retrieve byte 2 again and return it
 

Последняя часть несколько странная. SPI_I2S_ReceiveData() вызывается дважды в конце, вероятно, предполагая, что он вернет одно и то же значение дважды. Вероятно, было бы чище, если бы он был вызван только один раз.

Комментарии:

1. Спасибо. Я понял. Ваш пост действительно понятен.