1
\$\begingroup\$

After software SPI didn't work out I am now trying to connect to the ADXL345 acceleration sensor via hardware SPI of the STM8S103F3. But, of course, problems appeared again, why not. This is my SPI-Init code:

void initSPIMaster(){
    GPIOC->DDR = (1<<MOSI) | (1<<SCK) | (0<<MISO); //MOSI & SCK output, MISO input
    GPIOC->CR1 = (1<<MOSI) | (1<<SCK); //MOSI& SCK push-pull

    GPIOA->DDR |= (1<<CS); //set CS as output
    GPIOA->CR1 |= (1<<CS); //set CS as push-pull
    GPIOA->ODR |= (1<<CS); //turn CS high

    SPI->CR2 = 0b00000000; //2-line unidirectional, Hardware-Slave  management
    SPI->CR1 = 0b01111111; //Enable CPHA, CPOL, MASTER; Baudrate: f/256, SPI Enable
}

This is my SPI-Transmit function to write data to the DR-Register:

void SPITransmit(uint8_t data){
    while(!(SPI->SR & (1<<1))){
        nop(); //wait until transmit buffer is empty
    }
    SPI->DR = data;
    while((SPI->SR & (1<<7))){
        nop(); //wait until not busy
    }
}

This is my SPIReceive function to read data from the DR-Register:

uint8_t SPIReceive(){
    uint8_t registerValue;
    while((SPI->SR & (1<<7))){
        nop(); //wait until not busy
    }
    while(!(SPI->SR & (1<<0))){
        nop(); //wait until receive buffer is not empty
    }
    registerValue = (SPI->DR);
    nop();
    return registerValue;
}

As a initial test I tried to read the DEVID register of the ADXL345 (0x00), it should return 229 as decimal value. And indeed, it did, this is my function to read a register:

void getValueFromRegister(uint8_t reg, uint8_t *val){
    uint8_t transmitValue = (0x80 | reg);
    uint8_t receivedValue = 0;

    GPIOA->ODR &= ~(1<<CS); //CS low
    SPITransmit(transmitValue); //write 'read' command
    delay_ms(10);
    receivedValue = SPIReceive();
    GPIOA->ODR |= (1<<CS); //CS high

    delay_ms(10);
    *val = receivedValue;
}

I also enabled the ADXL345 with this code:

void initADXL345(){
    //enable measurements
    GPIOA->ODR &= ~(1<<CS); //turn CS low
    SPITransmit(0x2D);
    SPITransmit(0x08);
    GPIOA->ODR |= (1<<CS); //turn CS high
    delay_ms(5);

    //set FULL_RES & 16g-Range
    GPIOA->ODR &= ~(1<<CS); //turn CS low
    SPITransmit(0x31);
    SPITransmit(0b00001011);
    GPIOA->ODR |= (1<<CS); //turn CS high
}

So the next logical step would be to read data from the data registers (0x32-0x37), so I did (x, y, z are global values of type int16_t):

void getXYZValues(){
    uint8_t x0,x1,y0,y1,z0,z1;
    getValueFromRegister(0x32, &x0);
    delay_ms(10);
    getValueFromRegister(0x33, &x1);
    delay_ms(10);
    getValueFromRegister(0x34, &y0);
    delay_ms(10);
    getValueFromRegister(0x35, &y1);
    delay_ms(10);
    getValueFromRegister(0x36, &z0);
    delay_ms(10);
    getValueFromRegister(0x37, &z1);

    x = ((x1<<8) | x0);
    y = ((y1<<8) | y0);
    z = ((z1<<8) | z0);
}

The problem now is:

I always get the value -6683 (decimal) for every axis! And these value isn't even changing if I move the sensor!

For gods sake, why is it so horrible to work with this sensor?

I thought about that maybe CPOL or CPHA is the problem but according to the datasheet they should both be enabled (as I did).

Any ideas, why this is not working? I am really frustrated and I try to get it to work for weeks (if I add the days from my first try with software SPI).

\$\endgroup\$
  • 2
    \$\begingroup\$ There is a very big clue in the data; -6683 is 0xFFFFFFFFFFFFE5E5, or 0xE5E5 when limited to a 16 bit value; the ID register returns E5 in its ID. This makes me think you are simply getting repeats of the ID register reads; try reading back the setup registers (0x2D and 0x31) and check they are indeed being set up as you think. If not, it implicates the transmit function. \$\endgroup\$ – Peter Smith May 8 '16 at 14:15
  • \$\begingroup\$ You are completely right! I get the value 8 (decimal) for 0x2D and 0x31 register even though 0x31 should have the value 11 (decimal). But how do i know if the transmit or receive function is faulty? \$\endgroup\$ – binaryBigInt May 8 '16 at 14:26
  • \$\begingroup\$ The receive function is working for a device ID read, and I would therefore surmise it is operational. That leaves the transmit function. Note that the datasheet recommends a burst read of all 6 registers in a single transaction, but it should not be necessary unless you require guaranteed precision. I would suggest a breakpoint in the transmit function immediately after the SPI block data register is loaded; see what is in there. It is interesting that the value in the second register is the same as the first write \$\endgroup\$ – Peter Smith May 8 '16 at 14:29
  • \$\begingroup\$ If i write 0x31 to the DR-Register i get 0x0B as the value of the SPI Data register. Why? \$\endgroup\$ – binaryBigInt May 8 '16 at 14:38
  • \$\begingroup\$ 0x0B is what you are trying to write (0b00001011 = 0x0B) \$\endgroup\$ – Peter Smith May 8 '16 at 15:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.