Download as pdf or txt
Download as pdf or txt
You are on page 1of 42

ECE 521:

Microprocessor System
CHAPTER 3: Microprocessor Programming in C
What we will learn in this section:

❑ Data types
❑ Bit-wise Operations in C
❑ Logic operation
❑ Data conversion
❑ Simple I/O programming in C language
Why Use C for Embedded
Programming?
 Portability : code can be retargeted to different processors Portability of a
language is mainly important when an application program must be
moved to other operating systems. Code developed in C is more portable
and user can compile it on other platforms with least modifications.
 Readability : C code is efficient, easy to understand, maintain and debug.
A program can be written in one machine and can be run on other
machines.
 Processor independent : C language is not specific to any
microprocessor/micro-controller or any system. It can work on various
hardware configuration. C doesn’t require same set of hardware to run a
program.
Data Types Sizes
3 methods to find out the exact sizes of the data
types:
1. Read the compiler manual.
2. Use pseudo function sizeof().
3. Use C99 data types.
ISO C99 integer data types and their
ranges
Data type Size Range Min Range Max
int8_t 1 byte -128 127
uint8_t 1 byte 0 to 255
int16_t 2 bytes -32,768 32,767
uint16_t 2 bytes 0 65,535
int32_t 4 bytes -2,147,483,648 2,147,483,647
uint32_t 4 bytes 0 4,294,967,295
int64_t 8 bytes -9,223,372,036,854,775,808 9,223,372,036,854,775,807
uint64_t 8 bytes 0 18,446,744,073,709,551,615
Data type examples
• Read bits from GPIOA (16 bits, non-numeric)
uint16_t n; n = GPIOA->IDR; //or: unsigned short n;
• Write TIM2 prescale value (16-bit unsigned)
uint16_t t; TIM2->PSC = t; //or: unsigned short t;
• Read 32-bit value from ADC (unsigned)
uint32_t a; a = ADC; //or: unsigned int a;
• System control value range [-1000…+1000]
int32_t ctrl; ctrl = (x + y)*z; //or: int ctrl;
• Loop counter for 100 program loops (unsigned)
uint8_t cnt; //or: unsigned char cnt;
for (cnt = 0; cnt < 20; cnt++) {
Bit-wise logical operators in C

A B AND OR EX-OR Invert


(A & B) (A | B) (A^B) ~B
0 0 0 0 0 1
0 1 0 1 1 0
1 0 0 1 1 1
1 1 1 1 0 0
Bitwise logical operators
Bitwise logical operators produce n-bit results of the
corresponding logical operation:

& (AND) | (OR) ^ (XOR) ~ (Complement)

C = A & B; A 0 1 1 0 0 1 1 0
(AND) B 1 0 1 1 0 0 1 1
C 0 0 1 0 0 0 1 0

C = A | B; A 0 1 1 0 0 1 0 0
(OR) B 0 0 0 1 0 0 0 0
C 0 1 1 1 0 1 0 0

C = A ^ B; A 0 1 1 0 0 1 0 0
(XOR) B 1 0 1 1 0 0 1 1
C 1 1 0 1 0 1 1 1

B = ~A; A 0 1 1 0 0 1 0 0
(COMPLEMENT) B 1 0 0 1 1 0 1 1
Setting ,Clearing (masking) and Testing
bits with bit-wise operators in C
 Anything ORed with a “1“ results in a “1”; anything ORed with a “0” results
in no change.
 Anything ANDed with a “1”results in no change; anything ANDed with a “0”
results in a zero.
 Anything EX-ORed with a “1” results in the complement; anything EX-ORed
with a “0” results in no change.
 When it is necessary to test a given bit to see if it is high or low, the unused
bits are masked and then the remaining data is tested.
Bit set/reset/complement/test
• Use a “mask” to select bit(s) to be altered
C = A & 0xFE; A a b c d e f g h
0xFE 1 1 1 1 1 1 1 0 Clear selected bit of A
C a b c d e f g 0

C = A & 0x01; A a b c d e f g h
0x01 0 0 0 0 0 0 0 1 Clear all but the selected bit of A
C 0 0 0 0 0 0 0 h

C = A | 0x01; A a b c d e f g h
0x01 0 0 0 0 0 0 0 1 Set selected bit of A
C a b c d e f g 1

C = A ^ 0x01; A a b c d e f g h
0x01 0 0 0 0 0 0 0 1 Complement selected bit of A
C a b c d e f g h’
Bit-wise shift operation in C
Operation Symbol Format of Shift Operation
Shift Right >> data >> number of bit-positions to be shifted right
Shift Left << data << number of bit-positions to be shifted left

Shift operators:
x >> y (right shift operand x by y bit positions)
x << y (left shift operand x by y bit positions)
Vacated bits are filled with 0’s.

B = A << 3; A 1 0 1 0 1 1 0 1
(Left shift 3 bits) B 0 1 1 0 1 0 0 0` filled with 0

B = A >> 2; A 1 0 1 1 0 1 0 1
(Right shift 2 bits) B 0 0 1 0 1 1 0 1
filled with 0
Compound Operators

Instruction Its equivalent using compound


operators
a = a + 6; a += 6;
a = a – 23; a –= 23;
y = y * z; y *= z;
z = z / 25; z /= 25;
w = w | 0x20; w |= 0x20;
v = v & mask; v &= mask;
m = m ^ togBits; m ^= togBits;
Bit-wise operations using compound
operators
 The majority of hardware access level code involves
▪ setting a bit or bits in a register,
▪ clearing a bit or bits in a register,
▪ toggling a bit or bits in a register,
▪ monitoring the status bits.
Shift operator: to generate mask

 One way to ease the generation of the mask is to use the shift left operator.
▪ To generate a mask with bit n set to 1, use the expression: 1 << n
 If more bits are to be set in the mask, they can be “or” together.
▪ To generate a mask with bit n and bit m set to 1, use the expression:
(1 << n) | (1 << m)
▪ Example:
register |= (1 << 6) | (1 << 1);
Setting the value in a multi-bit field

Example:
 register |= 1 << 30;
register &= ~(1 << 29);
register |= 1 << 28;

 register &= ~(7 << 28);


register |= 5 << 28;

 register = register & ~(7 << 28) | (5 << 28);


Basic C program structure

#include "STM32fxx.h" /* I/O port/register names/addresses for the STM32fxx microcontrollers */

/* Global variables – accessible by all functions */


int count, bob; //global (static) variables – placed in RAM

/* Function definitions*/
int function1(char x) { //parameter x passed to the function, function returns an integer value
int i,j; //local (automatic) variables – allocated to stack or registers
-- instructions to implement the function
}

/* Main program */
void main(void) {
unsigned char sw1; //local (automatic) variable (stack or registers)
int k; //local (automatic) variable (stack or registers)
Declare local variables
/* Initialization section */
-- instructions to initialize variables, I/O ports, devices, function registers Initialize variables/devices
/* Endless loop */
while (1) { //Can also use: for(;;) {
-- instructions to be repeated Body of the program
} /* repeat forever */
}
Memory Map of STMF446RE
Microcontroller “header file”

• Keil MDK-ARM provides a derivative-specific “header


file” for each microcontroller, which defines memory
addresses and symbolic labels for CPU and peripheral
function register addresses.
#include "STM32Fxx.h“ /* target uC information */

// GPIOA configuration/data register addresses are defined in STM32Fxx.h


void main(void) {
uint16_t PAval; //16-bit unsigned variable
GPIOA->MODER &= ~(0x00000003); // Set GPIOA pin PA0 as input
PAval = GPIOA->IDR; // Set PAval to 16-bits from GPIOA
for(;;) {} /* execute forever */
}
Constant/ Literal values
Types Format Description
Decimal int m, n; 16 bit signed numbers
m= 45;
n=-23;
Hexadecimal m=0x67F2; Preface value with 0x
n=-0x1234;
Octal m=0345; Preface value with zero
n=-056; Don’t use leading zeros on “decimal” values. They
will be interpreted as octal.
Character m=‘a’; ASCII value 0x61
n=‘\14’ ASCII value 14 is the return character
String (array) of unsigned char k[7]
characters strcpy(m, “hello\n”); k[0]=‘h’, k[1]=‘e’, k[2]=‘l’, k[3]=‘l’, k[4]=‘o’,
k[5]=13 or’\n’ (ASCII new line char)
k[6]=0 or ‘\0’ (null char – end of string)
Relational Operators
• Test relationship between two variables/expressions
Test TRUE condition Notes
1. Compiler uses signed or
(m == b) m equal to b Double =
unsigned comparison, in
(m != b) m not equal to b
accordance with data types
(m < b) m less than b 1
(m <= b) m less than or equal to b 1
Example:
(m > b) m greater than b 1
unsigned char a,b; int j,k;
(m >= b) m greater than or equal to b 1
if (a < b) – unsigned if (j > k) -
(m) m non-zero
signed
(1) always TRUE
(0) always FALSE
Boolean operators

• Boolean operators && (AND) and || (OR) produce


TRUE/FALSE results when testing multiple TRUE/FALSE
conditions
if ((n > 1) && (n < 5)) //test for n between 1 and 5
if ((c = ‘q’) || (c = ‘Q’)) //test c = lower or upper case Q
• Note the difference between Boolean operators &&, ||
and bitwise logical operators &, |
if ( k && m) //test if k and m both TRUE (non-zero values)
if ( k & m) //compute bitwise AND between m and n,
//then test whether the result is non-zero (TRUE)
Common error

• Note that == is a relational operator,


whereas = is an assignment operator.

if ( m == n) //tests equality of values of variables m and n


if (m = n) //assigns value of n to variable m, and then
//tests whether that value is TRUE (non-zero)
C control structures

• Control order in which instructions are executed


(program flow)
• Conditional execution
– Execute a set of statements if some condition is met
– Select one set of statements to be executed from
several options, depending on one or more conditions
• Iterative execution
– Repeated execution of a set of statements
• A specified number of times, or
• Until some condition is met, or
• While some condition is true
If Statement

if (condition) statement


▪ If condition is met, the statement is executed, otherwise, it is omitted

if (work == 1)
{
statement s1;
statement s2;
}
IF-THEN-ELSE structure
if (condition) statement1;
else statement2 ;
▪If the condition is met (true), the statement1 is executed,
otherwise (false), statement2 is executed

if (a == 0)
{
statement s1;
statement s2; Yes No
S1; a == 0 S3;
} S2; ? S4;
else
{
statement s3;
statement s4:
}
Multiple ELSE-IF structure
• Multi-way decision, with expressions
evaluated in a specified order
if (n == 1)
statement1; //do if n == 1
else if (n == 2)
statement2; //do if n == 2
else if (n == 3)
statement3; //do if n == 3
else
statement4; //do if any other value of n (none of the above)

Any “statement” above can be replaced with a set of


statements: {s1; s2; s3; …}
SWITCH statement
• Compact alternative to ELSE-IF structure, for multi-
way decision that tests one variable or expression
for a number of constant values

/* example equivalent to that on preceding slide */


switch ( n) { //n is the variable to be tested
case 0: statement1; //do if n == 0
case 1: statement2; // do if n == 1
case 2: statement3; // do if n == 2
default: statement4; //if for any other n value
}
Any “statement” above can be replaced with a set of
statements: {s1; s2; s3; …}
Switch Statement
 Switch is only test for integer and character values
and not of type float/double.

switch (integer or character expression) /* evaluated to


become const1… */
{ case const1 : statement1;
break; /*optional*/
case const2 : statement2;
break; /*optional*/

default : statement; }
WHILE loop structure

• Repeat a set of statements (a “loop”) as long


as some condition is met

while (a < b)
{ S1;
statement s1; a<b S2;
? Yes …
statement s2;
No “loop” through these
…. statements while a < b
}

Something must eventually cause a >= b, to exit the loop


WHILE example

No Wait for a 1 to be applied


PORTA
bit0 0
operation to bit 0 of GPIOA
and then read GPIOB
1

Read
PORTB

while ( (GPIOA->IDR & 0x0001) == 0) // test bit 0 of GPIOA


{} // do nothing & repeat if bit is 0
c = GPIOB->IDR; // read GPIOB after above bit = 1
DO-WHILE loop structure
• Repeat a set of statements (one “loop”)until some condition is met
do { statements } while (condition);
▪The loop is always executed once since the condition is
tested at the end of the loop.

do “loop” through
S1;
{ S2; these statements
statement s1; … until a < b
statement s2;
….
Yes
} a<b
while (a < b); ?
No
FOR loop structure

• Repeat a set of statements (one “loop”) while


some condition is met
– often a given # of iterations
Condition for
Operation(s) at end
Initialization(s) execution
of each loop

for (m = 0; m < 200; m++)


a<b Statement s1;
{ ? Statement s2;
Yes
statement s1;
statement s2; No

}
FOR loop structure

• FOR loop is a more compact form of the


WHILE loop structure
/* execute loop 200 times */ /* equivalent WHILE loop */
for (m = 0; m < 200; m++) m = 0; //initial action(s)
{ while (m < 200) //condition test
statement s1; {
statement s2; statement s1;
} statement s2;
m = m + 1; //end of loop action
}
FOR structure example

 /* Read 100 16-bit values from GPIOB into array C */


 /* Bit 0 of GPIOA (PA0) is 1 if data is ready, and 0 otherwise */ uint16_t c[100];
 uint16_tk;

 for (k = 0; k < 200; k++) {


 while ((GPIOA->IDR & 0x01) == 0) //repeat until PA0 = 1

{} //do nothing if PA0 = 0


c[k] = GPIOB->IDR; //read data from PB[15:0]
}
FOR structure example

/* Nested FOR loops to create a time delay */

for (i = 0; i < 100; i++) { //do outer loop 100 times


for (j = 0; j < 1000; j++) { //do inner loop 1000 times
} //do “nothing” in inner loop
}
Switching ON LED

Eg. Write a program in C language that will turn on Green LED


(LD2) on the STM32F446RE board.
START

Enable Port A clock

Configure PA5 as
output

Turn on LED
Switching ON LED
START

Eg. Write a program in C language that will toggle the


green LED (LD2) on STM32F446RE Nucleo64 board at 16Hz Enable Port A clock

Configure PA5 as
output

Turn on LED

Delay 0.5s
User LED connection for STM32F446RE Nucleo board

Turn OFF LED

Delay 0.5s
TOOGLE OR BLINKING LED
Reading a Switch Condition

Eg. Write a program in C language that will turn on Green LED (LD2) on the
STM32F446RE board when the switch B1 is pressed (pull up register).

PA5
Reading a Switch Condition

Write a program in C language that will turn on Green LED (LD2) on


the STM32F446RE board when the switch B1 is pressed.

START

Read the status of


Enable Port A clock the switch

Turn off LED


Enable Port C clock
Is the N
switch
pressed
Configure PA5 as ?
output
Y

Turn on LED
Configure PC13 as
input
Reading a Switch Condition

You might also like