Do you think you can keep up with the innovations in technology without using microcontrollers?
If your answer is a “BIG YES”, you are certainly going in the wrong direction. Why?
Today, 17.6 billion devices around the world use microcontrollers for consumer-targeted applications.
More importantly, this number is only going to increase because of a rising trend in favor of microcontroller-based IoT devices. Not Impressed? Let me put it in another perspective.
A typical home in a developed country is likely to have 3 dozen microcontroller devices. Moreover, a mid-range auto-mobile has about 30 microcontrollers.
Ranging from miniature devices (digital thermometers, smartwatches, calculators, mobile phones, cameras) to high-end consumer electronics (microwave ovens, washing machines, televisions, refrigerators, vending machines), you will almost always find a tiny microcontroller peeking at you from the inside.
In 2019, the global microcontroller market size was valued at $16.49 billion which is expected to hit $42.19 billion by 2027. Did that change your mind?
If no, my struggle will surely make you reconsider your stance. Early on in my professional career, I tried to ignore microcontrollers in about every aspect. Guess, what it got me?
Three straight-off rejections during interviews for embedded systems programmer. Another rejection for teaching assistant position, where I was told “Your Electrical Engineering is Weak!”. Well, you don’t want that? Or, do you?
If you don’t want to end up like me, you need to start learning about microcontrollers.
In this article, I will provide you with an ultimate Introduction of Microcontroller Basics. This will help you get started with microcontrollers right away.
Essentially, I will try to answer every question you may have regarding the working of microcontrollers, such as:
- What is a Microcontroller?
- Components of Microcontroller
- How Microcontroller Works?
- Microcontroller Architecture
- Microcontroller Peripherals
- Difference between Microcontroller and Microprocessor
- Microcontroller Applications
Disclaimer: I will be using exciting analogies and interactive animations throughout the article, so you won’t get bored. For those who think “Technology is Boring Anyway”, try me and let me know of your enjoyment score on a scale of 1-10.
Let’s get started then…
What is a Microcontroller
A “Microcontroller Unit” or “MCU” is an Integrated Circuit (IC) that effectively controls electronic devices within a large embedded system.
In simple terminology, a microcontroller takes input from a user, processes the input signals, and then displays the output as per the user demand.
A microcontroller is a combination of two words: “micro” means small, and “controller” means an enhanced ability to perform control functions.
This does not mean that you try to control your Spouse using a microcontroller. Well, even if you do, don’t hold me responsible for any repercussions.
Jokes apart, a microcontroller is a control device which enables a friendly interaction between humans and electronic devices.
You pour coffee ingredients in a coffee maker, and it helps prepare a soothing coffee for you. With glucose meter, a microcontroller helps analyse your blood glucose levels and displays them on an LCD Display.
It helps thermostat in your Refrigerator to maintain a freezing temperature. You can also set a timer on your Washing Machines while doing your laundry. The microcontroller also helps you capture, edit, and store beautiful photos of your trips via Digital Cameras.
With microcontrollers, possibilities are endless. Most of the time, you are using a microcontroller-driven device but you are not fully aware of that. Now, how amazing is that!
Some of you may be thinking,” Why microcontrollers were created when Personal Computers could have performed such tasks with much better speed and accuracy?”
Your perspective is correct as far as the speed/accuracy aspect is concerned. But look, here’s the thing…
You cannot deploy personal computers everywhere for miniature tasks, simply because that would be too costly and demand much greater space than a microcontroller would, otherwise.
Your personal computer can run Word Editor, a Graphics Design application, and a bunch of other resource-intensive software, all at the same time.
But, why would you want to use such a powerful computer only to detect your car and then open a simple garage door? That would be a huge waste of computer resources, your hard-earned money, and electrical power.
So, what’s the solution? Well, this is where Microcontrollers say Hi to you!
Microcontrollers are highly application-oriented. You can easily program a microcontroller to perform a dedicated task for a specific application, that too at a reduced cost and power requirements.
For a typical application, a personal computer would require 50 Watts. But a microcontroller can implement the same task using merely 50 milliwatts. Does that ring any bells?
Moreover, a microcontroller can operate in extreme conditions i.e., inside a hot car engine, in space satellites, and chilly weather of Antarctica. Personal computers, however, need to be ruggedized for such harsh environments.
Until now, you must have understood the importance of using a microcontroller within your next project. But we all need to understand the technical aspects of anything we intend to use, don’t we?
So, fasten your seatbelts now. I am going to dive into the nitty-gritty details of the microcontroller.
Until now, I hope that you have clearly understood ‘what is a microcontroller’, and why do we even need microcontrollers in the first place.
Now is the right time to tell you about the components which combine to form a full-fledged microcontroller. And more importantly, how microcontrollers process instructions given by a human-user?
You cannot shout at the microcontrollers and say,” Fetch me a glass of water”. Even your dog would not understand that in true sense.
You need to talk to the microcontrollers in a language they understand, THE BINARY LANGUAGE. Or more simply, the language of ZEROs and ONEs.
In Binary language, one-bit can have two values (0 or 1). Two bits can give you four values (0 to 3). Similarly, three bits can take on eight values (0 to 7). Don’t you see a pattern building up here?
While binary instructions can help microcontrollers understand the user-intentions, they still need some Data (in binary form) to perform the desired operations.
The components of a microcontroller work in unison to perform arithmetic (addition, subtraction, multiplication), logical (OR, AND, XOR), shifting (left shift, right shift, rotate), and move operations on Binary Data.
Let’s explore each of the individual microcontroller components in great detail.
Once you have Instructions and Data, you need to store them somewhere. Can you guess a place where you can save them? Your cupboard maybe…
Don’t even think about that! Both the instructions and data are in binary format, so you need a binary storage device. In technical terms, such a device is called MEMORY.
The next question prevails, “How much data/instructions a memory can store?”. Memory is divided into cells, and each cell can store One Byte (8-bits). Moreover, the number of Memory Address Lines depicts how much cells a memory can have.
For example, a memory with one only address line can address two cells (0,1) or store 2 bytes. Similarly, for two address lines, there are 4 cells (0, 1, 2, 3) and storage of 4 bytes.
For three memory address lines, you can target 8 cells (0, 1, 2, 3, 4, 5, 6, 7) or store 8 bytes of data. If you are getting along, you should be able to see another repetitive pattern. Can you spot where have you seen such a pattern before?
Types of Memory
Three types of memories are commonly used in modern microcontrollers. I am not going to discuss the old ones. They are outdated anyway!
- Random Access Memory (RAM)
- Electrically Erasable Programmable Read-Only Memory (EEPROM)
- Flash Memory
Random Access Memory (RAM)
It is a volatile memory, which means it can only be accessed when the system is powered-up. As the system power shuts down, so do the contents inside the RAM.
It has a faster access time, but this is also expensive when compared with the other ones. It is mainly used to store temporary data, variables, and constants during the execution of user instructions.
Due to the high cost and limited usage, the storage capacity of RAM is less than EEPROM and Flash in most of the modern-day microcontrollers.
Electrically Erasable Programmable Read-Only Memory (EEPROM)
It is a non-volatile memory, which means that contents in such a memory remain intact even when the power is removed. You can program only one byte at a time in EEPROM.
The main use of EEPROM in the microcontroller is to store user instructions and data. The microcontroller then accesses the instructions one-by-one and sequentially executes them.
EEPROM needs to be programmed each time a user changes the executable instructions. However, there is a special circuitry needed for that.
Most of the manufacturers provide additional circuitry to program EEPROM with the user instructions e.g., PICKIT3 Programmer for PIC Microcontrollers.
Flash Memory is also non-volatile memory. Just like EEPROM, it does not lose content when the power is removed.
However, unlike EEPROM, it can only program a whole sector or block of bytes. If you want to program a single byte, you will have to program the whole memory sector.
Because of back and forth writing/erasing, flash memory wears out more quickly than the EEPROM. That’s why Flash memory is inexpensive as compared to EEPROM.
Some microcontroller manufacturers use either Flash or EEPROM, while others use both to provide more flexibility to the end-user.
Central Processing Unit (CPU)
CPU is a component of the microcontroller that fetches instructions from the memory, decodes them, and then executes them.
Whoa! Whoa! Stop! What is this Fetch, Decode, and Execute? Are these the “Three Musketeers”?
Well, these are certainly not the musketeers. However, this is what a CPU precisely does. I will explain the physical interpretation of each term. But first, let me elaborate on the major components which make up a CPU.
Control Unit (CU)
The main function of a control unit is to fetch and decode the user instructions. The instructions are stored in memory in the form of an ‘n-Bit’ stream. For an 8-bit stream, 8 bits are stored in each cell of the memory.
For 16-bit instructions, two 8-bit streams are stored in the consecutive cells of the memory.
The first few bits depict the operation which is to be performed i.e., addition, subtraction, multiplication, shifting, rotation, and move, etc.
The remaining bits show the constants, or the memory addresses for the data, or the memory store address.
Are you feeling overwhelmed? Yes? No? Please have some faith in me.
I won’t leave you alone without providing a practical example to easily understand all the concepts I have thrown at your face.
I will use an instruction size of 8-bits. You need to understand the concept, as it will remain the same for 16-bit or even 32-bit instructions. Moreover, I will design my own instruction set just for the sake of simplicity and obviously, your understanding.
Here we go then!
Let’s suppose you want to design a microcontroller that can perform four operations i.e., addition, subtraction, left shift, and move.
Now you need a 2-bit opcode to define the four instructions. Plus, each instruction needs two operands to perform the desired operation.
Operands are the constants or the addresses of the memory from where data is to be fetched. Each operand will have a size of 3-bits in our case.
Now you can generalize the architecture of your 8-bit instruction as:
Instruction: b7 b6 b5 b4 b3 b2 b1 b0
b2-b0: Source Operand
b5-b3: Destination Operand
b7-b6: Operation Code (or opcode)
Having defined the instruction architecture, you can define custom instructions as:
00 – Add $a $b ($a = $a + $b): Add the value at memory address ‘a’ and ‘b’. Store the result in memory address ‘a’
01 – Sub $a $b ($a = $a – $b): Subtract the value at memory address ‘b’ from the value at memory address ‘a’. Write the result in memory address ‘a’
10 – shl $a n ($a << n): Left-Shift the value at memory address ‘a’ by n-bits. Write the result in memory address ‘a’
11 – mov $a $b ($a = $b): Copy the value located at memory address ‘b’ to memory address ‘a’
Now I will explain some examples using the machine code for our instructions set architecture. But, Wait…
Before I move forward, you have to promise me one thing. You will not read the description of the machine codes before you have tried hard enough to comprehend it yourself. Promise? Ok, let’s dive in!
Question 1: What does the machine code ‘00011100’ means?
Answer 1: It means to add (remember the opcode ‘00’ for add instruction) the numbers located at memory addresses ‘011’ and ‘100’. Later, the result should be stored in memory address ‘011’
Easy-Peasy. Right? Let’s do another one…
Question 2: What does the machine code ‘01101001’ means?
Answer 2: It means to subtract (remember the opcode ‘01’ for sub instruction) the number located at memory addresses ‘001’ from the number located at address ‘101’. Later, the result should be stored in memory address ‘101’
I hope you are getting along! If not, you can throw in your query in the comments section.
Time for the next one…
Question 3: What does the machine code ‘10111011’ means?
Answer 3: It means to left-shift (remember the opcode ‘10’ for shl instruction) the number located at memory addresses ‘111’ by 3 bits (‘011’). Later, the result should be stored in memory address ‘111’
Now it’s your turn! Write the answer to the next question in the comments:
Question 4: What does the machine code ‘11110111’ means?
Answer 4: I was not kidding. If you understand the concept, please write the answer in the comments. Else, you can ask me and I will personally reply to each and every one.
Whatever we have done in the last four examples is called Decoding the Instructions.
Now, imagine the effort and amount of time you need to decode 100,000 instructions like that? 5 hours? 10 hours?
Well, don’t get worried about that! You don’t need to do that, as CPU has a dedicated Control Unit for this task.
But, Wait. If the Control unit can only fetch and decode the instructions, who is going to perform the mathematical operations? Is it again you who needs to get involved?
To get an answer, unlock the next sub-section. I am waiting for you there…
Arithmetic Logic Unit (ALU)
The next component in the line of CPU operation is the Arithmetic Logic Unit (ALU).
As the name implies, the basic task of an ALU is to perform Arithmetic, Logic, Shifting, or other mathematical operations as specified by the Instruction Set Architecture of any microcontroller.
ALU precisely handles the “Instruction Execution”.
Control Unit fetches the instruction, decodes it, and then sends appropriate commands to ALU about the desired operation. ALU then executes the instruction, and stores the result into memory.
So far, so good. I have discussed the CPU operation for a single instruction. But what happens, when CPU has to deal with a large number of instructions?
Instruction Pipelining is not a physical component in the CPU. Rather, this is a concept to optimize the use of time and the resources during Instruction Fetching, Decoding, and Execution.
I have a question for you here. When the Control Unit is fetching and decoding the instruction, what the ALU is doing during that period? Also, when ALU is executing the instruction, what the Control Unit is busy doing?
The answer to both of the questions is “NOTHING”. So, now you have found the culprits who are using your time and power but doing no useful work for almost half of the time.
What to do now? PIPELINE THEM! It means that the Control Unit should fetch and start decoding the next instruction, while ALU is busy executing the previous instruction.
By the time ALU executes the previous instruction, the Control Unit should have decoded the next instruction. Now control unit should pass this instruction over to ALU, and fetch the next available instruction.
This cycle continues forever and reduces the instruction execution time, a feature highly demanded by time-critical applications.
MCU Stack is a designated space in the memory used to store the program status, as well as the return addresses for Subroutine/Interrupt calls.
What is a Subroutine? It is a piece of code that is to be executed by a program for a large number of times.
Rather than writing such code, again and again, it is written for once and stored at a specific location in memory. Whenever the program wants to use that code, it can go to that specific location.
After executing the subroutine, the program jumps back to the instruction which is sequentially next to the one that called the subroutine.
What is an Interrupt? It is a diversion of the program from normal execution flow due to external or internal disturbances.
Each interrupt is satisfied using a specific Interrupt Handler, which is again, a piece of code placed somewhere into the memory.
Whenever an interrupt comes, the CPU disrupts the normal program execution and starts executing the interrupt handler to satisfy the interrupt requirements.
Once the interrupt handler terminates, CPU starts executing the same instruction where it was interrupted.
For both the interrupt handler and the subroutine, the CPU needs to go from the memory address of an instruction to the memory address of the subroutine/interrupt handler.
But, how would a CPU know where to return once it has entered the subroutine/interrupt handler? You need to store the ‘Return Address’ somewhere in the memory. This is where the mighty Stack comes in!
Stack works on a Last-In-First-Out (LIFO) scheme, which means that the last pushed number will be the first one to get popped out. Push means ‘Insert’. Pop means ‘Retrieve’.
Before starting the execution of any subroutine/interrupt handler, CPU pushes the return address onto the stack.
Moreover, the last instruction in any subroutine/interrupt handler pops the return address from the stack. This allows the CPU to resume the normal program execution flow.
One critical point is that the CPU should push the return address of the next instruction than the one, which is being interrupted or calling the sub-routine. This will prevent an infinite instruction execution loop.
You may be wondering “What is the need for a whole MCU stack to store only the return address?”. Don’t Worry. You will get the answer in the next sub-section.
Registers are temporary storage areas within a CPU. They are used to store the information about the program flow, program status, instruction results, and the hardware configuration.
In most of the architectures, registers are merely 14-15 in number. However, they are much faster to access than the memory.
This is the single main reason why CPU prefers registers over the memory for operations involving immediate data access.
There are several types of registers which exist within a CPU:
General Purpose Registers
These registers are used as source/destination operands for arithmetic, logic, and shifting instructions
This register points to the section of the memory used for the CPU hardware stack i.e., for subroutine/interrupt calls.
Stack Pointer always points to Top of the stack, which is also the last pushed element onto the stack.
In a bottom-up stack (which increases in an upward direction on element push), stack pointer gets incremented first and then the element is pushed at the updated stack pointer value.
For the pop operation, Top element is retrieved first and then stack pointer gets decremented
Program Counter (PC)
This register stores the address of the next instruction, which is to be executed by the CPU.
PC plays the most important rule during program execution and guides the execution flow of the program.
During the normal program execution, PC gets incremented to the address of the next instruction in a sequential manner.
For any subroutine/interrupt call, PC gets loaded with the starting address of the subroutine/interrupt handler and the return address for the next instruction is pushed onto the stack.
While exiting out of the subroutine/interrupt handler, the last instruction pops the return address from the stack into the Program Counter. The CPU then starts executing the instruction whose address gets loaded into PC.
Link Register (LR)
This register is not available in all of the microcontrollers. However, its function is to store the return address of subroutine/interrupt calls.
Remember! Earlier, CPU was saving the return address into a stack. Now there is a register available for that.
But what happens when a subroutine is called within another subroutine, or the same scenario occurs with an interrupt?
Now you also need to save your Link Register (LR) into the stack, as LR will get updated with the new return address for the nested subroutine/interrupt handler.
Once you get out of the nested subroutine, you need to pop the value from stack into the LR. This will get you to the starting point, the return address for the first sub-routine/interrupt.
Special Function Registers
These registers are used for a specific configuration of the hardware. More specifically, Status Flag Registers give information about the hardware status.
For example, an interrupt status register sets a flag whenever an interrupt occurs. This flag needs to be cleared to be able to detect an interrupt from the same source again.
A zero-bit flag is set whenever a mathematical operation result in a 0. This flag is used to compare the two operands are equal or not.
The Carry-bit flag is set whenever the result of an operation is larger than the allowed storage size.
For example, if you try to store a number greater than 255 in an 8-bit storage area, the carry bit is set indicating that the number is out-of-range.
Register Pushing onto Stack
Do you remember I promised you to answer one question in this section? If no, I am repeating my question here:
“What is the need for a whole MCU stack to store only the return address?”
After having learned about the registers, you are now well-in-shape to understand this cheeky concept.
Stack does not only store the return address. It is also needed to save Special Function Registers, Link Register, and even general-purpose register at times.
Every sub-routine/interrupt handler tends to change the Special Function Registers or flag status. Thus, it is necessary to save the state of these registers into the stack before entering the sub-routine/interrupt handler.
In the case of nested subroutines, Link Register gets updated with the new value whenever a new sub-routine is called. You need to store LR within the stack else you won’t be able to return to the instruction which is called the first instance of the sub-routine.
For the microcontroller architectures having no Link Register (LR), the value of the Program Counter (PC) should be stored in the stack whenever a subroutine or an interrupt handler is invoked.
The general-purpose registers depict the status of a program at any time. To preserve the status of the program before any interrupt or subroutine, general-purpose registers are pushed onto the stack and popped in reverse order before the termination of interrupt handler or subroutine.
As Promised! Here is an interactive ANIMATION describing the whole process:
Before moving onto the clock signal, I want you to imagine a scenario!
Let’s say you provided a bunch of instructions to CPU for execution. You were happy and enthusiastic about that, but then a strange thing happened!
CPU fetched instruction from memory and started executing it. However, without executing the complete instruction, CPU decided to fetch the next instruction. What will this anomalous CPU behaviour leave you with?
A faulty or garbage result for the first instruction, which tends to corrupt the whole program and ultimately the complete embedded systems.
I am pretty sure; you wouldn’t want that! So, how you can prevent this?
You need a Clock Signal which can synchronize each activity of the CPU with a rising or falling edge.
Moreover, the frequency of the clock signal will specify the execution period for each instruction. Higher the frequency, lower the execution time.
And Boy oh Boy! Don’t we all want higher and higher frequency…
If you already know the data for your instruction, you can feed that into the memory directly and you are good to go.
However, what will happen if you need to provide some information about the environment during the program execution?
Besides, what if you need to control some of the environment variables or an external device?
The solution is simple. You need Input-Output ports in microcontroller to read dynamic user-inputs, or to control external devices.
For example, I/O Ports provide the user input data from switches and keyboards to the CPU. Moreover, I/O Ports output the desired information to the user by interfacing with the LCD or LED display.
Each port in a microcontroller is programmable to be either input/output. This provides a user with the flexibility to program the I/O ports as per the application needs.
Now you have got all the components to execute your instructions. All you need to do now is to connect all the components using a Bus. This bus will establish a communication link between different components.
There are three kinds of buses which are mostly used in microcontrollers:
Instruction/Data Bus: This bus helps transfer instructions/data back and forth into CPU and the memory
Address Bus: This bus specifies the address where the desired instruction/data are located inside the memory
Control Bus: This bus specifies whether the instructions/data are to be written or be fetched from the memory
How Microcontroller Works
You are now aware of all the components which make up a microcontroller, and their functions.
But how do all the components work in unison to execute the instructions?
Or more simply, what happens when you have flashed your code in the EEPROM and reset your microcontroller?
There are a series of steps that happen before even CPU starts executing the first instruction of the user program.
Firstly, the microcontroller needs the know-how of the address where the user instructions are stored within EEPROM.
Luckily, there is a simple solution for that. On reset, the microcontroller goes to a fixed memory location. This memory location holds the actual address for the beginning of the program code.
Compiler loads the Program Counter (PC) with the starting address of the program code.
Control Unit (CU) fetches and decodes the instruction pointed by the PC. ALU executes the instruction and stores the result in the memory.
Meanwhile, PC gets updated with the address of the next-in-line instruction. Control Unit then fetches the next instruction, and the cycle goes on…
Repetitively, all the program instructions are fetched, decoded, and executed as per the pipelined architecture.
Most of the women believe that “All men are the same”. This thinking, however, does not apply in the context of the microcontrollers. Microcontrollers differ greatly based on their architecture, which I am going to discuss further:
External Memory vs Embedded Memory
In the case of external memory microcontrollers, memory is not interfaced within the microcontroller. Rather, the user needs to connect an external memory to store instructions/data.
For embedded memory microcontrollers, memory is embedded inside the microcontroller.
If you are a beginner, embedded memory microcontrollers are recommended since you will need a plug-and-play approach to develop the desired application.
Instruction Set Architecture (ISA): RISC vs CISC
RISC (Reduced Instruction Set Computer) has simplified instructions, each of which takes one clock cycle to execute. You need to write efficient software, as hardware in RISC can only handle simple instructions.
CISC (Complex Instruction Set Architecture) has complex instructions. Some of them may take one clock cycle, albeit many will require multiple clock cycles. The hardware in CISC is sophisticated enough to handle complex instructions, so you won’t need to make any extra effort to optimize your code.
Simply put, a CISC instruction may require multiple clock cycles if executed on a RISC architecture. Besides, RISC emphasizes software whereas CISC emphasizes hardware.
Due to the execution of an instruction on each clock cycle, RISC based microcontroller would also require more RAM as compared to the CISC one.
Most of the modern-day microcontrollers employ RISC Instruction Set Architecture. Besides, RISC has a successor in RISC-V architecture, although it is not common in commercial microcontrollers as of now.
Harvard vs Von. Neumann Architecture
In Harvard architecture, the microcontroller has separate buses to access the instructions and data. Whereas, von Neumann architecture has a common bus for both.
In simple terms, microcontrollers with Harvard architecture can fetch data and instructions at the same time. However, in von Neumann architecture, the microcontroller firstly fetches instructions, and then the data.
This bottleneck in von Neumann architecture increases the instruction execution time, and adversely affects the overall system performance.
In Harvard architecture, memory address space is defined for both the instructions and the data. So even if you have some space available in the instruction region, you cannot use that for the data and vice versa.
Now, let’s evaluate the execution time of an ‘addition operation’ for both the architectures.
In Harvard architecture, one clock cycle will be needed to fetch both the instruction and data. The next clock cycle would perform the addition operation. In the third clock cycle, the data bus will store the result in memory whereas the instruction bus will fetch the next instruction at the same time.
In von Neumann architecture, two clock cycles will be used to fetch the instruction and data. The third clock cycle will see through the addition operation. The fourth clock cycle will be used to store the data. Finally, the next instruction will be fetched in the fifth clock cycle.
Now you can see for yourself, it took only three cycles in Harvard architecture to execute an instruction and fetch the next instruction. While von Neumann architecture took five clock cycles for the same task.
Now imagine a scenario for tens of thousands of instructions, and a cumulative delay caused by von Neumann architecture.
That would be enough to convince you to adopt Harvard Architecture, as most of the modern-day microcontroller manufacturers already have.
As one shoe doesn’t fit all, so is the case with a microcontroller for different applications. Microcontrollers come in different bit configuration sizes i.e., 8-bit, 16-bit, 32-bit.
You may be wondering why so many configurations exist? And why can’t we use a 32-bit microcontroller for all of the applications? Let me explain this using a simple analogy.
Let’s say you are a team of 4 friends, and you all have decided to visit Disney Land during summer vacations. You have two choices for your ride: a car or an empty bus. Which one would you pick?
I knew you would go for the bus. After all, you would be able to sleep in the empty space. However, once you become aware of the difference between the fare, you will certainly prefer a car over an empty bus. I have excluded two kinds of humans in my speculation: firstly BILLIONAIRES, and secondly those with a fresh salary check!
The same concept applies to microcontrollers. If an 8-bit microcontroller can fulfill the requirements of an application, why would you want to use more costly and more power-consuming 32-bit MCU? I mean, WHY?
And you won’t believe me, 90% of the applications can be implemented with an 8-bit microcontroller. You will not need 16-bit or 32-bit MCU unless you intend to perform Digital Signal Processing, Floating-Point Arithmetic, or other resource-intensive tasks.
What is the physical, or technical interpretation of an n-bit microcontroller?
An n-bit microcontroller simply means that the data bus is ‘n-bit’. This implies that we can store n-bits at a time in the memory. Or, we can perform data manipulation up to a max of n-bits during one clock cycle.
A 32-bit data manipulation will take 4 clock cycles on an 8-bit microcontroller, whereas only 1 clock cycle on a 32-bit microcontroller.
On the contrary, an 8-bit data manipulation will take one clock cycle on either 8-bit/32-bit MCU. However, 32-bit MCU will be more costly and consume more energy than the 8-bit counterpart.
Feeling confused? Let me elaborate with a practical example…
Let’s suppose you need to add 100 and 150 on an 8-bit microcontroller. How many clock cycles will be required?
Only one clock cycle, since 250 (100+150) is within the 8-bit range (0…255).
However, if you want to add 200 and 250 using an 8-bit MCU, you will require 2 clock cycles. The reason being 200 + 250 = 450 is out-of-range for an 8-bit data (0-255) but well within the range for 16-bit data (0-65535).
Now, tell me the number of clock cycles needed to add ‘60000’ and ‘10000’ in the comments…
Microcontrollers come with additional peripherals to develop an interface with the external environment as well as to meet the demands of the sophisticated applications.
These peripherals are add-on features for a microcontroller. Some microcontrollers may have more of these features, while others may have only two or three additional peripherals.
It is you who is going to decide which features you need in a microcontroller, considering the demands of the application as well as the cost at which they are available.
Each peripheral of a microcontroller is sophisticated enough to deserve a personal blog post. So, I am only going to introduce each peripheral along with some of the possible applications.
As the name implies, this peripheral will induce the notion of time within your system. A clock signal from an external/internal crystal oscillator is used to ensure the proper working of timers/counters.
Timers are used to introduce timer delays within your program. For example, you can set a beep after every 1.5 seconds, or you can read the temperature sensor value after every 5 minutes or so.
Counters are used to count external events. For example, you may want to monitor how many times the user has pressed a button in the last 5 seconds. You can also count the number of bi-directional visitors passing through a security gate within a window of 24 hours.
A most important feature of timers is the generation of Pulse Width Modulation (PWM) signals. PWM signals are widely used for motor control in robotic applications.
PWM is a square wave signal with a specified duty cycle and frequency. The duty cycle means the ratio of signal ON-Time to OFF-Time.
Duty Cycle = (ON Time/Off Time) * 100
Let’s suppose you have a PWM signal that is varying between 0 and 5 volts. With a 20% Duty cycle, you will get 1 Volt. With 80% Duty Cycle, you will get 4 volts.
Thus, you can get different voltage at the output just by varying the duty cycle of a PWM signal. Can you tell me how much duty cycle you need to get 3 volts at the output? Over to the comments section…
Have you ever transferred any data from your mobile phone to a desktop computer? Okay, so which communication interface did you use?
Everybody knows it! USB or Universal Serial Bus. But do you know that USB is not the only communication protocol?
Your desktop computer only has USB ports because it can only interface with the USB hosts. However, the same is not the case with a microcontroller.
The microcontroller needs to interface with all kinds of devices, which have come to existence since the dark ages. As the electronic devices are getting sophisticated with the advent of technology, so are their communication interfaces.
The most important feature of a communication protocol is its high speed and reliability during data transfer. Nobody wants to lose their data. Right?
Many reliable and fast data communication protocols came into existence. However, after recurring trials and testing, there remain only a few which have won the trust of the developers.
The most prominent of them are serial communication protocols such as:
- Universal Asynchronous Receiver Transmitter (UART)
- Universal Synchronous Asynchronous Receiver Transmitter (USART)
- Serial Peripheral Interface (SPI)
- Inter-Integrated Circuit (I2C)
- Universal Serial Bus (USB)
Because of the never-ending demand for high speed and reliable communication, we are inching towards Bus Communication. There are two dominant protocols in this domain:
- Control Area Network (CAN) Bus
- Ethernet for Control and Automation Technology (EtherCAT)
Analog-to-Digital Converter (ADC)
All the sensors having either Serial or Bus Communication Interface produce their output in a digital form. It means that their output voltage is either at logic level ‘Low’ or logic level ‘High’.
An output in such form is readily accepted by the communication interfaces embedded within the microcontroller.
However, there are some sensors whose output follows the analog format. In other words, their output voltage varies between the two levels.
Any such sensor could produce an output voltage of 1.3V, or 2.98V, or 4.78V. Such irregular output voltage is not comprehended by the digital communication interfaces.
Ok. Fine. So, there must exist an analog communication interface for analog data?
Believe me. That will be of no use because CPU also can’t understand the analog voltage signals. What is the solution, then?
An analog-to-digital converter is your best buddy for this task. ADC takes analog inputs and converts them to digital values. These digital values are then fed into CPU for further processing.
If you have a 10-bit ADC, you will be able to convert analog voltage (0-5 volts) to a digital value in the range of 0-1023.
A value of 0 volts will be equal to ‘0’, and a value of 5 volts will be equal to ‘1023’ in the digital format. All the intermediate values will have relative digital counterparts as indicated by the formulae:
Digital Value = (Analog Voltage/5) * 1023
In a 16-bit ADC, you will be able to convert the analog voltage into a digital range of 0-65535. So, you have more precision and more control. In this case, formulae for digital conversion will be:
Digital Value = (Analog Voltage/5) * 65535
Digital-to-Analog Converter (DAC)
Digital-to-Analog Converter (DAC) is a reciprocal of ADC. DAC converts digital pulses into analog signals.
It finds applications for the devices which are controlled using analog voltage.
As the microcontroller can only output digital values, you need DAC to convert the digital values into analog voltage signals.
For a 10-bit DAC, you can convert a digital value in the range of 0-1023 to analog voltage signal from 0 – 5 volts.
The digital value of ‘0’ will correspond to 0 volts, and ‘1023’ will correspond to 5 volts as per the formulae:
Analog Voltage = (Digital Value/1023) * 5
For a 16-bit DAC, you can convert a high range of digital values (0-65535) to an analog voltage in the range of 0-5 volts:
Analog Voltage = (Digital Value/65535) * 5
You may remember that we have already talked about interrupt handlers in the context of MCU Stack. But what is an interrupt controller?
You first need to be crystal clear about the interrupt handler. Simply put, an Interrupt Handler is a piece of a program, which is executed whenever an interrupt comes.
Interrupts caused by any external hardware are called Hardware Interrupts. While interrupts happening internally in the software are called Software Interrupts.
An example of a hardware interrupt is an interrupt due to push button state change i.e., whenever a user presses a push-button or releases it.
Software interrupt could be caused by an internal timer i.e., after each 1 sec, timer generates an interrupt.
There is also another type of interrupt called Exception. Exceptions are the software interrupts caused by the system-level programs rather than user-level programs.
Each peripheral in a microcontroller has its interrupt handler. For example, Port A will have its interrupt handler. Timer0 will have its interrupt handler. Timer1 will also have a unique interrupt handler. I hope you are getting the point!
Whenever a software or hardware interrupt is caused by a peripheral, the corresponding interrupt handler is executed. You can write instructions in an interrupt handler, and your instructions will execute whenever that same interrupt handler is invoked.
Let’s say you want to toggle the output state of Port A after each second. What will you do?
You will set a Timer0 to generate an interrupt after every second. Then, you will go to the Timer0 Interrupt handler and insert your application-specific instructions in that handler i.e., toggle the state of Port A.
So far so good. But what role does Interrupt Controller play in all this? Is Interrupt Controller just a fancy name for ‘Interrupt Handler’?
No, No! Wait, let me explain…
As there are a large number of interrupt handlers, they are stored in NVIC (Nested Vectored Interrupt Controller). Now, what the hell is this NVIC?
NVIC stores the starting address of each interrupt handler in a vector-like format within the memory.
Whenever an interrupt occurs, THE “Interrupt Controller” firstly detects the peripheral which has caused the interrupt.
In the second step, the interrupt controller fetches the starting address of the corresponding interrupt handler from the NVIC.
In the third step, the interrupt controller loads the Program Counter (PC) with the address of the interrupt handler. CPU then starts executing the interrupt handler, while the Interrupt controller goes back to listen for more interrupts.
Difference between Microcontroller and Microprocessor
This is the topic that confuses almost 3/4th of the people, who try to get their basics right about the microcontrollers.
Most of them get confused because they don’t understand the microcontroller and its working principle. But you are not like them!
You have now read almost 7000 words about the basics of microcontroller, and understand microcontrollers from every nook and angle. Understanding the difference between microcontrollers and microprocessors is going to be a piece of cake for you!
Do you remember all the components of a microcontroller i.e., CPU, I/O Ports, Memory, Bus, and Clock? Also, do you remember the additional peripherals that come embedded into the microcontroller?
What if I remove all the components and peripherals from a microcontroller except the CPU? What will you get then?
How simple was that! I bet you did not have any problems understanding that. People, however, make a mess of this because they don’t comprehend microcontrollers in true sense.
Simply put, a microprocessor is essentially a CPU with no memory/peripherals attached. You need to interface the memory as well as the other components/peripherals externally.
With a microprocessor, you need to get some homework done before you can even get the simplest of the applications up and running.
On the contrary, a microcontroller is a ready-to-use unit. It has all the memories, components, and peripherals embedded inside a single chip. You only need to burn EEPROM with the instructions and you are good to go!
But why do microprocessors even exist?
Although microcontrollers come with an embedded memory inside, the memory is only enough to implement low-profile applications.
What if you want to execute resource-intensive applications such as Graphics, 3D Modelling, Android/IOS App development? A more extreme case would be to run all such applications at a single time.
Can a microcontroller perform such an intensive task? Maybe, yes. However, due to the limited memory and CPU computational power, it will take ages.
But we don’t want that? So, what is the solution?
Again. A Microprocessor!
A microprocessor essentially comes with high computational power. Besides, you can interface large memories with the microprocessor, making it an ideal candidate for resource-intensive applications.
Another selling point of the microprocessor is its ability to execute a myriad of resource-intensive applications at the same time. This is the main reason why your desktop/laptop computers come with a processor rather than a microcontroller.
By now, you should have a fair idea of the applications which can be implemented with the help of a microcontroller.
I have also mentioned many such applications within the entire article. However, to give you an extra boost, I am sharing some more:
- Baby Monitors
- Fire Detection
- Internet of Things
- Home Automation
- Light Sensing
- LED Control
- Low-Cost Wearables
- Medical Equipment
- Aerospace System
- and many more…
This list will never end, even If I continued to write for the next three days.
I am calling it a day here. However, it’s time for you to take some action!
Assignment: Think of 20 devices that you can develop with the microcontrollers. Once you have done that, share them with me via email. In return, I will share them on the social media pages so that others can also benefit from your knowledge. Awaiting your answers!
And, please. Don’t forget to share this amazing article with your friends, colleagues, and even your stubborn Boss. You may get a promotion for doing that!
He is the owner and founder of Embedded Robotics and a health based start-up called Nema Loss. He is very enthusiastic and passionate about Business Development, Fitness, and Technology. Read more about his struggles, and how he went from being called a Weak Electrical Engineer to founder of Embedded Robotics.