Файл: C Programming for microcontrollers (Joe Pardue, 2005).pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 13.06.2025

Просмотров: 2458

Скачиваний: 2

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

Chapter 4: C Types, Operators, and Expressions

Which will scroll by so fast you won’t see it, so you’ll assume the compile was good. Notice how clear (NOT) this warning was? Most complier warnings are even more cryptic. Not all compilers will flag this error with a warning. It is a very easy mistake to make, and you will feel really dumb after an hour of debugging, looking for something obscure, only to find a lousy missing ‘=’ character. I do this all the time.

Note: Some of these operators may seem strange at this point, but they are explained fully in later sections. Then they’ll seem really strange.

Table 1: Arithmetic Operators

Operator

Name

Example

Defined

*

Multiplication

x*y

Multiply x times y

/

Division

x/y

Divide x by y

%

Modulo

x%y

Provide the remainder of x divided by y

+

Addition

x+y

Add x and y

-

Subtraction

x-y

Subtract y from x

++

Increment

x++

Increment x after using it

--

Decrement

--x

Decrement x before using it

-

Negation

-x

Multiply x by –1

+

Unary Plus

+x

Show x is positive (not really needed)

Table 2: Data Access and Size Operators

Operator

Name

Example

Defined

[]

Array element

x[6]

Seventh element of array x

.

Member selection

PORTD.2

Bit 2 of Port D

->

Member selection

pStruct->x

Member x of the structure pointed to

by pStruct

*

Indirection

*p

Contents of memory located at

address p

&

Address of

&x

Address of the variable x

51


Chapter 4: C Types, Operators, and Expressions

Table 3: Miscellaneous Operators

Operator

Name

Example

Defined

()

Function

wait(10)

call wait with an argument of 10

(type)

Type cast

(double)x

x converted to a double

?:

Conditional

x?y:z

If x is not 0 evaluate y, otherwise evaluate

z

,

Sequential

x++,y++

Increment x first, then increment y

evaluation

Relational and Logical Operators

Table 4: Logical and Relational Operators

Operator

Name

Example

Defined

>

Greater than

x>y

1 if x is greater than y, otherwise 0

>=

Greater than

x>=y

1 if x is greater than or equal to y,

or equal to

otherwise 0

<

Less than

x<y

1 if x is less than y, otherwise 0

<=

Less than or

x<=y

1 if x is less than or equal to y, otherwise

equal to

0

==

Equal to

x==y

1 if x equals y, otherwise 0

!=

Not equal to

x!=y

1 if x is not equal to y, otherwise 0

!

Logical NOT

!x

1 if x is 0, otherwise 0

&&

Logical AND

x&&y

0 if either x or y is 0, otherwise 1

||

Logical OR

x||y

0 if both x and y are 0, otherwise 1

52


Chapter 4: C Types, Operators, and Expressions

Bitwise Operators

Table 5: Bitwise Operators

Operator

Name

Example

Defined

~

Bitwise complement

~x

Changes 1 bits to 0 and 0 bits to 1

NOT

&

Bitwise AND

x&y

Bitwise AND of x and y

|

Bitwise OR

x|y

Bitwise OR of x and y

^

Bitwise exclusive OR

x^y

Bitwise XOR of x and y

<<

Left shift

x<<2

Bits in x shifted left 2 bit

positions

>>

Right shift

x>>3

Bits in x shifted right 3 bit

positions

Bitwise operators are critically important in microcontroller software. They allow us to do many things in C that can be directly and efficiently translated into microcontroller machine operations. Keep in mind that these operators work on bits but are similar enough to the logical operators that you will get confused. Let’s look at the truth tables for &, |, and ^:

AND

OR

XOR

0 & 0 = 0

0 | 0 = 0

0 ^ 0 = 0

0 & 1 = 0

0 | 1 = 1

0 ^ 1 = 1

1 & 0 = 0

1 | 0 = 1

1 ^ 0 = 1

1 & 1 = 1

1 | 1 = 1

1 ^ 1 = 0

Let’s create a variable, myByte and do some bitwise operations on it:

