SPI_I2S_ReceiveData always returns 0xff or 0x00

生来就可爱ヽ(ⅴ<●) 提交于 2020-01-01 07:21:04

问题


I want to create firmware to stm32f4 discovery wich flashes the lights, when the board moves. But SPI_I2S_ReceiveData always returns 0xff or 0x00. I think the problem is in my SPI initialization but I do not know where exactly it is.

Here is my code.

#include <stm32f4xx.h>
#include <stm32f4xx_rcc.h>
#include <stm32f4xx_gpio.h>
#include <stm32f4xx_spi.h>
#include <stm32f4xx_i2c.h>

void InitLEDs(void);

void InitSPI(void);

void Delay(int iTicks);

void DiodeFlash(void);

unsigned short ReadACCELEROMETER(void);

unsigned char WriteSPI(unsigned char cbData);

int main(void)
{
    unsigned short cbPrevRead = 0;
    unsigned short cbCurrentRead = 0;

    InitLEDs();
    InitSPI();

    while(1)
    {
        cbCurrentRead = ReadACCELEROMETER();

        if (cbCurrentRead != cbPrevRead)
        {
            DiodeFlash();

            cbPrevRead = cbCurrentRead;
        }
    }
}


void InitLEDs(void)
{
    GPIO_InitTypeDef PortD;

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

    PortD.GPIO_Mode = GPIO_Mode_OUT;
    PortD.GPIO_OType = GPIO_OType_PP;
    PortD.GPIO_PuPd = GPIO_PuPd_NOPULL;
    PortD.GPIO_Speed = GPIO_Speed_100MHz;
    PortD.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;

    GPIO_Init(GPIOD, &PortD);
}


void InitSPI(void)
{
    GPIO_InitTypeDef PortA;
    GPIO_InitTypeDef PortE;

    SPI_InitTypeDef SPI1Conf;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);

    PortA.GPIO_Mode = GPIO_Mode_AF;
    PortA.GPIO_OType = GPIO_OType_PP;
    PortA.GPIO_Speed = GPIO_Speed_50MHz;
    PortA.GPIO_PuPd = GPIO_PuPd_NOPULL;
    PortA.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;

    GPIO_Init(GPIOA, &PortA);

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);


    PortE.GPIO_Mode = GPIO_Mode_OUT;
    PortE.GPIO_OType = GPIO_OType_PP;
    PortE.GPIO_Speed = GPIO_Speed_50MHz;
    PortE.GPIO_PuPd = GPIO_PuPd_NOPULL;
    PortE.GPIO_Pin = GPIO_Pin_3;

    GPIO_Init(GPIOE, &PortE);

    GPIOE->ODR = 0x0008; // Disable CS

    SPI1Conf.SPI_DataSize = SPI_DataSize_8b;
    SPI1Conf.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;
    SPI1Conf.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI1Conf.SPI_FirstBit = SPI_FirstBit_MSB; // ACCELEROMETER PROTOCOL
    SPI1Conf.SPI_Mode = SPI_Mode_Master;
    SPI1Conf.SPI_CPHA = SPI_CPHA_2Edge;
    SPI1Conf.SPI_CPOL = SPI_CPOL_High;
    SPI1Conf.SPI_CRCPolynomial = 7;
    SPI1Conf.SPI_NSS = SPI_NSS_Soft;
    SPI_Init(SPI1, &SPI1Conf);
    SPI_Cmd(SPI1, ENABLE);

    WriteSPI(0x23); WriteSPI(0xc9);
    WriteSPI(0x20); WriteSPI(0x97);
    WriteSPI(0x24); WriteSPI(0x00);

    WriteSPI(0x10); WriteSPI(0x00);
    WriteSPI(0x11); WriteSPI(0x00);
    WriteSPI(0x12); WriteSPI(0x00);
}


void Delay(int iTicks)
{
    while ((iTicks--) > 0);
}


void DiodeFlash(void)
{
    GPIO_Write(GPIOD, 1UL << 12);
    Delay(100000);
    GPIO_Write(GPIOD, 1UL << 13);
    Delay(100000);
    GPIO_Write(GPIOD, 1UL << 14);
    Delay(100000);
    GPIO_Write(GPIOD, 1UL << 15);
    Delay(100000);
    GPIO_Write(GPIOD, 0x0000);
}

