ELEC3730 Embedded Systems Lecture 7: C for Embedded Programming
Bitwise Operations Setting,Inverting,Toggling,Clearing,Extracting + Inserting bits Structures Unions
ELEC3730 Callaghan Campus
Boolean and Binary Operators
Operation AND OR NOT XOR LEFT SHIFT RIGHT SHIFT Boolean Operator && || ! N/A N/A N/A Bitwise Operator & | ~ ^ << >>
Boolean operators used to for conditional expressions (eg: if statement) C does not contain a Boolean data type. Boolean operators yield results of type int, with true and false represented by 1 and 0. Any numeric data type may be used as a Boolean operand. Zero is interpreted as false; any non-zero value is interpreted as true. Bitwise operators operate on individual bit positions within the operands; The result in one bit position is independent of all the other bit positions.
Bitwise operators are used to manipulate bits.
ELEC3730 Callaghan Campus
Boolean versus bitwise operations
(5 || !3) && 6 = (true OR (NOT true)) AND true = (true OR false) AND true = (true) AND true = true =1
(5 | ~3) & 6 = (00..0101 OR ~00..0011) AND 00..0110 = (00..0101 OR 11..1100) AND 00..0110 = (11..1101) AND 00..0110 = 00..0100 =4
ELEC3730 Callaghan Campus
Bitwise-AND: Forces 0 0s where they occur in mask
m p m AND p Interpretation If bit m of the mask is 0, 0 0 bit p is cleared to 0 in 0 0 1 0 the result. 1 0 0 1 1 p
If bit m of the mask is 1, bit p is passed through to the result unchanged.
ELEC3730 Callaghan Campus
Bitwise-OR: Forces 1 1s where they occur in mask
m p m OR p 0 0 0 p 1 1 1 0 1 1 1 1
Interpretation
If bit m of the mask is 0, bit p is passed through to the result unchanged. If bit m of the mask is 1, bit p is set to 1 in the result.
ELEC3730 Callaghan Campus
Bitwise-XOR: Forces bit flip where 1 1s occur in mask
m p m XOR p Interpretation If bit m of the mask is 0, 0 0 bit p is passed through 0 p 1 1 to the result unchanged. If bit m of the mask is 1, 0 1 bit p is passed through 1 ~p 1 0 to the result inverted.
ELEC3730 Callaghan Campus
Testing Bits
Form a mask with 1 in the bit position of interest; Bitwise AND the mask with the operand. The result is non-zero if and only if the bit of interest was 1:
if ((bits & 64) != 0) 0x64) /* check to see if bit 6 is set */ /* check to see if bit 6 is set * /* check to see if bit 6 is set */ Same as: if (bits &
Same as if (bits & (1 << 6))
if ((bits & 64) != 0)
/* check to see if bit 6 is set */
b7b6b5b4b3b2b1b0
&
01000000
ELEC3730 Callaghan Campus
0b6000000
7
Setting bits, Inverting bits
Setting a bit to 1 is easily accomplished with the bitwise-OR operator:
bits = bits | (1 << 7) ; /* sets bit 7 */
b7b6b5b4b3b 2b 1b 0
10000000
1b6b5b4b3b2b1b 0
This would usually be written more succinctly as:
bits |= (1 << 7) ; /* sets bit 7 */
Inverting (toggling) is accomplished with bitwise-XOR: bits ^= (1 << 6) ; /* flips bit 6 */
ELEC3730 Callaghan Campus
Clearing Bits
Clearing a bit to 0 is accomplished with the bitwise-AND operator:
bits &= ~(1 << 7) ; /* clears bit 7 */ (1 << 7) ~(1 << 7) 10000000 01111111
Mask must be as wide as the operand! if bits is a 32-bit data type, the assignment must be 32-bit:
bits &= ~(1L << 7) ;
/* clears bit 7 */
ELEC3730 Callaghan Campus
Extracting Bits
Bits 15 - 11
Bits 10 - 5
Bits 4 - 0
time time >> 5 (time >> 5) & 0x3F
15
Hours
Bits 15 - 11
Minutes
Bits 10 - 6
Seconds 2
Bits 5 - 0
?????
Bits 15 - 11
Hours
Bits 10 - 6
Minutes
Bits 5 - 0
00000
00000 Minutes
Minutes
0
minutes = (time >> 5) & 0x3F
ELEC3730 Callaghan Campus
10
Inserting Bits
Bits 15 - 11
Bits 10 - 5
Bits 4 - 0
oldtime newtime = oldtime & ~(0x3F << 5) newtime |= (newmins & 0x3F) << 5
Hours
Bits 15 - 11
Old Minutes
Bits 10 - 5
Seconds 2
Bits 4 - 0
Hours
Bits 15 - 11
000000
Bits 10 - 5
Seconds 2
Bits 4 - 0
Hours
New Minutes
Seconds 2
ELEC3730 Callaghan Campus
11
Structures in C
#include<stdio.h> struct{ float x; int y; char c; } brett; int main(void) { brett.x=2.345; brett.y=5; brett.c='b'; printf("x,y,c in brett is %f,%d,%c\n",brett.x,brett.y,brett.c); }
ELEC3730 Callaghan Campus
12
Structures in C - Use typedef to define
#include<stdio.h> typedef struct{ float x; int y; char c; } elec3730; int main(void) { elec3730 brett; brett.x=2.345; brett.y=5; brett.c='b'; printf("x,y,c in brett is %f,%d,%c\n",brett.x,brett.y,brett.c); }
ELEC3730 Callaghan Campus
13
Pointers to Structures
#include<stdio.h> #include<stdlib.h> typedef struct{ float x; int y; char c; } elec3730; int main(void) { elec3730 *brett; brett=malloc(sizeof(elec3730)); if (brett != NULL) { (*brett).x=2.345; brett->y=5; brett->c='b'; printf("x,y,c in brett is %f,%d,%c\n",brett->x,(*brett).y,(*brett).c); free(brett); } } ELEC3730 Callaghan Campus 14
Testing Keyboard Flags Using Bitwise Operators.
#define #define FALSE TRUE 0 1 BOOL ; BOOL get_keys(KEYS *) ;
typedef unsigned char typedef struct { BOOL right_shift BOOL left_shift BOOL ctrl ; BOOL alt ; BOOL left_ctrl; BOOL left_alt ; } KEYS ;
; ;
void main(){ KEYS kybd ; do{ /* wait for both shift keys*/ get_keys(&kybd) } while (!kybd.left_shift || !kybd.right_shift) ; }
void get_keys(KEYS { int hit, *addr; *kybd)
addr=0x417; hit=*addr; kybd->right_shift kybd->left_shift kybd->ctrl kybd->alt kybd->left_alt kybd->left_ctrl } = = = = = = (hit (hit (hit (hit (hit (hit & & & & & & (1 (1 (1 (1 (1 (1 << << << << << << 0)) 1)) 2)) 3)) 9)) 8)) != != != != != != 0 0 0 0 0 0 ; ; ; ; ; ;
ELEC3730 Callaghan Campus
15
Automatic Insertion/Extraction Using Structure Bit Fields
struct { unsigned
seconds minutes hours
:5 , :6 , :5 ;
/* secs divided by 2 */
} time ; time.hours = 13 ; time.minutes = 34 ; time.seconds = 18 / 2 ;
Leave the insertion (or extraction) problems to the compiler!
ELEC3730 Callaghan Campus
16
Keyboard Revisited - Using Structure Bit Fields
#define #define FALSE TRUE 0 1 BOOL ; BOOL get_keys(KEYS *) ;
typedef unsigned char typedef struct { unsigned right_shift left_shift ctrl alt left_ctrl left_alt } KYBD_BITS;
:1, :1, :1, :1, :4, :1, :2;
void main(){ KEYS kybd ; do{ /* wait for both shift keys*/ get_keys(&kybd) } while (!kybd.left_shift || !kybd.right_shift) ; }
void get_keys(KEYS { int hit, *addr; KYBD_BITS *bits ; *kybd)
addr=0x417; hit=*addr; bits = (KYBD_BITS *) &hit ; kybd->right_shift = bits->right_shift kybd->left_shift = bits->left_shift kybd->ctrl = bits->ctrl kybd->alt = bits->alt kybd->left_alt = bits->left_alt kybd->left_ctrl = bits->left_ctrl } != != != != != != 0 0 0 0 0 0 ; ; ; ; ; ;
ELEC3730 Callaghan Campus
17
Variant Access with Pointers, Casts, & Subscripting
Given an address:
! !
Cast it as a pointer to data of the desired type, Then dereference the pointer by subscripting. Read or write various parts of an object named operand using:
Without knowing the data type used in its declaration:
!
((char *) &operand)[k]
ELEC3730 Callaghan Campus
18
Keyboard Revisited - Using Pointers+Cast+Subscripting
#define #define FALSE TRUE 0 1 BOOL ; BOOL get_keys(KEYS *) ;
typedef unsigned char typedef struct { char lo ; char hi ; short both ; } KEYS;
void main(){ KEYS kybd ; do{ /* wait for both shift keys*/ get_keys(&kybd) } while (!kybd.left_shift || !kybd.right_shift) ; }
void get_keys(KEYS { int hit, *addr; *kybd)
addr=0x417; hit=*addr; kybd->both = ((short *) &hit)[0] ; kybd->lo = ((char *) &hit)[0] ; kybd->hi = ((char *) &hit)[1] ; }
ELEC3730 Callaghan Campus
19
Variant Access with Unions
union { 31 0 unsigned long dd ; dd unsigned short dw[2] ; dw[1] dw[0] unsigned char db[4] ; db[3] db[2] db[1] db[0] 31 24 23 16 15 87 0 };
ELEC3730 Callaghan Campus
20
Keyboard Revisited - Using Unions
#define #define FALSE TRUE 0 1 BOOL ; BOOL get_keys(KEYS *) ;
typedef unsigned char typedef union { char b[2] ; short int w ; } VARIANT ;
void main(){ KEYS kybd ; do{ /* wait for both shift keys*/ get_keys(&kybd) } while (!kybd.left_shift || !kybd.right_shift) ; }
void get_keys(KEYS { VARIANT *hit; hit=0x417; kybd->both = hit->w ; kybd->lo = hit->b[0] ; kybd->hi = hit->b[1] ; } *kybd)
ELEC3730 Callaghan Campus
21