Notes while learning Embedded
Table of Contents
1. Embedded programs
1.1. Normal flow of a embedded program (esp-hal)
Reset -> Bootloader -> Application startup -> embedded entry point -> #[main] fn main()
- Since there isn’t necessarily an OS/runtime that launches the program
2. Communication Protocols
┌─────────────────┐
│ MCU │
│ │
│ STM32 / AVR │
└───────┬─────────┘
│
┌─────────────┼─────────────┐
│ │ │
UART I²C SPI
│ │ │
USB-UART Sensor Flash
Adapter EEPROM Display
| Protocol | Wires | Typical use | Main characteristic |
| ---------- | -—: | ------------------------ | -------------------------------- |
| UART | 2 | MCU ↔ PC, GPS, Bluetooth | Simple point-to-point |
| I²C | 2 | Sensors, EEPROM, RTC | Multiple devices on same bus |
| SPI | 3–4+ | Flash, displays, ADCs | Fast, full-duplex |
| CAN | 2 | Automotive, industrial | Robust multi-node bus |
| USB | 2+ | MCU ↔ computer/devices | Complex, standardized |
| RS-232 | 2+ | Older serial equipment | Electrical interface + signaling |
| RS-485 | 2 | Industrial networks | Long distance, differential |
| LIN | 1 | Automotive subsystems | Cheap/simple automotive bus |
2.1. UART
> Universal Asynchronous Receiver/Transmitter asynchronous:no shared clock between the devices
MCU TX → Device RX MCU RX ← Device TX GND ↔ GND
- Device x needs to send data “A” to y
Instead of simply putting the data
A = 0x41 = 01000001
on the wire. It creates a frame.
Common configuration:
1 start bit 8 data bits 1 stop bit no parity
Often written as:
8N1
8 data bits N = no parity 1 stop bit
The frame looks like:
Idle │ ▼ 1 0 1 0 0 0 0 0 1 1 └──────┬────────┘ dataMore precisely:
START DATA STOP ↓ ↓ ↓ ┌──┐ ┌────────────────┐ ┌── Idle ──┘ └──┤ 8 data bits ├─────┘ └────────────────┘- UART uses a defined baud rate: 115200 means 115200 symbols per second so one bit takes approximately 1/11520 seconds per bit.
- Both sides need compatible settings
But why the start bit? Since there’s no clock wire, the reciever doesn’t know when the byte starts so the line normally sits at high and when the trasmission begins
HIGH │ │ └──── LOW
This tells the receiver: A frame is starting
2.1.1. Limitations of UART
simple but( only for Point to Point communications) A ───────── B
┌── B │ A ─────┼── C │ └── DSince we have no shared clock, both devices must agree on timing, usually one transmitter and one receiver
2.2. I²C
> Inter-Integrated Circuit: synchronous Typical example:
┌──────────────┐
│ MCU │
└──────┬───────┘
│
SDA ───┼───────────────┐
SCL ───┼───────────────┤
│ │
┌──┴──┐ ┌──┴──┐
│Temp │ │EEPROM
│sensor │ │
└─────┘ └─────┘
- SDA = Serial Data
- SCL = Serial Clock
Unlike UART, which has TX, RX I2C has a clock
SCL ──┐ ┌─┐ ┌─┐ ┌─┐ ┌─
└─┘ └─┘ └─┘ └─┘
SDA ───── data ─────────
Let’s say I have a system:
STM32 │ ├──── Temperature sensor │ ├──── Accelerometer │ ├──── OLED │ ├──── EEPROM │ └──── RTC
- All of these devices share SDA, SCL.
Each device has an address. Example:
Temperature sensor → 0x48 Accelerometer → 0x68 EEPROM → 0x50 RTC → 0x68Then the MCU can say: “Talk to device 0x68”
Master │ ├──── Slave ├──── Slave └──── Slave
- The master controls the clock.
- The master initiates communication.
For example in the above system we intend to read temperature data.
START │ ▼ Device Address(0x48) │ ▼ Register Address │ ▼ READ │ ▼ Temperature Data(0x19) │ ▼ STOP
2.2.1. Verifying if data is received
> occurs on the 9th pulse of SCL, following each 8-bit byte
- ACK: acknowledge; After a successfull byte transmission, the receiver can acknowledge it.
- NACK: not acknowledge; After an unsuccessfull byte transmission, the receiver can state “I didn’t accept/receive that.”.
- Transactions-based
- Write transcations: The slave sends ACK/NACK after receiving the master’s address or data bytes.
- Read transcations: The master send ACK/NACK after receiving the data from the slave. The master typically sends a NACK after the final byte to signal the slave to stop transmitting, followed immediately by a STOP condition.
- Address Phase: A NACK after the address byte indicates no slave device on the bus matched the target address, causing the master to abort the transfer.
2.3. UART vs I2C
| UART | I²C | |
| ---------------- | ----------------------------- | -------------------- |
| Clock | No | Yes |
| Wires | TX/RX | SDA/SCL |
| Typical topology | Point-to-point | Shared bus |
| Addressing | No built-in addressing | Yes |
| ACK | Not like I²C | Yes |
| Multiple devices | Not naturally | Yes |
| Complexity | Low | Medium |
| Typical use | Debug console, GPS, Bluetooth | Sensors, EEPROM, RTC |
2.4. SPI
> Serial Peripheral Interface: synchronous like the I2C
Typical signals: SCLK: Serial clock; shared clock between master‐slaves
- MOSI: Master Out, Slave In; from master to slave
- MISO: Master In, Slave Out; from slave to master
CS: Chip Select
MCU │ ┌─────────┼─────────┐ │ │ │ SCLK MOSI MISO │ │ │ └─────────┼─────────┘ │ CS │ ┌───┴───┐ │ Flash │ └───────┘- SPI is generally faster than I2C, but uses more wires.
2.4.1. SPI with multiple devices
- devices can share:SCLK, MOSI,MISO
but each device gets its own chip-select CS
MCU │ ┌──────────┼──────────┐ │ │ │ SCLK MOSI MISO │ │ │ │ │ │ ┌────┴───┐ ┌────┴───┐ ┌────┴───┐ │ Flash │ │ Display│ │ Sensor │ └────────┘ └────────┘ └────────┘ ↑ ↑ ↑ CS1 CS2 CS3The MCU selects the device it wants: CS1 = low CS2 = high CS3 = high
i.e. Flash is selected from above devices
2.5. UART, I2C, SPI
UART:
A ───────── B
I2C:
┌── Sensor │ MCU ─────────┼── EEPROM │ └── RTCSPI:
MCU ───── Flash └───── Display └───── ADC
3. End notes
Project Ideas: https://wokwi.com/