The fundamental principles and functions of any microcontroller (MCU) are largely similar. The main differences lie in the configuration and quantity of peripheral modules and the instruction set. While instruction sets may seem vastly different, they are essentially just different symbols for similar meanings, functions, and addressing modes.
To understand and master any MCU, you should focus on the following key aspects:
MCU Specifications
To understand an MCU, you must first be familiar with its specifications: ROM and RAM size, number of I/O pins, number and type of timers, available peripheral modules, interrupt sources, operating voltage, and power consumption.
Once you understand these features, the next step is to compare the MCU's capabilities with your project's requirements. This helps identify which resources are needed and which are not. If a required feature is not available on the selected MCU, you may need to implement it indirectly. For example, if your project requires communication with a PC's COM port but the MCU lacks a UART, you could implement it using external interrupts and software.
Focus on carefully reading the documentation for the features you will use. You can skim or ignore the sections on modules your project does not require. Practical application is the key to learning any MCU.
Do not spend a dedicated block of time trying to memorize the instruction set. It is simply a set of symbols for logical operations. You can look up specific instructions as needed while programming. As you code more, you will become familiar with the instructions naturally.
Core MCU Functions
For most MCUs, the following functions are fundamental. The terminology may differ between manufacturers, but the core concepts are essentially the same:
Timers
Timers can be grouped into two main categories:
- Fixed-Interval Timers: The timing is preset by the system and not user-controllable. The system typically offers a few fixed intervals (e.g., 32 Hz, 16 Hz, 8 Hz). These are common in 4-bit MCUs and are useful for clock or timing functions.
- Programmable Timers: The timing can be controlled by user software through settings like clock source selection, prescaler values, and preload values. These timers are very flexible and are often used for applications like generating PWM outputs. They are often combined with event counters.
I/O Ports
All MCUs have I/O ports for communicating with external components. They can be classified into several types:
- Pure Input or Output: The direction is fixed by the hardware design and cannot be changed by software.
- Direct Read/Write Ports: Like those on MCS-51 devices, these act as inputs during a read instruction and as outputs during a write instruction.
- Software-Configurable Ports: The direction (input or output) can be set by the program as needed. This flexibility allows them to be used for bus protocols like I2C or for controlling various LCD and LED drivers.
When using I/O ports, it is crucial to remember two points: Input pins should never be left floating and must have a defined logic level, which can be ensured with pull-up or pull-down resistors. For output pins, you must consider the external circuit to ensure they do not source or sink excessive current in standby or static states.
External Interrupts
External interrupts are a standard feature on most MCUs, used for real-time signal triggering, data sampling, and state detection. They can be triggered by a rising edge, falling edge, or logic level. Common applications include:
- External Signal Detection: For real-time applications like TRIAC control or detecting burst signals, and for power-saving purposes.
- Signal Frequency Measurement: Ideal for ensuring no signal transitions are missed.
- Data Decoding: Used in applications like remote controls to decode data streams (e.g., Manchester or PWM) via software to reduce cost.
- Keypress Detection and System Wake-up: An external interrupt, often triggered by a button press, is a common way to wake an MCU from a sleep state.
Communication Interfaces
MCUs typically provide several communication interfaces, including:
- SPI (Serial Peripheral Interface): A common synchronous communication interface using signals like SDI (Serial Data In), SDO (Serial Data Out), and SCLK (Serial Clock). It operates in master or slave mode, where the master provides the clock signal.
- UART (Universal Asynchronous Receiver-Transmitter): A basic asynchronous serial interface using Rx (Receive) and Tx (Transmit) lines. The data format includes a start bit, data bits, an optional parity bit, and stop bits. Most MCUs allow for software configuration of parameters like baud rate. It's commonly used for communication with a PC's serial port.
- I2C (Inter-Integrated Circuit): A two-wire protocol (SDAT and SCLK) that allows multiple devices to be connected to the same bus, each identified by a unique address. A major advantage of I2C is that it can be easily implemented in software using general-purpose I/O pins.
Watchdog Timer (WDT)
The watchdog timer is a standard feature that provides an automatic recovery mechanism if the MCU freezes due to a software fault. In many MCUs, the WDT can be reset by the program but not disabled once activated. Generally, the watchdog's reset period is software-configurable.
MCU Program Structure
Programming an MCU is different from writing software for a PC. Although C-based development is popular, assembly language remains a concise and efficient choice for performance-critical code. The basic structure of an MCU program consists of three main parts: initialization, the main program loop, and interrupt service routines.
Initialization
Initialization is a critical first step in any MCU program. It typically includes:
- Disabling all interrupts and initializing the stack pointer.
- Clearing the system RAM area and display memory for reliability.
- Configuring I/O ports, including direction, pull-up/pull-down resistors, and initial output states.
- Enabling and configuring necessary interrupt sources while disabling unused ones.
- Initializing all required peripheral modules (e.g., setting UART baud rate or timer parameters).
- Initializing program variables and data structures. For applications that store preset values in EEPROM, it's recommended to copy this data to RAM during startup to improve access speed and reduce power consumption.
Main Program Loop
Most MCUs are designed for continuous operation, so their main program is typically an infinite loop. This loop is generally responsible for handling:
- Complex Calculations: Time-consuming operations, especially multiplication and division, should be kept out of interrupt routines.
- Non-Time-Critical Tasks: Any processing that does not have strict real-time requirements.
- Display Updates: Managing data transfer for external LED or LCD drivers.
Interrupt Service Routines (ISRs)
ISRs handle time-sensitive tasks and events like signal detection, key presses, and timing. As a rule, ISRs should be kept as short and efficient as possible. For tasks that don't require immediate processing, set a flag in the ISR and let the main loop handle the actual work. This is crucial for ensuring timely response to all interrupts, especially on low-power, low-speed MCUs.
A critical point in MCU programming is to avoid accessing or modifying the same variable in both an ISR and the main loop simultaneously. To prevent race conditions, the ISR can set a flag to signal that data is ready, and a dedicated function in the main loop can check this flag to perform the actual data manipulation safely.
Ultimately, successful MCU development relies on finding the right methods for a given problem through hands-on practice and thoughtful design.