簡體   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