我正在编写一个驱动程序来使用加速度计 LIS3LV02DQ 测量加速度。我使用STM32F411和CMSIS。我连接了一个四通道SPI并将其频率设置为大约1 MHz。我可以从加速度计读取寄存器值,但在其中写入值时没有任何反应。使用示波器,我可以看到 STM32 的输出信号与数据表中的一模一样,但加速度计没有响应它们。此外,STM32 上的 SPI2->SR 并没有显示通过 SPI 传输期间发生了某些错误。可能是什么错误?
我的函数的源代码:
void setup_LIS_spi() {
// set GPIO pins
// set PB10 as input, PB12 (CS) as output, PB15:13 as AF
GPIOB->MODER |= (GPIO_MODER_MODER12_0 | GPIO_MODER_MODER13_1
| GPIO_MODER_MODER14_1 | GPIO_MODER_MODER15_1);
GPIOB->OSPEEDR |= ((0xFF << 24) | (3 << 20)); // high speed for PB15:PB12 & PB10 pins
// enable AF05 for PB13 (SCK), PB14 (MISO) and PB15 (MOSI)
GPIOB->AFR[1] |= ((5 << 20) | (5 << 24) | (5 << 28));
// set SPI2 properties
SPI2->CR1 |= SPI_CR1_MSTR; // master mode
SPI2->CR1 |= SPI_CR1_SSM; // software slave management
SPI2->CR1 |= SPI_CR1_SSI; // internal slave select
SPI2->CR1 |= SPI_CR1_SPE; // SPI enable
// transmission of 16 bits
SPI2->CR1 |= SPI_CR1_DFF;
// APB2 = 50 MHz
// Baud rate ~ 1 MHz = (50 / 16) MHz
SPI2->CR1 |= (3 << 3);
// LIS3LV02DQ
SPI2->CR1 |= SPI_CR1_CPOL;
SPI2->CR1 |= SPI_CR1_CPHA;
}
static inline void transfer_spi2_16bit(const uint16_t byte_send, uint16_t *byte_read) {
while (SPI2->SR & SPI_SR_BSY); // wait for when spi is not busy
SPI2->DR = byte_send;
while(!(SPI2->SR & SPI_SR_RXNE)); // wait for when rx buffer is not empty
*byte_read = SPI2->DR & 0xFFFF;
}
// dalay = 10 000 == 1 ms
inline void __attribute__((always_inline)) delay(uint32_t delay) {
while(delay--) __asm("");
}
void LIS3_write_data(uint8_t address, uint8_t data) {
// the first 8 bits indicate the address of the register to be communicated with
// the next 8 bits transmit the value to be written to this register
// The 16th bit must be equal to 0 in order for a register entry to occur.
uint16_t tx_data = ((address << 8) | data) & 0x7fff;
uint16_t trash = 0;
CS_OFF;
transfer_spi2_16bit(tx_data, &trash);
// the delay is manually adjusted so that CS becomes 1 when all bits are sent
delay(105);
CS_ON;
}
uint8_t LIS3_read_data(uint8_t address) {
address |= READ_FLAG;
uint16_t rx_data = 0;
uint16_t tx_data = (address << 8);
CS_OFF;
transfer_spi2_16bit(tx_data, &rx_data);
delay(105);
CS_ON;
// the required data is in the lower 8 bits
return (uint8_t)(rx_data & 0x00FF);
}
如果我只是读取 WHO_AM_I 寄存器,那么它的正确值就会返回给我:
int main() {
setup_LIS_spi();
while (1) {
// value after reset
LIS3_read_data(0x0F); // return 0x3A
LIS3_read_data(0x20); // return 0x07
}
}
如果我将一个值写入寄存器作为初始化,然后读取同一寄存器的值,则返回未更改的值:
int main() {
setup_LIS_spi();
LIS3_write_data(0x20, 0x87)
while (1) {
LIS3_read_data(0x20); // return 0x07
}
}
如果我在无限循环中调用寄存器写入函数,那么读取时会返回0xff
int main() {
setup_LIS_spi();
while (1) {
LIS3_write_data(0x20, 0x87)
delay(10000);
LIS3_read_data(0x20); // return 0xFF
}
}
您的
LIS3_write_data()
功能并未按照您想象的方式工作。
uint16_t tx_data = ((地址<< 8) | data) & 0x7fff;
对于使用 Little Endian 的机器,这行代码中的
tx_data
会将值像数组一样存储为 array[0] = data
和 array[1] = address
,当您尝试通过 SPI 传输时,这不是正确的顺序。