unsigned char myByte = 0;

We can set bit 3 (numbering from the right starting with 0):

myByte = myByte | 0x08;

To see what’s happening Let’s look at these in binary:

myByte = 00000000 = 0x00

53


Chapter 4: C Types, Operators, and Expressions

0x08 = 00001000 = 0x08

------------------------

OR = 00001000 = 0x08

Suppose myByte = 0xFF:

myByte = 11111111 = 0xFF 0x08 = 00001000 = 0x00

------------------------

OR = 11111111 = 0xFF

Or maybe myByte = 0x55:

myByte = 01010101 = 0x55 0x08 = 00001000 = 0x08

-----------------

OR = 01011101 = 0x5D

This all shows that only the 3rd bit of myByte is affected by the OR operation, since it is the only bit equal to 1 in 0x08.

Now let’s do the same thing with the & operator:

unsigned char myByte = 0;

We can set bit 3 with:

myByte = myByte & 0x08;

To see what’s happening Let’s look at these in binary:

myByte = 00000000 = 0x00 0x08 = 00001000 = 0x08

------------------------

AND = 00000000

Suppose myByte = 0xFF:

myByte = 11111111 = 0xFF 0x08 = 00001000 = 0x08

------------------------

54

Chapter 4: C Types, Operators, and Expressions

AND = 00001000

Or maybe myByte = 0x55:

myByte = 01010101 = 0x55 0x08 = 00001000 = 0x08

------------------------

AND = 00000000 = 0x00

And maybe myByte = 0xAA:

myByte = 10101011 = 0xAA 0x08 = 00001000 = 0x08

------------------------

AND = 00001000 = 0x08

In each of the above cases we are only dealing with a single bit, but we might be interested in any or all of the bits. One of the most important features of using masks with bitwise operators is that it allows us to set or clear a specific bit or set of bits in a byte without knowing or affecting the bits we aren’t interested in. For example, suppose we are only interested in bits 0, 2, and 6. Let’s set bit 6, regardless of its present value, then clear bits 0 and 2, also regardless of their present value and, here’s the trick, leave bits 1, 2, 4, 5, and 7 as they were when we began. Let’s have myByte starting equal to the secret to life the universe and everything, which according to Douglas Adams is 42, but remember that the start value doesn’t matter to us since we are going to force 3 bits to values regardless of the start value.

NOTE:

myByte = myByte | 0x08; is the same as

myByte |= 0x08; which we will use from no on.

At the beginning myByte is equal to 42 = 0x2B = 00101011. We set bit 6 with:

myByte |= 0x40;

which does the following:

55

Chapter 4: C Types, Operators, and Expressions

myByte = 00101011 = 0x2B 0x40 = 01000000 = 0x40

------------------------

AND = 01101011 = 0x6B

Next we want to clear bits 0 and 2:

myByte &= 0xFA;

which does the following:

myByte = 01101011 = 0x6B 0x40 = 11111010 = 0xFA

------------------------

AND = 01101010 = 0x6A

So in summary we set bits with ‘|’ and clear bits with ‘&’.

The Butterfly Software has a clever snippet in LCD_driver.c where the ‘&’ and ‘~’ operators are used to convert a lowercase letter to a capital:

// c is a letter

// Convert to upper case

if (c >= 'a')

c &= ~0x20;

// if necessary

This statement first checks to see if the character c is greater than or equal to ‘a’ and uses the convenient fact that in ASCII the letters are sequential with the capitals beginning at 0x41 and the lowercase beginning at 0x61. So if the character is >= 0x61 then it is lowercase and we can derive the uppercase version by subtracting 0x20. So why do we use ‘c &= ~0x20’ instead of subtracting as in ‘c -= 0x20’? Well, it is more efficient for the machine to take the inverse of the minuend and then AND it with the subtrahend (this by the way, is the first time since grammar school that I’ve actually used minuend and subtrahend, I’m amazed that these terms actually stuck. Maybe it was the teachers steely glare and the dangerous looking pointer she held.) Let’s look at it shall we?

0x20 = 00100000 ~0x20 = 11011111

56