Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
457 views
in Technique[技术] by (71.8m points)

c - Assigning individual bits to bytes

I have a to make a SPI communication between a microcontroller and another chip. The chip accepts a 16bit word. But the abstraction library requires the data to be sent as two 8bit bytes. Now I want to make a wrapper so I can easily create requests for read and write...but I have not yet got any success. Here is how it supposed to be:

The table below shows 16bits. The MSB can be 0 for write or 1 for read. The address can be from 0x0 to 0x7 and the data is 11 bits.

R/W  |      ADDRESS   |    DATA
 B15 |      B14-B11   |   B10-B0
 0   |        0000    | 00000000000
 W0  | A3, A2, A1, A0 | D10, D9, D8, D7, D6, D5, D4, D3, D2, D1, D0

For example, if I want to read from register 0x1 I think I have to set the bits like this:

 W0  | A3, A2, A1, A0 | D10, D9, D8, D7, D6, D5, D4, D3, D2, D1, D0
  1  | 0    0   0   1 |  0    0   0   0   0   0   0   0   0   0   0

Or reading from register 0x7:

 W0  | A3, A2, A1, A0 | D10, D9, D8, D7, D6, D5, D4, D3, D2, D1, D0
  1  | 0    1   1   1 |  0    0   0   0   0   0   0   0   0   0   0

I have tried to create this struct/union to see if it can work:

typedef struct{
    uint8_t acc_mode:1;
    uint8_t reg_addr:4;
    uint8_t reg_data:8; //TODO fix me should be 11
} DRVStruct;

typedef union {
    DRVStruct content;
    uint16_t all;
} DRVUnion;

void DRV_PrepareReadMsg(uint8_t reg, uint8_t* msgBuffer) {
    DRVUnion temp;
    temp.content.acc_mode = 1;
    temp.content.reg_addr = reg;
    temp.content.reg_data = 0; //read mode does not need data!

    msgBuffer[1] = temp.all & 0xFF;
    msgBuffer[0] = temp.all >> 8;
}

I am getting strange results...from time to time I get answer from the SPI (I am sure the SPI communication is OK, but my code for preparing messages is the problem).

So the questions are:

  • Am I doing the right thing or approach?
  • How can I increase bit width of reg_data from 8 to 11 without getting compile error?
  • What do you suggest for a better approach?
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This seems to work:


#include <stdio.h>
#include <stdint.h>

typedef union {
    struct{     // no struct tag, since it is not needed...
        uint16_t acc_mode:1;
        uint16_t reg_addr:4;
        uint16_t reg_data:11; //TODO fix me should be 11
        } bits;
    uint16_t all;
    uint8_t bytes[2]; //extra bonus when lit;-)
        } DRVUnion;

int main(void)
{
DRVUnion uni,uni13[13];

printf("Size=%zu, %zu
", sizeof uni, sizeof uni13);
return 0;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...