繁体   English   中英

STM32和ADXL345之间的SPI通信

[英]SPI Communication between STM32 and ADXL345

我正在尝试使用 SPI 通信从 ADXL345 加速度计读取数据。 我在主模式下配置了不同的引脚和 SPI,并尝试读取 x、y 和 z 轴加速度。

我的问题是 SPI 读数始终为 0。我尝试调试以找到问题,但我意识到即使我正在传输数据也从未设置 RXNE,我真的不明白为什么。

我正在使用 STM32F103 板。

这是我的代码:

#include "Driver_GPIO.h"

#include "stm32f10x.h"

uint8_t RxData[6];
int x,y,z;
float   x_acc,y_acc,z_acc;

void GPIO_Config (void)
{

    
    MyGPIO_Struct_TypeDef NSS={GPIOA,4,Out_OD}; // Output Open Drain
    MyGPIO_Struct_TypeDef SCK={GPIOA,5,AltOut_Ppull}; // Alternate Output Push-Pull
    MyGPIO_Struct_TypeDef MISO={GPIOA,6,In_Floating}; // Input Floating
    MyGPIO_Struct_TypeDef MOSI={GPIOA,7,AltOut_Ppull}; // Alternate Output Push-Pull

    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; //enable GPIOA clk
    
    MyGPIO_Init(&NSS);
    MyGPIO_Init(&SCK);
    MyGPIO_Init(&MISO);
    MyGPIO_Init(&MOSI);
}
    

void SPI_Enable (void)
{
    SPI1->CR1 |= (SPI_CR1_SPE);   // SPE=1, Peripheral enabled
}

void SPI_Disable (void)
{
    SPI1->CR1 &= ~(SPI_CR1_SPE);   // SPE=0, Peripheral Disabled
}

void CS_Enable (void)
{
    GPIOA->BSRR |= GPIO_BSRR_BR9;
}

void CS_Disable (void)
{
    GPIOA->BSRR |= GPIO_BSRR_BS9;
}

void SPI_Config(void){
  RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;  // Enable SPI1 CLock
    
  SPI1->CR1 |= SPI_CR1_CPOL| SPI_CR1_CPHA;   // CPOL=1, CPHA=1
    
  SPI1->CR1 |= SPI_CR1_MSTR;  // Master Mode
    
  SPI1->CR1 |= (SPI_CR1_BR_0)| (SPI_CR1_BR_1);  // BR[2:0] = 400: fPCLK/16, PCLK2 = 72MHz, SPI clk = 3.375MHz
    
  SPI1->CR1 &= ~SPI_CR1_LSBFIRST;  // LSBFIRST = 0, MSB first
    
  SPI1->CR1 |= (SPI_CR1_SSM) | (SPI_CR1_SSI);  // SSM=1, SSI=1 -> Software Slave Management
    
  SPI1->CR1 &= ~SPI_CR1_RXONLY;  // RXONLY = 0, full-duplex
    
  SPI1->CR1 &= ~SPI_CR1_DFF;  // DFF=0, 8 bit data
    
  SPI1->CR2 = 0;

}

void SPI_Transmission(uint8_t *data, int size){
    uint8_t clear;
    //check flag TxE //
    int i=0;
    while (i<size)
    {
        while (!((SPI1->SR)&(SPI_SR_TXE))){};  // buffer is empty
        *(volatile uint8_t *)&SPI1->DR = data[i];
        i++;
    }
    
    while (!((SPI1->SR)&(SPI_SR_TXE))){};  // buffer is empty

    while (((SPI1->SR)&(SPI_SR_BSY))){}; // buffer not communicating

    
    clear= SPI1->DR; // empty Overrun flag
    clear= SPI1->SR;
}

void SPI_Receive (uint8_t *data,int size)
{
    while (size)
    {
        while (((SPI1->SR)&(SPI_SR_BSY))) {};  // buffer not communicating
        *(volatile uint8_t *)&SPI1->DR = 0;  // dummy data
        while (!((SPI1->SR) &(SPI_SR_RXNE))){};
        // buffer is not empty
        *data++= *(volatile uint8_t *)&SPI1->DR;
        size--;
    }
}

void adxl345_write (uint8_t address, uint8_t value)
{
    uint8_t data[2];
    data[0] = address|0x40;  // multibyte write
    data[1] = value;
    CS_Enable ();  // pull the cs pin low
    SPI_Transmission (data,2);  // write data to register
    CS_Disable ();  // pull the cs pin high
}
    

void adxl345_read (uint8_t address, uint8_t *RxData)
{
    address |= 0x80;  // read operation
    address |= 0x40;  // multibyte read
    CS_Enable ();  // pull the pin low
    SPI_Transmission (&address,1);  // send address
    SPI_Receive (RxData,6);  // receive 6 bytes data
    CS_Disable ();;  // pull the pin high
}

void adxl345_init (void)
{
    adxl345_write (0x31, 0x01);  // data_format range= +- 4g
    adxl345_write (0x2d, 0x00);  // reset all bits
    adxl345_write (0x2d, 0x08);  // power_cntl measure and wake up 8hz
}
int main(void)
    
{ 
    GPIO_Config();
    SPI_Config();
    SPI_Enable();
    adxl345_init();

    do{
        adxl345_read(0x32,RxData);
        x = ((RxData[1]<<8)|RxData[0]); // DATA X0, X1
        y = ((RxData[3]<<8)|RxData[2]); // DATA Y0, Y1
        z = ((RxData[5]<<8)|RxData[4]); // DATA Z0, Z1
        
        // Scale Factor for Xout, Yout and Zout is 7.8 mg/LSB for a +-4g, 10-bit resolution
        // ==> multiply by 0.0078 to get real acceleration values
        
        x_acc= x * 0.0078; 
        y_acc= y * 0.0078;
        z_acc= z * 0.0078;
        
    }while(1);
    

}

如前所述,您在这里有很多问题

  1. 为什么NSS引脚配置为开漏? 通常 CS 线是推挽式的。 我不知道原理图,但这是我第一次看到开漏 CS
  2. GPIO_Config NSS 是 pin 4,但是 pin 9 从CS_Enable切换
  3. 如果 F1 系列有单独的备用功能时钟位,则不启用

您还说 RXNE 始终为零并且读数返回零,这也很奇怪。 如果 RXNE 保持为零,您的代码应该停留在 while 循环中

我不会分析幻数,因为我没有时间检查 RM 中的每个数字。 但是你有很多明显的问题。

  1. 启用外设时钟后需要延迟或回读。 您立即设置了错误的寄存器。 添加__DSB(); 或回读(例如(void)RCC->APB2ENR; )。 所有外围设备都相同

  2. 读取或读取DR寄存器时强制使用 8 位指令。

*(volatile uint8_t *)&SPI1->DR = data[i];

否则,如果外设具有 FIFO,它将向其添加 4 个字节。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM