Embedded C Lab (21EC481)
Embedded C Lab (21EC481)
List of Experiments
Conduct the following experiments by writing C Program using Keil microvision simulator (any 8051
microcontroller can be chosen as the target).
void multiply(unsigned int num1, unsigned int num2, unsigned long *result) {
*result = (unsigned long)num1 * num2;
}
int main() {
unsigned int num1 = 0xA3C1; // Binary: 1101010110101010
unsigned int num2 = 0xB3B4; // Binary: 1010110011101010
unsigned long result;
while (1) {
}
}
EXPLANATION:
#include <reg51.h>:This is a basic template for an 8051 microcontroller program using the reg51.h header file.
The reg51.h file is specific to the Keil C51 compiler, which is commonly used for programming the 8051
microcontroller
It provides definitions and constants for the 8051 microcontroller's registers and special function registers
(SFRs). Including the reg51.h header file allows you to directly access and manipulate the 8051's hardware
resources.
The multiply function is defined. It takes three arguments: num1 and num2 (unsigned integers) representing
the numbers to be multiplied, and result (a pointer to an unsigned long integer of 4 bytes) to store the result of
the multiplication.
An argument refers to values that are passed within a function when the calling of a function takes place
In computer programming the positive number will be represented as unsigned number and to represent
negative value we must assigned as signed number. The signed number has both positive and negative
numbers.
In the C programming language, the main function serves as the entry point for the program execution. The
main function can have two different return types: int and void.
int main() indicates that the main function should return an integer value to the operating system upon program
termination where as void main() function does not return any value to the operating system. Here Since the
program does not interact with the operating system and does not require reporting any success or error codes,
using void return type for main is acceptable.
unsigned int num1 = 0xA3C1;: This line declares an unsigned integer variable num1 and initializes it with the
hexadecimal value 0xA3C1, which is equivalent to the binary value 1101010110101010.unsigned int num2 =
0xB3B4;: This line declares an unsigned integer variable num2 and initializes it with the hexadecimal value
0xB3B4, which is equivalent to the binary value 1010110011101010.
unsigned long result;: This line declares an unsigned long variable result to store the 32-bit result of the
multiplication.
multiply(num1, num2, &result);: This line calls the function multiply with the arguments num1, num2, and the
address of result using the reference operator &. The function multiplies num1 and num2 and stores the 32-bit
result in the memory location pointed to by result.
*((unsigned long*)0x18) = result;: This line stores the 32-bit result in internal RAM starting at address
0x2000.
while (1) { }: This is an infinite loop that keeps the microcontroller running after the multiplication and storage
of the result.
OUTPUT:
#include <reg51.h>
void main()
{
Unsigned int sum = 0; // initialize sum to 0
Unsigned int i;
EXPLANATION:
#include <reg51.h>: This line includes the header file reg51.h which contains the definitions for the 8051
microcontroller.
Unsigned int sum = 0;: This line declares an unsigned integer variable sum and initializes it with the value 0.
This variable will be used to store the sum of the numbers.
Unsigned int i;: This line declares an unsigned integer variable i which will be used as a loop variable in the for
loop.
for(i=1; i<=10; i++): This line starts a for loop that initializes i to 1, continues the loop as long as i is less than
or equal to 10, and increments i by 1 in each iteration. This loop will iterate 10 times.
P1 = sum;: This line assigns the value of sum to the output port P1. It assumes that P1 is a hardware register or
port that can be used to display or output the value of sum
OUTPUT:
1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = 55
In hexadecimal 0X37h
PROGRAM .3
// Calculate factorial
for(i=1; i<=n; i++)
{
result = result * i;
// Display result
P1=result;
EXPLANATION:
#include <reg51.h>: This line includes the header file reg51.h, which contains the definitions for the 8051
microcontroller.
unsigned char n = 5;: This line declares an unsigned char ( unsigned char is represented by 1 byte i.e. 8 bits)
variable n and initializes it with the value 5. This variable represents the number for which the factorial will be
calculated.
unsigned char i;: This line declares an unsigned char variable i which will serve as a loop variable in the for
loop.
unsigned char result = 1;: This line declares an unsigned char variable result and initializes it with the value 1.
This variable will store the factorial result.
for(i=1; i<=n; i++): This line starts a for loop that initializes i to 1, continues the loop as long as i is less than or
equal to n, and increments i by 1 in each iteration. This loop will calculate the factorial of n.
Inside the for loop:
result = result * i;: This line multiplies the current value of result with the current value of i and assigns
the result back to result. This accumulates the factorial of n in result variable.
P1 = result;: This line assigns the value of result to the output port P1. It assumes that P1 is a hardware register
or port that can be used to display or output the value of result.
while(1): This line starts an infinite loop, ensuring that the program does not terminate and continues to display
or perform other operations based on the result.
(These lines are used only whenever we want to store the result in memory location)
*((unsigned char*)0x18) = result; stores the value of result in the memory location specified by the address
0x18
OUTPUT:
Factorial of 5=5*4*3*2*1=120
In hexadecimal =0x78h
Program 4
4. Write a 8051 C program to add an array of 16 bit numbers and store the 32 bit result in
internal RAM
#include <reg51.h>
#define ARRAY_SIZE 4
void main() {
unsigned int array[ARRAY_SIZE] = {0x1234, 0x5678, 0x9ABC, 0xDEFF};
unsigned long result = 0;
unsigned char i;
}
}
EXPLANATION:
The program starts by including the reg51.h header file, which contains definitions for the 8051
microcontroller.
A constant ARRAY_SIZE is defined with a value of 4.
An unsigned integer array array of size ARRAY_SIZE is defined with initial values {0x1234, 0x5678,
0x9ABC, 0xDEFF}.
A for loop is used to iterate through the elements of the array from index 0 to 3 (which is ARRAY_SIZE-1). In
each iteration, the current element of the array is added to result.
After the for loop, the 32-bit result is stored in internal RAM starting at memory address 0x18 using a pointer.
RESULT:
5. Write a 8051 C program to find the square of a number (1 to 10) using look-up table.
#include <reg51.h>
void main() {
unsigned char num = 3; // The number whose square we want to find
unsigned char index = num - 1; // Index into the lookup table
EXPLANATION:
The program includes the header file reg51.h, which is specific to the 8051 microcontroller and provides
definitions for its registers and other hardware-related functions.
The program defines a global array named lookup_table without specifying the size explicitly. The size is
automatically determined based on the number of elements initialized within the braces. In this case, the array
has 10 elements, representing the squares of numbers from 1 to 10.
The main() function is declared, which is the entry point of the program.
Inside the main() function, an unsigned char variable num is declared and initialized with a value of 3. This
variable represents the number whose square is to be found.
Another unsigned char variable index is declared and initialized with the value of num - 1. Since the lookup
table array is 0-based, subtracting 1 from num gives the corresponding index in the lookup table.
An unsigned char variable square is declared and initialized with the value obtained by looking up the index in
the lookup_table. This retrieves the square of the num from the lookup table.
The program then assigns the value of square to the P1 register. In the 8051 microcontroller, P1 is one of the
general-purpose I/O ports. By assigning a value to P1, the result of the square calculation is output to the
corresponding pins of the microcontroller.
RESULT:
Square of 3 = 3*3 = 9
In hexadecimal= 0x09h
PROGRAM 6
void main() {
unsigned char i;
unsigned char largest, smallest;
unsigned char numbers[ARRAY_SIZE] = {4, 12, 6, 8, 1, 9, 15, 7, 10, 3, 5, 11, 13, 2, 14, 16, 18, 20, 17, 22,
19, 23, 21, 24, 27, 25, 28, 30, 26, 31, 29, 35};
largest = numbers[0];
smallest = numbers[0];
EXPLANATION:
The program includes the header file "reg51.h" which provides definitions for the 8051 microcontroller.
The constant ARRAY_SIZE is defined with a value of 32. This constant determines the size of the array
numbers.
largest and smallest are unsigned char variables used to store the largest and smallest numbers, respectively.
numbers is an array of unsigned char elements with a size of ARRAY_SIZE. It contains a predefined set of
numbers.
The first element of numbers (index 0) is assigned to both largest and smallest variables as the initial values.
A for loop is used to iterate through the elements of the numbers array, starting from index 1 (since index 0
was already assigned to largest and smallest).
Inside the loop, the program checks if the current element numbers[i] is greater than the current value of
largest. If it is, the value of largest is updated to the current element.
Similarly, the program checks if the current element numbers[i] is smaller than the current value of smallest. If
it is, the value of smallest is updated to the current element.
Once the loop finishes iterating through all elements of the array, the largest and smallest numbers have been
determined.
The program then assigns the value of largest to the Port 1 register (P1) and the value of smallest to the Port 2
register (P2).
RESULT:
#include <REG51.h>
void main() {
unsigned long series[] = { 0XFFF45678,0X8734ABD3, 0X1654DB58, 0XAB3423D8 }; // example series of
32-bit numbers
unsigned char len = sizeof(series) / sizeof(unsigned long);
unsigned char i;
sortAscending(series, len);
EXPLANATION:
The program includes the header file "REG51.h" which provides definitions for the 8051 microcontroller.
The program defines a function sortAscending that takes an unsigned long array (arr) and its length (len) as
parameters.
This function is responsible for sorting the array in ascending order.
The function uses nested for loops to implement the selection sort algorithm. The outer loop iterates from i = 0
to i < len - 1, and the inner loop iterates from j = i + 1 to j < len.
Inside the nested loops, the function compares the value of arr[j] with arr[i]. If arr[j] is smaller than arr[i],
the values of arr[i] and arr[j] are swapped using the temporary variable temp.
Inside main(), the program declares an array series containing four 32-bit numbers as an example.
The program calculates the length of the series array by dividing the size of the array by the size of an
unsigned long.
The program calls the sortAscending function, passing the series array and its length as arguments, to sort the
array in ascending order.
After sorting, the program stores the sorted elements in internal memory locations starting from address 0x100.
It uses a for loop to iterate through the sorted series array and assigns each element to the corresponding
memory location using a typecast.
RESULT:
RESULT:
8. Write a 8051 C program to count the number of ones and zeros in two consecutive
memory locations.
#include<reg51.h>
void main() {
unsigned char count_ones = 0;
unsigned char count_zeros = 0;
unsigned char memory_location_1 = 0xAA; // Example value for memory location 1
unsigned char memory_location_2 = 0x55; // Example value for memory location 2
unsigned char i;
count_ones = 0;
count_zeros = 0;
EXPLANATION:
The program includes the header file "reg51.h" which provides definitions for the 8051 microcontroller.
A for loop is used to iterate through the 8 bits of memory_location_1 and count the number of ones and zeros.
Inside the loop, the program uses bitwise operations to check each bit of memory_location_1.
If the current bit is 1 (using the bitwise AND operator &), count_ones is incremented.
Otherwise, if the current bit is 0, count_zeros is incremented.
The program stores the count of ones in the higher nibble (bits 7-4) and the count of zeros in the lower nibble
(bits 3-0) of the Port 1 register (P1).
It does this by shifting the value of count_ones by 4 bits to the left and performing a bitwise OR operation (|)
with count_zeros. The result is assigned to P1.
The program resets count_ones and count_zeros to 0 for counting in the next memory location.
Another for loop is used to iterate through the 8 bits of memory_location_2 and count the number of ones and
zeros, similar to the previous loop.
The program stores the count of ones in the higher nibble and the count of zeros in the lower nibble of the Port
2 register (P2).
RESULT:
Memory_location_1 = 0xAAh
Memory_location_1 = 0x19h
9. Write a 8051 C program to scan a series of 32 bit numbers to find how many are
negative.
#include <reg51.h>
void main() {
unsigned long int numbers[] = {0x80000000, 0x12345678, 0x2FFFFFFF, 0x00000000, 0x87654321};
unsigned char i, negativeCount;
EXPLANATION:
The program starts by defining an array of unsigned long integers named numbers with five elements, each
containing a 32-bit hexadecimal number.
Two variables are declared: an unsigned char variable i, which will be used as a counter in the for loop, and an
unsigned char variable negativeCount, which will store the number of negative numbers in the array.
The for loop scans through each element in the numbers array using the counter variable i.
Inside the loop, the value of the current element of numbers is assigned to a new variable number.
The if statement checks if the most significant bit (MSB) of number is set to 1, indicating that it is a negative
number. This is done by performing a bitwise AND operation between number and the hexadecimal value
0x80000000, which has only its MSB set to 1.
After the loop completes, the negativeCount variable contains the total number of negative numbers in the
array.
The program then stores the value of negativeCount in the memory location 0x18, which is done by casting the
address to an unsigned char pointer and dereferencing it to assign the value.
RESULT:
If msb = 1 number is negative
If msb = 0 number is positive
For example,
1.Hexadecimal number = 0x80000000
Its binary representation = 1000000000000000000000000000000
Since msb = 1, it’s a negative number
10. Wite a 8051 c program to display the message “Hello World” (either in simulation
mode or interface LCD display)
printf("Hello World\n");
}
EXPLANATION:
`#include<reg51.h>`: This line includes the header file `reg51.h`, which contains special function register
declarations for the 8051 microcontroller. The 8051 is a popular microcontroller used in embedded systems.
`#include<stdio.h>`: This line includes the standard input/output library header file `stdio.h`, which contains
prototype declarations for input/output functions like `printf`.
`void main(void)`: This is the main function of the program, the entry point for execution. In C, the `main`
function is where the program starts executing.
`#ifndef MONITORS1`: This is a preprocessor directive. It checks if the macro `MONITORS1` is not defined.
If the macro is not defined, the code inside this block will be executed. It's a way to conditionally include or
exclude code based on whether a certain macro is defined or not.
`SCON = 0x50;`: This line configures the Serial Control Register (SCON) to set up the UART (Universal
Asynchronous Receiver/Transmitter) for serial communication. The value `0x50` sets the UART to mode 1 (8-
bit UART with variable baud rate), and enables the receiver.
`TMOD = 0X20;`: This line sets the Timer/Counter Mode Control Register (TMOD) to configure Timer 1 in
mode 2, which is an 8-bit auto-reload timer.
`TH1 = 221;`: This line sets the value of Timer 1's high byte (TH1) to 221. This value is used for baud rate
generation. With a clock frequency of 16MHz, a value of 221 corresponds to a baud rate of 1200 bits per second
(bps).
`TR1 = 1;`: This line sets the Timer 1 run (TR1) bit to 1, which starts Timer 1.
`TI = 1;`: This line sets the UART Transmit Interrupt (TI) bit to 1. Setting this bit will trigger the UART to send
the first character of the data in the output buffer.
`printf("Hello World\n");`: This line uses the `printf` function to print the given string to the standard output..
11. Write a 8051 C program to convert the hexadecimal data 0xCFh to decimal and
display the digits on ports P0, P1 and P2 (port window in simulator).
#include <reg51.h>
unsigned char x, input, d0, d1, d2;
void main()
{
input=0xCF;
P0=0x00;
P1=0x00;
P2=0x00;
while (1)
{
X=input;
d0=x%10;
x=x/10;
d1=x%10;
d2=x/10;
P0=d0;
P1=d1;
P2=d2;
}
}
EXPLANATION:
This program uses an 8-bit microcontroller to display a 3-digit decimal number on three 7-segment LED
displays connected to Port 0, Port 1, and Port 2.
The program starts by initializing the values of all the ports to zero.
The program then extracts the individual digits of the number using modular arithmetic and integer division.
The least significant digit (d0) is obtained by taking the number modulo 10. The next digit (d1) is obtained by
dividing the number by 10 and taking the result modulo 10. The most significant digit (d2) is obtained by
dividing the number by 100. Finally, the values of the digits are written to Port 0, Port 1, and Port 2, which are
connected to the 7-segment LED displays.
The digits are written to the ports in reverse order, so the least significant digit is written to Port 0, the next
digit is written to Port 1, and the most significant digit is written to Port 2.
OUTPUT:
Assuming X=0XCF
Then d0 = x%10
= 0xcf % 10
Remainder =7
Therefore, d0 = 7=Po
D1=x%10
Remainder = 0
So d1 = 0 = P1
D2 = x/10
20/10 = 2
So, d2 = 2 = P2