Lacko
Lacko

Reputation: 79

Reading bits serially in C

I am trying to convert a bit of code from Python to C. I have got it all working other than the section below. All the variables have been defined as ints. I believe the problem has to do with pointers and addresses but I can't work it out.

for(j=0; j<12; j++)
{
  digitalWrite(CLOCK, 1);
  sleep(0.001);
  bit = digitalRead(DATA_IN);
  sleep(0.001);
  digitalWrite(CLOCK, 0);
  value = bit * 2 ** (12-j-1);  // error
  anip = anip + value;
  printf("j:%i bit:%i value:%i anip:%i", j, bit, value, anip);
}

The error is invalid type argument of unary ‘*’ (have ‘int’)

Upvotes: 1

Views: 155

Answers (3)

Adam Liss
Adam Liss

Reputation: 48330

The sleep() function takes an integer argument and waits for the specified number of seconds. The argument 0.001 becomes 0, which is probably not what you want. Instead, try usleep(), which takes an argument that represents milliseconds.

The other answers will solve the generic problem of raising an arbitrary number to a power, or to a power of 2, but this is a very specific case.

The purpose of the loop is to read 11 bits serially from MSB to LSB and convert them into an integer. The implementation you've shown attempts to do this by reading a bit, shifting it to the correct position, and accumulating the result into anip. But there's an easier way:

anip = 0;
for (j=0; j<12; ++j) {
  // Pulse the CLOCK line and read one bit, MSB first.
  digitalWrite(CLOCK, 1);
  usleep(1);
  bit = digitalRead(DATA_IN);
  usleep(1);
  digitalWrite(CLOCK, 0);

  // Accumulate the bits.
  anip <<= 1;    // Shift to make room for the new bit.
  anip += bit;   // Add the new bit.

  printf("j:%i bit:%i anip:%i", j, bit, anip);
}

As an example, suppose the first 4 bits are 1,0,0,1. Then the output will be

j:0 bit:1 anip:1
j:1 bit:0 anip:10
j:2 bit:0 anip:100
j:3 bit:1 anip:1001

When the loop completes, anip will contain the value of the entire sequence of bits. This is a fairly standard idiom for reading data serially.

Although the advice to use uint32_t is generally appropriate, the C standard defines int to be at least 16 bits, which is more than the 12 you need (including the sign bit, if anip is signed). Moreover, you're probably writing this for a specific platform and therefore aren't worried about portability.

Upvotes: 2

BraveNewCurrency
BraveNewCurrency

Reputation: 13065

In C, 1<<i is the best way to raise i to the power of 2.

Do not use ints for bit manipulation, because they vary in size by platform. Use uint32_t from /usr/include/stdint.h.

Upvotes: 7

Some programmer dude
Some programmer dude

Reputation: 409384

C has no exponentiation operator, which is what I guess you do ** for.

You can use e.g. pow if it's okay to typecast the result from a floating point value back to an integer.

Upvotes: 7

Related Questions