Table of Contents
KEY TAKEAWAYS
- Embedded C is standard C with extensions and constraints specific to microcontroller programming
- Embedded C uses hardware-specific features like register access, interrupts, and memory-mapped I/O
- Standard C programs run on an OS; Embedded C programs often run on bare metal without an OS
- Resource constraints (limited RAM, ROM, and CPU speed) shape how Embedded C code is written
C vs Embedded C – The Differences
| C programming | Embedded C programming |
|---|---|
| C is a general purpose programming language, which can be used to design any type of desktop based applications. | Embedded C is an extension of C language (some of the features are there, which can be used to specific purposes), it is used to develop micro-controller based applications (low-level or/and application level). |
| While, writing a C programming language code there is no need to know about computer hardware i.e. C language is not hardware dependent language. | You must have good knowledge about the hardware for that you’re developing any code. Embedded C is fully hardware dependent language. |
| C language program is hardware independent. | Embedded C program is hardware dependent. |
| For C language, the standard compilers can be used to compile and execute the program. | For Embedded C, you need to some specific compilers that are able to generate particular hardware/micro-controller based output. |
| We need to write full program from scratch while developing a C language code. | The compiler generates some initial code automatically (which may include some assembly language code/files) based on the selected micro-controller/microprocessor. |
| In the C programming language, we can use standard function like printf(), scanf() etc for output and input. | These functions may not work, because in an embedded device there may not any standard output device (like monitor, Keyboard etc.). you have to write code to display output to connected display unit like 16X2 LCD, graphics display etc. |
| C language compilers generate operating system dependent executable files that can be run on the same operating system. | Embedded C language compilers generate hardware dependent files that you have to upload in the micro-controller and then you have to switch on the device to check weather code is working or not |
| Readability modifications, bug fixing are very easy in a C language program. | It’s not too easy to read, understand, modify and fix the bugs in an Embedded C language program. |
| GCC (GNU Complier collection), Borland turbo C, Intel C++ compiler are some of the popular compilers which are used to compile, execute a C language program. | Keil compiler (An Arm company compilers), BiPOM ELECTRONIC – Embedded training and Development, Green Hill software etc are some of the popular compilers to compile, run an Embedded C language program. |
Side-by-Side Code Comparison
The best way to understand the difference is to see the same task done both ways. Let’s read a temperature value and print it.
Standard C — Read Temperature from a File
#include <stdio.h>
int main(void)
{
FILE *fp = fopen("/sys/class/thermal/thermal_zone0/temp", "r");
int temp;
fscanf(fp, "%d", &temp);
fclose(fp);
printf("CPU Temperature: %.1f °Cn", temp / 1000.0);
return 0;
}Standard C relies on an operating system. fopen(), printf(), and file I/O all require a kernel, a file system, and a standard library. This code runs on Linux, Windows, or macOS — but it cannot run on a bare-metal microcontroller.
Embedded C — Read Temperature from an ADC
#include <avr/io.h>
void uart_putchar(char c) {
while (!(UCSR0A & (1 << UDRE0))); /* Wait for transmit buffer empty */
UDR0 = c; /* Send character */
}
void uart_print(const char *s) {
while (*s) uart_putchar(*s++);
}
uint16_t adc_read(uint8_t channel) {
ADMUX = (1 << REFS0) | (channel & 0x07); /* AVcc ref, select channel */
ADCSRA |= (1 << ADSC); /* Start conversion */
while (ADCSRA & (1 << ADSC)); /* Wait for completion */
return ADC; /* Return 10-bit result */
}
int main(void) {
/* Configure ADC: enable, prescaler = 128 */
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
/* Configure UART: 9600 baud at 16 MHz */
UBRR0H = 0;
UBRR0L = 103;
UCSR0B = (1 << TXEN0);
uint16_t raw = adc_read(0); /* Read ADC channel 0 (LM35 sensor) */
uint16_t temp_c = (raw * 500) / 1024; /* Convert to Celsius */
char buf[16];
uart_print("Temp: ");
/* Simple integer-to-string (no printf available) */
buf[0] = '0' + (temp_c / 10);
buf[1] = '0' + (temp_c % 10);
buf[2] = 'C';
buf[3] = '
