Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GPIO button pressing in C

Tags:

c

embedded

I'm relatively new in the embedded world, so I may be a little newbie asking this.

I'm having trouble to understand the syntax of an example program in C that checks if a button is pressed and then turning a LED on if so. I'm using a STM32F207VCT6 (Cortex-M3) microcontroller.

The part of the program that I'm having trouble to understand is the following:

if(!(GPIOA->IDR & (1<<4)))
  Key=1;

Port 4 from GPIOA is set to be an input with pull-up register. The signal from the button goes to GND once it's pressed. IDR is the input data register.

So my question is:

I don't understand in this code why the NOT symbol, !, inside the if statement is needed. And I do not know what comparison is being made inside the if, since there is no sign of equal. Can someone help me with that?

PS: I already know that (1<<4) is the bit-wise operation for left shifting the bit 1 four times.

like image 824
Gui W. Eckert Avatar asked Dec 29 '25 16:12

Gui W. Eckert


2 Answers

There are 16 pins per port in the STM32F207VCT6. This operation is trying to determine the state of a single pin, number 4, of port A. Let's expand each part to better understand what is going on.

We start with the expression:

if(!(GPIOA->IDR & (1<<4)))

We're working with a 16-bit number to account for the 16 pins. Expanding this we get:

if(!(GPIOA->IDR & ((0000 0000 0000 0001) << 4)))

You already know that << is a bitwise left shift. Applying this we get:

if(!(GPIOA->IDR & (0000 0000 0001 0000)))

Expanding the IDR, I will use X's for bits that we don't care about and a ? for the unknown bit we are testing for:

if(!((XXXX XXXX XXX? XXXX) & (0000 0000 0001 0000)))

Next we have a & which is the bitwise AND operator. If you remember your AND truth table:

&   0 1
    - -
0 | 0 0
1 | 0 1

So we have the operation:

  XXXX XXXX XXX? XXXX
& 0000 0000 0001 0000
---------------------
  0000 0000 000? 0000

If Bit 4 in Port A is a 0, the the result will be 0000 0000 0000 0000. If Bit 4 in Port A is a 1, the the result will be 0000 0000 0001 0000.

If the switch is pressed, the input will be pulled to GND and Bit 4 will be set to 0. If the switch is unpressed, then the internal pull-up will pull the input high and Bit 4 will be set to 1.

So we have two possibilities:

//Button is pressed
if(!(0000 0000 0000 0000))

Or:

//Button is not pressed
if(!(0000 0000 0001 0000))

Now it's important to understand that ! is the Logical NOT operator. Which inverts true and false in conditional statements. It is also important to understand that in the C language:

Logical operators (&&, ||, !, etc.) and condition-testing statements (if, while) assume that zero is false and all other values are true.

Emphasis mine

So what we really have is:

//Button is pressed
if(!(false))

Or:

//Button is not pressed
if(!(true))

Applying the NOT:

//Button is pressed
if(true)
    Key=1;

Or:

//Button is not pressed
if(false)
    Key=1;
like image 124
embedded.kyle Avatar answered Dec 31 '25 09:12

embedded.kyle


if(!(GPIOA->IDR & (1<<4))) Key=1;

is equivalent to

if((GPIOA->IDR & (1<<4)) == 0) Key=1;

In C, !E is equivalent to E == 0.

So here basically, Key = 1; statement is executed if the value of bit 4 of GPIOA->IDR is 0.

like image 32
ouah Avatar answered Dec 31 '25 08:12

ouah