MDM QB
MDM QB
Ans:
4. Bit-Fields
struct Flags {
unsigned int flag1 : 1;
unsigned int flag2 : 1;
};
struct Flags f = {1, 0};
4. Bitwise Operators
Used for bit-level operations (useful in embedded systems).
Operator Description Example
& Bitwise AND a & b
` ` Bitwise OR
^ Bitwise XOR a ^ b
~ Bitwise NOT ~a
<< Left shift a << 2
>> Right shift a >> 2
Example:
int x = 5; // 00000101 in binary
int y = x << 1; // 00001010 (10 in decimal)
5. Assignment Operators
Used to assign values to variables.
Operator Description Example
= Assign a=b
Operator Description Example
+= Add and assign a += b (same as a = a + b)
-= Subtract and assign a -= b
*= Multiply and assign a *= b
/= Divide and assign a /= b
%= Modulus and assign a %= b
Example:
int a = 5;
a += 3; // a becomes 8
8. Special Operators
a) Sizeof Operator
Finds the size of a data type or variable.
int a;
printf("%lu", sizeof(a)); // Output: 4 (on a 32-bit system)
b) Type Casting Operator
Converts one data type to another.
float f = (float) 5 / 2; // Result: 2.5
3. Illustrate the storage classes in Embedded C with examples of each.
Ans:
Storage classes in Embedded C define a variable’s storage, scope, lifetime, and visibility,
crucial for memory-efficient 8051 microcontroller programming. The reg51.h header
enables interaction with Special Function Registers (SFRs) like P0, P1, TMOD, and IE.
Auto variables exist only within the function in which they are declared. They are allocated
memory when the function starts and deallocated when it exits.
#include <reg51.h>
void blinkLED() {
auto int i; // Auto variable (default for local variables)
for (i = 0; i < 5; i++) {
LED = ~LED; // Toggle LED
delay();
}
}
void delay() {
unsigned int j;
for (j = 0; j < 50000; j++); // Simple delay loop
}
void main() {
while (1) {
blinkLED();
}
}
Explanation:
• The auto keyword is optional since all local variables are auto by default.
• The i variable exists only within blinkLED(), and it gets reinitialized every time the
function runs.
The register storage class is used for frequently accessed variables, such as loop counters. It
instructs the compiler to store the variable in a CPU register (if available), making access
faster. However, in 8051 microcontrollers, only a limited number of registers are available,
so the compiler may ignore this request.
#include <reg51.h>
void fastBlink() {
register int i; // Attempt to store in a register
for (i = 0; i < 10; i++) {
LED = ~LED; // Toggle LED
delay();
}
}
void delay() {
unsigned int j;
for (j = 0; j < 30000; j++);
}
void main() {
while (1) {
fastBlink();
}
}
Explanation:
• The register variable i is suggested to be stored in a CPU register for faster access.
• However, since the 8051 microcontroller has limited registers, the compiler may store
i in RAM instead.
A static variable declared inside a function maintains its value even after the function exits,
making it useful for counters or persistent flags. If a static variable is declared globally, it
restricts access to only the file in which it is declared.
void staticCounterBlink() {
static int count = 0; // Retains value across calls
count++;
if (count % 2 == 0) {
LED = ~LED; // Toggle LED on even calls
}
delay();
}
void delay() {
unsigned int j;
for (j = 0; j < 40000; j++);
}
void main() {
while (1) {
staticCounterBlink();
}
}
Explanation:
• The static variable count retains its value across function calls.
• Unlike auto, it does not get reinitialized to 0 every time the function is called.
Static global variables are accessible only within the file in which they are declared. This
prevents accidental modifications by other files in a multi-file project.
#include <reg51.h>
void blinkWithGlobalCounter() {
counter++; // Increment counter
if (counter >= 5) {
LED = ~LED; // Toggle LED after 5 cycles
counter = 0; // Reset counter
}
delay();
}
void delay() {
unsigned int j;
for (j = 0; j < 30000; j++);
}
void main() {
while (1) {
blinkWithGlobalCounter();
}
}
Explanation:
• The static global variable counter cannot be accessed from other files.
• The LED toggles only every 5 function calls due to the persistent counter.
The extern keyword allows global variables to be accessed across multiple files without
redefining them. This is useful in modular embedded programming.
#include <reg51.h>
void main() {
while (1) {
toggleLED();
}
}
#include <reg51.h>
void toggleLED() {
LED = ~LED; // Toggle LED
delay();
}
void delay() {
unsigned int j;
for (j = 0; j < delay_time; j++);
}
Explanation:
• extern int delay_time; allows led.c to use delay_time without redefining it.
• This is useful in large projects where variables must be shared across multiple files.
Summary Table
Storage
Scope Lifetime Example
Class
Until program
static (local) Local Persistent function variables
terminates
Until program
extern Global (across files) Shared variables between files
terminates
4. Write a C program to store first ten prime numbers into an array using for loop.
Ans:
#include <reg51.h>
#define SIZE 10 // Number of prime numbers to store
void UART_Init();
void UART_Transmit(char);
void UART_SendString(char *);
void findPrimes();
int primes[SIZE]; // Array to store prime numbers
void main() {
UART_Init(); // Initialize UART
findPrimes(); // Find and display prime numbers
while (1); // Infinite loop
}
// UART Initialization (9600 baud)
void UART_Init() {
TMOD = 0x20; // Timer1 Mode2
TH1 = 0xFD; // Baud rate 9600
SCON = 0x50; // 8-bit UART
TR1 = 1; // Start Timer1
}
// Send one character via UART
void UART_Transmit(char ch) {
SBUF = ch;
while (!TI);
TI = 0;
}
// Send string via UART
void UART_SendString(char *str) {
while (*str) {
UART_Transmit(*str++);
}
}
// Find first 10 prime numbers
void findPrimes() {
int count = 0, num = 2, i, isPrime;
while (count < SIZE) {
isPrime = 1;
for (i = 2; i * i <= num; i++) {
if (num % i == 0) {
isPrime = 0;
break;
}
}
if (isPrime) {
primes[count] = num;
count++;
}
num++;
}
// Send prime numbers via UART
UART_SendString("First 10 primes: ");
for (i = 0; i < SIZE; i++) {
UART_Transmit(primes[i] + '0'); // Convert to char
UART_Transmit(' ');
}
}
5. Write a C program to count number of 1’s in the given 8-bit value and send the count to
Port 3.
Ans:
#include <reg51.h>
void main() {
unsigned char input_value = 0x5A; // Example 8-bit value (01011010 in binary)
unsigned char ones_count;
void main() {
unsigned char input_value = 0x5A; // Example 8-bit value (01011010 in binary)
unsigned char ones_count;
unsigned char primes[10];
void delay() {
unsigned int i, j;
for (i = 0; i < 500; i++)
for (j = 0; j < 100; j++);
}
void send_table_of_5() {
unsigned char i;
for (i = 1; i <= 10; i++) {
P2 = 5 * i; // Send table value to Port 2
delay(); // Delay after sending each value
}
}
void main() {
send_table_of_5(); // Send table of 5 to Port 2
while (1);
}
8. Write an Embedded C program to transfer a block of five 8-bit values from RAM memory
address 0x40-0x44 to 0x50-0x54.
Ans:
#include <reg51.h>
void transfer_block() {
unsigned char i;
unsigned char xdata *src = (unsigned char xdata *)0x40; // Source address
unsigned char xdata *dest = (unsigned char xdata *)0x50; // Destination address
The TMOD register is an 8-bit register in the 8051 microcontroller used to configure Timer 0
and Timer 1. It controls the mode of operation for both timers.
r
CopyEdit
| GATE | C/T | M1 | M0 | GATE | C/T | M1 | M0 |
|------|-----|----|----|------|-----|----|----|
| T1 | T1 | T1 | T1 | T0 | T0 | T0 | T0 |
• GATE: If set to 1, the timer runs only when the external interrupt (INT0/INT1) is
high.
• C/T: If set to 1, the timer works as a counter (counts external pulses); if 0, it works as
a timer.
• M1 & M0: Select the timer mode.
o 00 - Mode 0 (13-bit timer)
o 01 - Mode 1 (16-bit timer)
o 10 - Mode 2 (8-bit auto-reload)
o 11 - Mode 3 (Split timer mode)
The TCON register is an 8-bit register used to control Timer and External Interrupt
operations.
CopyEdit
| TF1 | TR1 | TF0 | TR0 | IE1 | IT1 | IE0 | IT0 |
• TF1, TF0 (Timer Overflow Flags): Set when Timer 1 or Timer 0 overflows.
• TR1, TR0 (Timer Run Control): Start (1) or Stop (0) Timer 1 or Timer 0.
• IE1, IE0 (Interrupt Flags): Set when an external interrupt occurs.
• IT1, IT0 (Interrupt Type Control):
o 1 - Edge-triggered interrupt.
o 0 - Level-triggered interrupt.
10. Explain Timer Mode 1 block diagram.
Ans:
The lower 5 bits of TLX and 8 bits of THX are used for the 13 bit count.Upper 3 bits of
TLX are ignored. When the counter rolls over from all 0's to all 1's, TFX flag is set and an
interrupt is generated.
The input pulse is obtained from the previous stage. If TR1/0 bit is 1 and Gate bit is 0, the
counter continues counting up. If TR1/0 bit is 1 and Gate bit is 1, then the operation of the
counter is controlled by input. This mode is useful to measure the width of a given
pulse fed to input.
Timer Mode 1 is a 16-bit timer mode, meaning the timer operates with a full 16-bit register
(THx and TLx) to count from 0000H to FFFFH (0 to 65535 decimal). Once the timer
overflows (FFFFH → 0000H), the TFx (Timer Overflow Flag) in the TCON register is set,
indicating that the timer has completed one full cycle.
• The timer can be incremented by the system clock (machine cycle) or external
clock pulses.
• Controlled by the C/T bit in the TMOD register:
o 0 → Uses the internal system clock (1/12th of the oscillator frequency).
o 1 → Uses an external event for counting.
3. Control Signals:
• GATE (TMOD Register): If 1, the timer only runs when the external interrupt pin
(INTx) is high.
• TRx (TCON Register): When set (1), the timer starts running; when cleared (0), the
timer stops.
4. Overflow Mechanism:
This mode is commonly used for time delays, event counting, and waveform generation in
embedded applications.
This is a 8 bit counter/timer operation. Counting is performed in TLX while THX stores a
constant value. In this mode when the timer overflows i.e. TLX becomes FFH, it is fed
with the value stored in THX. For example if we load THX with 50H then the timer in
mode 2 will count from 50H to FFH. After that 50H is again reloaded. This mode is useful
in applications like fixed time sampling.
Timer Mode 2 is an 8-bit auto-reload mode, meaning the timer operates with an 8-bit
register (TLx) while the THx register holds a constant reload value. When the TLx
register overflows (FFH → 00H), it is automatically reloaded with the value stored in THx.
• THx (Timer High Register): Holds the reload value that is automatically loaded
into TLx after an overflow.
• TLx (Timer Low Register): Increments with the clock and overflows at FFH.
3. Control Signals:
• GATE (TMOD Register): If 1, the timer runs only when the external interrupt pin
(INTx) is high.
• TRx (TCON Register): When set (1), the timer starts running; when cleared (0), the
timer stops.
This mode is mainly used when a constant time delay or baud rate generation is required
in 8051 microcontroller applications.
12. Write an embedded C program to toggle the port pin P3.7 after every 10ms using Timer0.
Also show the steps to design the timer value. Assume Crystal Freq=11.0592MHz.
Ans: Here’s an Embedded C program that toggles P3.7 every 10ms using Timer 0 in Mode 1 (16-bit
Timer Mode). The program calculates the timer's initial value based on a Crystal Frequency of 11.0592 MHz.
#include <reg51.h>
void Timer0_Init() {
TMOD = 0x01; // Timer0 in Mode 1 (16-bit timer)
TH0 = 0xDC; // Load high byte
TL0 = 0x00; // Load low byte
TR0 = 1; // Start Timer0
ET0 = 1; // Enable Timer0 interrupt
EA = 1; // Enable global interrupt
}
#include <reg51.h>
void Timer1_Init() {
TMOD |= 0x10; // Timer1 in Mode 1 (16-bit timer)
TH1 = 0xFC; // Load high byte
TL1 = 0x67; // Load low byte
TR1 = 1; // Start Timer1
ET1 = 1; // Enable Timer1 interrupt
EA = 1; // Enable global interrupt
}
#include <reg51.h>
void Timer0_Init() {
TMOD = 0x02; // Timer0 in Mode 2 (8-bit auto-reload)
TH0 = 0xA4; // Load auto-reload value for 100µS delay
TL0 = 0xA4; // Load initial value
TR0 = 1; // Start Timer0
ET0 = 1; // Enable Timer0 interrupt
EA = 1; // Enable global interrupt
}
void main() {
P2 = 0x00; // Initialize Port 2
Timer0_Init(); // Initialize Timer0
while (1); // Infinite loop
}
15. Write an embedded C program to generate the square wave of 10KHz frequency using
Timer1, Mode 2 on P1.5 pin of 8051. Also show the steps to design the timer value. Assume
Crystal Freq=11.0592MHz.
Ans:
#include <reg51.h>
void Timer1_Init() {
TMOD |= 0x20; // Timer1 in Mode 2 (8-bit auto-reload)
TH1 = 0xD2; // Load auto-reload value for 50µs delay
TL1 = 0xD2; // Load initial value
TR1 = 1; // Start Timer1
ET1 = 1; // Enable Timer1 interrupt
EA = 1; // Enable global interrupt
}
void Timer1_ISR() interrupt 3 {
P1 ^= 0x20; // Toggle P1.5
}
void main() {
P1 = 0x00; // Initialize Port 1
Timer1_Init(); // Initialize Timer1
while (1); // Infinite loop
}