如何向加速度计LIS3LV02DQ的控制寄存器写入数据?

问题描述 投票:0回答:1

我正在编写一个驱动程序来使用加速度计 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
    }
}
c embedded stm32 accelerometer cmsis
1个回答
0
投票

您的

LIS3_write_data()
功能并未按照您想象的方式工作。

uint16_t tx_data = ((地址<< 8) | data) & 0x7fff;

对于使用 Little Endian 的机器,这行代码中的

tx_data
会将值像数组一样存储为
array[0] = data
array[1] = address
,当您尝试通过 SPI 传输时,这不是正确的顺序。

© www.soinside.com 2019 - 2024. All rights reserved.