unsigned short ReadACCELEROMETER(void)
{
    unsigned short nAxisX = 0x0000;
    unsigned short nAxisY = 0x0000;
    unsigned short nAxisZ = 0x0000;

    unsigned char cbAddress = 0x80;

    //**********************************************************
    // Forming X Value
    WriteSPI(cbAddress | 0x0f);
    nAxisX |= WriteSPI(0x00);

    WriteSPI(cbAddress | 0x2A);
    nAxisX |= WriteSPI(0x00) << 8;

    //**********************************************************
    // Forming Y Value
    WriteSPI(cbAddress | 0x2B);
    nAxisX |= WriteSPI(0x00);

    WriteSPI(cbAddress | 0x2C);
    nAxisX |= WriteSPI(0x00) << 8;

    //**********************************************************
    // Forming Z Value
    WriteSPI(cbAddress | 0x2D);
    nAxisX |= WriteSPI(0x00);

    WriteSPI(cbAddress | 0x2E);
    nAxisX |= WriteSPI(0x00) << 8;

    return nAxisX ^ nAxisY ^ nAxisZ;
}

unsigned char WriteSPI(unsigned char cbData)
{
    unsigned char cbResult = 0x00;

    GPIOE->ODR = 0x0000; // Enable CS

    // Wait for ready status
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);

    SPI_I2S_SendData(SPI1, cbData);

    // Wait for ready status
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);

    cbResult = SPI_I2S_ReceiveData(SPI1);

    GPIOE->ODR = 0x0008; // Disable CS

    return cbResult;
}

回答1:


First, you don't specify your accelerometer. I can guess, that it is ST LISxx.
In this case, there is incorrect data transfer to accelerometer.

Correct write sequence:
- activate chipselect
- write register number
- write register value
- deactivate chipselect
Use similar sequence to read each register.

Next, ST not recommend your algo for low-level SPI transfer:

Do not use the BSY flag to handle each data transmission or reception. It is better to use the TXE and RXNE flags instead

(see Reference manual). Use simply

SPIx->DR = out;  
while (!(SPIx->SR & SPI_SR_RXNE)) ;  
return SPIx->DR;  

Also, i am working with LIS3DH with CPOL=0 & CPHA = 0 SPI settings (i don't know, how it will work with your CPOL=1, CPHA=1).

Hint: to check SPI communication, try to read WHO_AM_I register - it is alawys enabled and always have known value.




回答2:


It is beacuse you writes address of register, after deselects your device, so wrote address is clean up. In this case you must do something like this.

unsigned char WriteSPI(unsigned char cbData)
{
    unsigned char cbResult = 0x00;

    // Wait for ready status
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);

    SPI_I2S_SendData(SPI1, cbData);

    // Wait for ready status
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);

    cbResult = SPI_I2S_ReceiveData(SPI1);

    return cbResult;
}


unsigned char WriteReg(unsigned char cbAddress, unsigned char cbData)
{
    unsigned char cbResult = 0x00;

    GPIOE->ODR = 0x0000; // select device
    WriteSPI(cbAddress);
    cbResult = WriteSPI(cbData);
    GPIOE->ODR = 0x0008; // deselect device

    return cbResult;
}

unsigned char ReadReg(unsigned char cbAddress)
{
    unsigned char cbResult = 0x00;

    GPIOE->ODR = 0x0000; // select device
    WriteSPI(cbAddress);
    cbResult = WriteSPI(0x00);
    GPIOE->ODR = 0x0008; // deselect device

    return cbResult;
}



回答3:


There is nothing wrong with your SPI initialization. The main mistake is in writing register addresses. You must not deselect device before reading register values, instead you must perform write address - reading values in one batch. It mean

  1. Select device.

  2. Write register address.

  3. Read register value.

  4. Deselect device.



来源:https://stackoverflow.com/questions/33078660/spi-i2s-receivedata-always-returns-0xff-or-0x00

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!