1
\$\begingroup\$

i bought a small board with an acceleration sensor (ADXL345) on it and now i try to write my functions to communicate with the IC. I use an STM8S103F3P6 as controller and ST Visual Develop as IDE. So at first i took a look at the "rising/falling edge schematic": ADXL345 Schematic

So at first i want to write the "writeCommand" function, it looks like this, currently:

void writeCommand(uint16_t cmd){
    uint8_t i,k;
    GPIOD->ODR |= (1<<SDIO); //turn SDIO HIGH to turn it LOW later

    GPIOD->ODR &= ~(1<<CS); //turn CS LOW
    delay_ms(2);
    GPIOD->ODR &= ~(1<<SCLK); //turn SCLK LOW

    for(k = 0; k < 2; k++){ //proceed with toggling R/W and multiple-byte bit
        GPIOD->ODR ^= (1<<SDIO);
        delay_ms(1);
        GPIOD->ODR |= (1<<SCLK);
        delay_ms(1);
        GPIOD->ODR &= ~(1<<SCLK);
    }

    for(i = 0; i < 15; i++){ //start writing data
        if(cmd & 128){
            GPIOD->ODR |= (1<<SDIO);
        } else {
            GPIOD->ODR &= ~(1<<SDIO);
        }
        GPIOD->ODR |= (1<<SCLK);
        cmd << 1;
        GPIOD->ODR &= ~(1<<SCLK);
    }
    delay_ms(1);
    GPIOD->ODR |= (1<<CS);
}

I am wondering why there are only 6 (A5...A0) address bits? I am not sure how to concatenate the register i want to write to and the data.

Would this be the right way to call my function?

writeCommand(0x2C << 8 | 0x09); //write 1001 to 0x2C register

I know that it is probably possible to do this with hardware SPI but i want to learn how to do it by software. So maybe a few questions sound retarded but i hope you will still answer them :)

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Did you look at the datasheet? None of the register addresses exceed 6 bits, so you don't need to worry about not having 8. Furthermore, the 2 extra bits are used to signify Read/notWrite and Multibyte access.

Your write command matches your function (16 bits at a time), but there is really no way for you to do multibyte access with it. Perhaps a more generic function (one that can take a pointer to a buffer as an argument, along with transfer length) would be useful.

If you want to write 0x09 to register 0x2C, the command should be fine. However, I would still suggest using the SPI drivers from the SDK instead of writing your own.

To combine multiple fields you will need to do something like this:

#define WRITE (0 << 7)
#define READ  (1 << 7)
#define MB    (1 << 6)

Then to form all 16 bits you would do:

uint16_t read_message = ((READ | addr) << 8) | garbage;
uint16_t write_message = ((WRITE | addr) << 8) | data;

If you wanted to issue a multibyte read message your first byte would become:

uint8_t read_multibyte = READ | MB | addr;

To expand on my previous comment about a more generic function, though, and one that would allow you to use multibyte commands, you could do something like this:

void sendCommand(uint8_t * buffer, uint8_t length)
{
   for (int i = 0; i < length; i++)
   {
      sendByte(buffer[i]);
   }
}

void sendByte(uint8_t byteToSend)
{
   // Put an 8-bit of your SPI function here
}

Then the data you send can become:

buffer[0] = READ | MB | addr;
// The rest of the buffer doesn't matter since we are reading
sendCommand(buffer, 4); // Will receive 3 bytes

Also you may want to use brackets to make your commands easier to read and eliminate any potential errors due to order of operations.

\$\endgroup\$
7
  • \$\begingroup\$ How can i combine 3 different bit-values? I want to add 00(Write and MB bit) to 0x2C (register) and to 0x09 (data) so that it would be: 00|101100|0000|1001 \$\endgroup\$ Commented Apr 15, 2016 at 18:45
  • \$\begingroup\$ I added some extra information, hopefully that helps! Let me know if you have any more questions. \$\endgroup\$
    – Catsunami
    Commented Apr 15, 2016 at 19:32
  • \$\begingroup\$ Thanks! One question would be how i can actually read bytes from the IC? Do i have to do the things i have done in my writeCommandfunction backwards? \$\endgroup\$ Commented Apr 15, 2016 at 19:45
  • \$\begingroup\$ To read, you start the transfer as you do now (send READ|addr as the first byte), and then you need to get the data from the MISO (SDA, I think) line at roughly the same time as you push data out on the MOSI (SDO). Roughly because they are offset by 1/2 of the SCK cycle. So in that loop where you are pushing the bits out, you should also read some values in right before you flip the SCK value. Also one quick note, your clock changes too fast (I think) - you set it and clear it almost immediately. You should add some sort of a delay there to control the bit rate. \$\endgroup\$
    – Catsunami
    Commented Apr 15, 2016 at 19:53
  • \$\begingroup\$ In fact you have a delay between the SCK changes when you do the read/write byte and the MB byte. Just do the same thing when you send the data. \$\endgroup\$
    – Catsunami
    Commented Apr 15, 2016 at 19:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.