3

I'm programming with Keil uVision 4.

I have some code like this:

sbit X = P3 ^ 3; // X is third bit of P3 register

...

    while (1) {
      X = !X; // X equals not X ?!

      if (X == 0)
        printf("0");
      else
        printf("1");
    }

I can control `P3^3 generic input pin, because on this pin i've got a PIR (pulse infrared sensor). It gives me 1 on that line when it is blinking, 0 when it is sleeping.

when P3^3 is pulled-up to 1, output is (as expected) 10101010101010..

When it is still to 0, output is (as not expected) 0000000000000..

The behaviour I'm obtaing is that I described above, considering that sbit X is setted/unsetted by PIR..

So the question is, what is the meaning of the operator ! in the Keil C51 compiler?

Filippo Lauria
  • 1,965
  • 14
  • 20
  • The documentation states that an `sbit` cannot be declared inside a function, so I am also assuming that this code fragment is elided? It isn ormal to indicate that with an elipsis (`...`) – Clifford Jun 18 '13 at 19:19
  • Just to be clear, it might be helpful to describe the `expected` output when the input is low, since on analysis I think it is behaving *correctly* (i.e. as coded) given the hardware and the semantics of the `sbit` language extension. – Clifford Jun 18 '13 at 19:25
  • yes the scope is the global one. i'm expecting pretty much the same output that i had when line was high. Pratically, I was thinking that `!` is the same of `~`. – Filippo Lauria Jun 18 '13 at 20:32
  • The expression `X = !X` changes P3.3 from an input to an output and vice versa. X is a reference to the pin, not an independent variable in memory. – Clifford Jun 19 '13 at 11:09
  • Regarding being clear regarding the output, I expected you to modify the question rather than comment on it. – Clifford Jun 19 '13 at 11:15
  • I'm sorry, Clifford, I'm doing it right now. – Filippo Lauria Jun 19 '13 at 13:52

2 Answers2

4

In Keil C51, to quote the manual:

The sbit type defines a bit within a special function register (SFR)

So you are not declaring a variable X and reading it once before the loop, rather you are defining a reference to P3.3, and reading it's state on every iteration of the loop. That is to say that X is a reference to the hardware I/O pin register, not a variable.

Despite appearances sbit is not a simple typedef alias and the ^ is not a bitwise XOR operator. Rather it defines a reference to a bit addressable register. Assigning X writes to the hardware register - the behaviour is then defined by the hardware in this case rather than the language. The ability to apparently change the value of X when it is externally pulled high, I am guessing is in the nature of the GPIO hardware rather than any strange behaviour of the ! operator. Check the hardware documentation for I/O pin behaviour, but I am guessing again that pulling it high makes the pin output-capable

To get the behaviour (I imagine) you expect you would code it thus:

sbit p = P3 ^ 3; // p is third bit of P3 register


...
int X = p ; // get p's current value

while (1) {
  X = !X; // X equals not X ?!

  if (X == 0)
    printf("0");
  else
    printf("1");
}
Clifford
  • 88,407
  • 13
  • 85
  • 165
  • Sorry for being not clear, on P3^3 i've got a PIR (pulse infrared sensor). It gives me 1 on that line when it is blinking, 0 when it is sleeping. The behaviour I'm obtaing is that I described above, considering that `sbit X` is setted/unsetted by PIR. – Filippo Lauria Jun 18 '13 at 20:17
  • 1
    @FilippoLauria: I was referring the MCU GPIO hardware rather then the hardware you have connected to the pin. I believe that on 8051, a port is configured as an input by writing zero to it, which allows it to be asserted externally. You write 1 to the pin to set it as an input, thereafter you should only read it - you are writing to it in the expression `X = !X`, so you are toggling it between an input and an output in the while loop. As I said, check the documentation for your MCU. – Clifford Jun 19 '13 at 11:07
0

Presumably it means the same thing it means in standard C. !x evaluates to 1 if x==0, or to 0 otherwise. The result is of type int.

If you're looking for a bitwise complement that inverts all the bits, you want the ~ operator.

UPDATE :

There's more to it than that; see Clifford's answer.

Community
  • 1
  • 1
Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • I think that c51 is an extension of standard C. If what you said is right, why compiler doesn't give me an error (or a warning) when I'm trying to assign an `int` to a `sbit` ? – Filippo Lauria Jun 18 '13 at 20:19
  • @FilippoLauria: I don't know; quite possibly I'm wrong. I'm familiar with C, not with Keil C51. Do you get a warning when you explicitly assign an `int` value to an `sbit`? – Keith Thompson Jun 18 '13 at 20:24
  • I've tried `( int x = 1; sbit y = P3^3; ... y = x; )` no warnings are triggered off. Maybe is like you said, and for some reason unknown to me, the behaviour is, in my opinion, strange. – Filippo Lauria Jun 18 '13 at 20:40
  • 1
    @KeithThompson: Assigning a value to an sbit changes the state of the pin referenced by the sbit. I have linked to the documentation of sbit in my answer. – Clifford Jun 19 '13 at 11:13