Skip to content

필사 모드: 嵌入式系统与 IoT 完全指南:从 MCU 到边缘 AI

中文
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

1. 嵌入式系统概述

嵌入式系统(Embedded System)是为执行特定功能而将硬件与软件结合在一起的专用计算系统。洗衣机、汽车发动机控制单元(ECU)、智能温控器、医疗设备等,我们身边无数的设备中都内置着它。

微控制器(MCU)与微处理器(MPU)

项目MCUMPU
CPU简单、低功耗高性能、复杂
内存内置 Flash/RAM需要外部 DRAM
操作系统无或 RTOSLinux、Android 等
功耗数 mW数 W
示例STM32、AVR、ESP32Raspberry Pi、i.MX8

主要 MCU 平台

  • STM32(ST Microelectronics):基于 ARM Cortex-M,广泛用于工业领域。提供 HAL 库与 CubeMX 开发工具。
  • AVR(Microchip/Atmel):Arduino UNO 的基础 MCU。对初学者友好的平台。
  • ESP32(Espressif):双核 Xtensa LX6,内置 WiFi+BLE。最适合 IoT 项目。
  • RP2040(Raspberry Pi):双核 ARM Cortex-M0+,PIO(可编程 I/O)功能独具特色。
  • PIC(Microchip):在工业现场拥有悠久历史的 MCU。

开发环境

  • IDE:STM32CubeIDE、MPLAB X、Arduino IDE、PlatformIO
  • 编译器:GCC(arm-none-eabi-gcc)、LLVM/Clang
  • 调试器:JTAG、SWD(Serial Wire Debug)、OpenOCD、J-Link

2. 用 C 语言控制硬件

嵌入式 C 编程的核心,在于直接操作硬件寄存器,或是利用 HAL(硬件抽象层)库。

GPIO 控制

GPIO(通用输入输出)是控制数字输入输出最基本的接口。

// 使用 STM32 HAL 库控制 GPIO
#include "stm32f4xx_hal.h"

// LED 翻转(引脚 PA5)
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
HAL_Delay(500);

// 读取按钮(引脚 PC13,低电平有效)
if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_RESET) {
    // 按钮被按下时的处理
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
}

直接操作寄存器

不使用 HAL、直接操作寄存器的方式更快、代码体积也更小。

// 直接操作寄存器(STM32F4)
// 启用 GPIOA 时钟
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;

// 将 PA5 设置为输出(MODER 寄存器)
GPIOA->MODER &= ~(0x3 << (5 * 2));   // 清除对应位
GPIOA->MODER |=  (0x1 << (5 * 2));   // 设置为输出模式

// PA5 输出 HIGH
GPIOA->BSRR = (1 << 5);

// PA5 输出 LOW
GPIOA->BSRR = (1 << (5 + 16));

volatile 关键字的重要性

由于编译器优化,对硬件寄存器的访问可能被忽略。用 volatile 来防止这种情况。

// 错误示例:编译器可能会将其优化掉
uint32_t *reg = (uint32_t *)0x40020000;
*reg = 0x01;

// 正确示例:使用 volatile
volatile uint32_t *reg = (volatile uint32_t *)0x40020000;
*reg = 0x01;

// ISR 中使用的全局变量也需要 volatile
volatile uint8_t button_pressed = 0;

3. 中断与定时器

中断服务例程(ISR)

中断是一种机制:当硬件事件(按钮输入、定时器溢出、通信接收等)发生时,CPU 中断当前工作、执行 ISR。

// EXTI 中断回调(HAL 方式)
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
    if (GPIO_Pin == GPIO_PIN_13) {
        button_pressed = 1;
        // ISR 内只做最小限度的工作
        // 禁止使用 HAL_Delay() 等阻塞函数
    }
}

// 定时器中断回调(每 1ms 调用一次)
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
    if (htim->Instance == TIM2) {
        system_tick++;
    }
}

PWM 输出

利用定时器的 PWM(脉宽调制)功能,实现伺服电机、LED 亮度调节、电机转速控制。

// 启动 PWM(TIM3 通道 1)
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);

// 设置占空比 50%(若 ARR = 999,则 CCR = 500)
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 500);

// 伺服电机角度控制函数(0~180 度)
void servo_set_angle(uint8_t angle) {
    // 将 1ms~2ms 脉宽转换为定时器计数值
    uint32_t pulse = 500 + (angle * 1000 / 180);
    __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, pulse);
}

4. 串行通信协议

UART/USART

异步串行通信。主要用于调试输出、GPS 模块、蓝牙模块的连接。

// 通过 UART 发送字符串
char msg[] = "Hello, UART!\r\n";
HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), 100);

// UART 接收(中断方式)
uint8_t rx_byte;
HAL_UART_Receive_IT(&huart2, &rx_byte, 1);

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
    if (huart->Instance == USART2) {
        rx_buffer[rx_index++] = rx_byte;
        HAL_UART_Receive_IT(&huart2, &rx_byte, 1);
    }
}

SPI 通信

主从式同步通信。用于需要高速数据传输的显示器、SD 卡、ADC。

// 通过 SPI 收发数据
uint8_t tx_data[] = {0x9F, 0x00};  // 读取 Flash ID 命令
uint8_t rx_data[2];

HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET);  // CS LOW
HAL_SPI_TransmitReceive(&hspi1, tx_data, rx_data, 2, 100);
HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);    // CS HIGH

I2C 通信

双线(SDA、SCL)总线通信。可在同一总线上连接多个设备。主要用于各类传感器。

// 通过 I2C 读取 MPU6050 加速度计
#define MPU6050_ADDR  0xD0  // 7 位地址 0x68,写地址 0xD0
#define ACCEL_XOUT_H  0x3B

uint8_t data[6];
HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDR, ACCEL_XOUT_H,
                  I2C_MEMADD_SIZE_8BIT, data, 6, 100);

int16_t accel_x = (data[0] << 8) | data[1];
int16_t accel_y = (data[2] << 8) | data[3];
int16_t accel_z = (data[4] << 8) | data[5];

// 实际加速度(g 单位) = raw / 16384.0(设为 ±2g 时)
float ax = accel_x / 16384.0f;

CAN 总线

汽车与工业设备中使用的坚固差分串行通信协议。

// 发送 CAN 消息(STM32 HAL)
CAN_TxHeaderTypeDef tx_header;
uint8_t tx_data[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
uint32_t tx_mailbox;

tx_header.StdId = 0x123;          // CAN ID
tx_header.IDE = CAN_ID_STD;       // 标准帧
tx_header.RTR = CAN_RTR_DATA;     // 数据帧
tx_header.DLC = 8;                // 数据长度

HAL_CAN_AddTxMessage(&hcan1, &tx_header, tx_data, &tx_mailbox);

5. RTOS(实时操作系统)

RTOS 是能够保证确定性(Deterministic)时序的操作系统。它按优先级调度多个任务,对要求实时响应的系统必不可少。

FreeRTOS 基础

FreeRTOS 是应用最广泛的开源 RTOS。由 Amazon 维护,支持 STM32、ESP32、Arduino 等多种平台。

#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "queue.h"

// 任务函数定义
void vTaskLED(void *pvParameters) {
    while(1) {
        HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
        vTaskDelay(pdMS_TO_TICKS(500));  // 等待 500ms(让出 CPU)
    }
}

void vTaskSensor(void *pvParameters) {
    QueueHandle_t xQueue = (QueueHandle_t)pvParameters;
    float temperature;

    while(1) {
        temperature = read_temperature_sensor();
        xQueueSend(xQueue, &temperature, portMAX_DELAY);
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

int main(void) {
    HAL_Init();
    SystemClock_Config();

    QueueHandle_t xTempQueue = xQueueCreate(10, sizeof(float));

    // 创建任务(函数名、任务名、栈大小、参数、优先级、句柄)
    xTaskCreate(vTaskLED,    "LED",    128, NULL,        1, NULL);
    xTaskCreate(vTaskSensor, "Sensor", 256, xTempQueue,  2, NULL);

    vTaskStartScheduler();  // 启动 RTOS 调度器(此行之后不再返回)
    while(1);
}

信号量与互斥锁

SemaphoreHandle_t xMutex;
SemaphoreHandle_t xSemaphore;

// 用互斥锁保护共享资源
xMutex = xSemaphoreCreateMutex();

void vTaskA(void *pvParameters) {
    while(1) {
        if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) {
            // 临界区:访问共享资源
            shared_data++;
            xSemaphoreGive(xMutex);
        }
    }
}

// 用二值信号量实现 ISR-任务同步
xSemaphore = xSemaphoreCreateBinary();

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    xSemaphoreGiveFromISR(xSemaphore, &xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

6. Arduino 生态系统

Arduino 是面向嵌入式入门者的开源平台。特点是简单的 API 与庞大的库生态系统。

Arduino 开发板比较

开发板MCU时钟FlashRAM特点
UNO R3ATmega328P16MHz32KB2KB基础入门款
NanoATmega328P16MHz32KB2KB小型封装
Mega 2560ATmega256016MHz256KB8KB引脚数量多
DueSAM3X8E84MHz512KB96KB32 位 ARM
UNO R4RA4M148MHz256KB32KB最新版本

DHT22 + I2C LCD 示例

#include <DHT.h>
#include <LiquidCrystal_I2C.h>

#define DHTPIN 2
#define DHTTYPE DHT22

DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup() {
    Serial.begin(9600);
    dht.begin();
    lcd.init();
    lcd.backlight();
    lcd.print("IoT Weather Box");
    delay(2000);
    lcd.clear();
}

void loop() {
    float temp = dht.readTemperature();
    float hum  = dht.readHumidity();

    if (isnan(temp) || isnan(hum)) {
        Serial.println("DHT read error!");
        return;
    }

    lcd.setCursor(0, 0);
    lcd.print("Temp: ");
    lcd.print(temp, 1);
    lcd.print(" C  ");

    lcd.setCursor(0, 1);
    lcd.print("Hum:  ");
    lcd.print(hum, 1);
    lcd.print(" %  ");

    Serial.print("T="); Serial.print(temp);
    Serial.print(" H="); Serial.println(hum);

    delay(2000);
}

7. ESP32 & WiFi/BLE IoT

ESP32 是 Espressif Systems 出品的强大 IoT MCU。内置双核 240MHz、WiFi 802.11 b/g/n、BLE 4.2/5.0,性价比出众。

用 MicroPython 实现 MQTT IoT

# MicroPython ESP32 通过 MQTT 发送传感器数据
import time
import network
from umqtt.simple import MQTTClient
from machine import Pin, ADC

# WiFi 连接
def connect_wifi(ssid, password):
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    if not wlan.isconnected():
        wlan.connect(ssid, password)
        while not wlan.isconnected():
            time.sleep(0.5)
    print('WiFi connected:', wlan.ifconfig())

# MQTT 消息接收回调
def on_message(topic, msg):
    print('Topic:', topic, 'Message:', msg)
    if topic == b'device/led' and msg == b'on':
        led.value(1)

connect_wifi('MySSID', 'MyPassword')

# 用 ADC 读取温度传感器(NTC 热敏电阻)
adc = ADC(Pin(34))
adc.atten(ADC.ATTN_11DB)

client = MQTTClient('esp32_sensor', 'broker.hivemq.com', port=1883)
client.set_callback(on_message)
client.connect()
client.subscribe(b'device/led')

while True:
    raw = adc.read()
    voltage = raw * 3.3 / 4095
    # 简易温度转换(实际需要 NTC 特性曲线)
    temp_approx = (voltage - 0.5) * 100
    payload = '{:.1f}'.format(temp_approx)
    client.publish(b'sensor/temperature', payload.encode())
    client.check_msg()
    time.sleep(5)

ESP-IDF(基于 C/C++)

// ESP-IDF WiFi 连接示例
#include "esp_wifi.h"
#include "esp_event.h"
#include "nvs_flash.h"

#define WIFI_SSID "MyNetwork"
#define WIFI_PASS "MyPassword"

static void wifi_event_handler(void *arg, esp_event_base_t event_base,
                                int32_t event_id, void *event_data) {
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        esp_wifi_connect();
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
        ESP_LOGI("WiFi", "Got IP: " IPSTR, IP2STR(&event->ip_info.ip));
    }
}

void wifi_init_sta(void) {
    nvs_flash_init();
    esp_netif_init();
    esp_event_loop_create_default();
    esp_netif_create_default_wifi_sta();

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    esp_wifi_init(&cfg);

    esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, wifi_event_handler, NULL);
    esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, wifi_event_handler, NULL);

    wifi_config_t wifi_config = {
        .sta = {
            .ssid = WIFI_SSID,
            .password = WIFI_PASS,
        },
    };
    esp_wifi_set_mode(WIFI_MODE_STA);
    esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
    esp_wifi_start();
}

8. Raspberry Pi 与 Linux 嵌入式

Raspberry Pi 是运行完整 Linux 操作系统的单板计算机(SBC)。它是处于嵌入式与通用计算交界处的强大平台。

Raspberry Pi 系列比较

型号CPURAM特点
Pi Zero 2WARM Cortex-A53 quad 1GHz512MB超小型,WiFi/BLE
Pi 4 Model BARM Cortex-A72 quad 1.8GHz1~8GB通用高性能
Pi 5ARM Cortex-A76 quad 2.4GHz4~8GB最新高性能
Pi Pico 2RP2350 dual Cortex-M33520KB微控制器

GPIO 控制与伺服电机

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)      # 使用 BCM 引脚编号
GPIO.setup(18, GPIO.OUT)    # 将 GPIO18 设置为输出

# 50Hz PWM 伺服电机控制
pwm = GPIO.PWM(18, 50)
pwm.start(7.5)  # 中立位置(90 度)

def set_servo_angle(angle):
    """设置伺服电机角度(0~180 度)"""
    duty = 2.5 + (angle / 180.0) * 10.0
    pwm.ChangeDutyCycle(duty)
    time.sleep(0.3)

try:
    for angle in [0, 45, 90, 135, 180]:
        set_servo_angle(angle)
        print(f"Angle: {angle} degrees")
        time.sleep(1)
finally:
    pwm.stop()
    GPIO.cleanup()

gpiozero 库

from gpiozero import LED, Button, Servo, DistanceSensor
from signal import pause
import time

# 连接 LED 和按钮
led = LED(17)
button = Button(4)

# 按钮事件处理器
button.when_pressed = led.on
button.when_released = led.off

# 超声波距离传感器(HC-SR04)
sensor = DistanceSensor(echo=24, trigger=23)
while True:
    dist = sensor.distance * 100  # 单位:cm
    print(f"Distance: {dist:.1f} cm")
    if dist < 20:
        led.blink(on_time=0.1, off_time=0.1)
    time.sleep(0.5)

使用 Docker 容器

# 面向 Raspberry Pi 的 Python IoT 应用 Dockerfile
FROM python:3.11-slim-bullseye

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .
CMD ["python", "sensor_server.py"]
# docker-compose.yml
version: '3'
services:
  sensor-app:
    build: .
    privileged: true # 需要该权限才能访问 GPIO
    volumes:
      - /dev:/dev
    restart: unless-stopped

  influxdb:
    image: influxdb:2.7
    ports:
      - '8086:8086'
    volumes:
      - influx_data:/var/lib/influxdb2

  grafana:
    image: grafana/grafana:latest
    ports:
      - '3000:3000'
    volumes:
      - grafana_data:/var/lib/grafana

volumes:
  influx_data:
  grafana_data:

9. 边缘 AI(Edge AI)

边缘 AI 是一种在本地设备而非云端执行 AI 推理的技术。低延迟、离线运行、隐私保护、节省带宽是它的主要优点。

TensorFlow Lite(TFLite)

TFLite 是为移动端及嵌入式设备优化的轻量级 ML 框架。

# TFLite 图像分类推理(Raspberry Pi)
import tflite_runtime.interpreter as tflite
import numpy as np
from PIL import Image
import time

# 加载模型
interpreter = tflite.Interpreter(
    model_path='mobilenet_v2_1.0_224_quant.tflite',
    num_threads=4  # 多线程推理
)
interpreter.allocate_tensors()

input_details  = interpreter.get_input_details()
output_details = interpreter.get_output_details()

# 打印输入信息
print("Input shape:", input_details[0]['shape'])   # [1, 224, 224, 3]
print("Input dtype:", input_details[0]['dtype'])   # uint8(量化模型)

def classify_image(image_path, labels):
    img = Image.open(image_path).convert('RGB').resize((224, 224))
    input_data = np.expand_dims(np.array(img), axis=0)

    # uint8 量化模型无需归一化
    interpreter.set_tensor(input_details[0]['index'], input_data)

    start = time.time()
    interpreter.invoke()
    elapsed = (time.time() - start) * 1000

    output = interpreter.get_tensor(output_details[0]['index'])
    top_idx = np.argmax(output[0])

    print(f"Label: {labels[top_idx]}, Score: {output[0][top_idx]}")
    print(f"Inference time: {elapsed:.1f}ms")

# 加载标签文件
with open('labels.txt') as f:
    labels = [line.strip() for line in f.readlines()]

classify_image('test.jpg', labels)

ONNX Runtime

# 用 ONNX Runtime 运行自定义模型
import onnxruntime as ort
import numpy as np
from PIL import Image

# 创建会话(可选择 CPU/GPU)
session = ort.InferenceSession(
    'model.onnx',
    providers=['CPUExecutionProvider']
)

# 确认输入输出信息
input_name  = session.get_inputs()[0].name
output_name = session.get_outputs()[0].name
input_shape = session.get_inputs()[0].shape
print(f"Input: {input_name}, Shape: {input_shape}")

# 图像预处理
img = Image.open('test.jpg').resize((224, 224))
img_array = np.array(img).astype(np.float32) / 255.0
img_array = np.transpose(img_array, (2, 0, 1))  # HWC -> CHW
img_array = np.expand_dims(img_array, axis=0)   # 添加批次维度

# 推理
result = session.run([output_name], {input_name: img_array})
print("Output shape:", result[0].shape)

边缘 AI 平台比较

平台厂商AI 性能功耗特点
Jetson Orin NanoNVIDIA40 TOPS7~15W内置 CUDA GPU
Coral Dev BoardGoogle4 TOPS~2W专用 Edge TPU
RK3588Rockchip6 TOPS NPU~8W性价比出色
Hailo-8 M.2Hailo26 TOPS2.5WPCIe 扩展模块
Pi 5 + AI HAT+RPi Foundation26 TOPS~5W树莓派生态

10. IoT 通信协议与云

MQTT

MQTT(Message Queuing Telemetry Transport)是为 IoT 优化的轻量级 pub/sub 消息协议。发布者(Publisher)与订阅者(Subscriber)通过代理(Broker)进行通信。

# Python Paho-MQTT 客户端示例
import paho.mqtt.client as mqtt
import json
import time

BROKER = "broker.hivemq.com"
PORT   = 1883
TOPIC_PUB = "home/sensor/living_room"
TOPIC_SUB = "home/control/#"

def on_connect(client, userdata, flags, rc):
    print(f"Connected with code: {rc}")
    client.subscribe(TOPIC_SUB)

def on_message(client, userdata, msg):
    payload = json.loads(msg.payload.decode())
    print(f"Topic: {msg.topic}, Payload: {payload}")

client = mqtt.Client("python_sensor_01")
client.on_connect = on_connect
client.on_message = on_message
client.connect(BROKER, PORT, keepalive=60)
client.loop_start()

while True:
    data = {
        "temperature": 23.5,
        "humidity": 60.2,
        "timestamp": int(time.time())
    }
    client.publish(TOPIC_PUB, json.dumps(data))
    time.sleep(10)

InfluxDB + Grafana 数据可视化

# 将传感器数据写入 InfluxDB
from influxdb_client import InfluxDBClient, Point
from influxdb_client.client.write_api import SYNCHRONOUS

INFLUX_URL   = "http://localhost:8086"
INFLUX_TOKEN = "your_token_here"
INFLUX_ORG   = "myorg"
INFLUX_BUCKET = "iot_sensors"

client = InfluxDBClient(url=INFLUX_URL, token=INFLUX_TOKEN, org=INFLUX_ORG)
write_api = client.write_api(write_options=SYNCHRONOUS)

# 创建数据点
point = (
    Point("environment")
    .tag("location", "living_room")
    .tag("device", "esp32_01")
    .field("temperature", 23.5)
    .field("humidity", 60.2)
    .field("co2_ppm", 650)
)
write_api.write(bucket=INFLUX_BUCKET, record=point)

AWS IoT Core

AWS IoT Core 是一项完全托管的云服务,能够安全地连接与管理数十亿台 IoT 设备。它通过基于 X.509 证书的 mTLS 保障安全,并与 AWS Lambda、DynamoDB、S3 等 AWS 服务集成。


11. 嵌入式安全

OTA(Over-the-Air)固件更新

安全 OTA 的核心是签名验证。拒绝未签名的固件,防止恶意代码被安装。

// ESP-IDF OTA 更新示例
#include "esp_ota_ops.h"
#include "esp_https_ota.h"

void ota_task(void *pvParameter) {
    esp_https_ota_config_t ota_config = {
        .http_config = &(esp_http_client_config_t){
            .url = "https://myserver.com/firmware.bin",
            .cert_pem = server_cert_pem,  // 验证服务器证书
        },
    };

    esp_err_t ret = esp_https_ota(&ota_config);
    if (ret == ESP_OK) {
        esp_restart();  // 成功后重启
    } else {
        ESP_LOGE("OTA", "Update failed: %s", esp_err_to_name(ret));
    }
    vTaskDelete(NULL);
}

在 MCU 上进行 AES 加密

// mbedTLS AES-128 CBC 加密(STM32/ESP32)
#include "mbedtls/aes.h"

void aes_encrypt_data(uint8_t *plaintext, uint8_t *ciphertext,
                       uint8_t *key, uint8_t *iv, size_t len) {
    mbedtls_aes_context ctx;
    mbedtls_aes_init(&ctx);
    mbedtls_aes_setkey_enc(&ctx, key, 128);  // 128 位密钥

    uint8_t iv_copy[16];
    memcpy(iv_copy, iv, 16);  // IV 会在加密过程中被修改

    mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, len,
                           iv_copy, plaintext, ciphertext);
    mbedtls_aes_free(&ctx);
}

安全设计原则

  1. 最小权限原则:只启用必要功能,禁用未使用的接口
  2. 安全启动(Secure Boot):启动时验证固件签名
  3. Flash 加密:对存储在 Flash 中的代码/数据进行加密
  4. 读出保护(RDP):防止通过 JTAG/SWD 转储固件
  5. 随机数生成器(TRNG):使用硬件 RNG 生成加密密钥
  6. 超时与看门狗:自动从无响应状态恢复

12. 测验

Q1. MCU 与 MPU 最大的区别是什么?

答案:MCU(微控制器)将 CPU、内存(Flash、RAM)、外设(UART、SPI、I2C、ADC 等)集成在同一颗芯片上。而 MPU(微处理器)专注于 CPU 核心,需要额外配备外部内存与外设。

说明:MCU 适合要求低功耗、小体积、低成本的嵌入式应用,MPU 则适合需要运行 Linux 等复杂操作系统的高性能应用。

Q2. RTOS 中信号量与互斥锁的区别是什么?

答案:互斥锁(Mutex)具有所有权(Ownership),只有加锁的任务才能解锁,并具备防止优先级反转(Priority Inversion)的优先级继承机制。信号量没有所有权,其他任务或 ISR 也可以发出信号。

说明:互斥锁用于共享资源的互斥(Mutual Exclusion),信号量则用于任务间同步或资源计数。当需要从 ISR 向任务通知事件时,使用二值信号量。

Q3. 比较 I2C 与 SPI 通信方式的优缺点。

答案:

  • I2C 优点:只需 2 根线(SDA、SCL),可在同一总线上连接多个设备(以地址区分),布线简单
  • I2C 缺点:比 SPI 慢(最高 3.4Mbps),需要上拉电阻,开漏方式不利于高速传输
  • SPI 优点:速度非常快(数十 Mbps),全双工通信,硬件实现简单
  • SPI 缺点:每个设备都需要 CS 引脚(引脚数增加),没有地址概念

说明:低速传感器(MPU6050、BMP280 等)主要使用 I2C,需要高速传输的显示器、SD 卡、SPI Flash 则主要使用 SPI。

Q4. 在嵌入式系统中,为什么 volatile 关键字很重要?

答案:编译器在优化过程中,会假定变量的值只在代码内部发生变化。但硬件寄存器、在 ISR 中被修改的变量、DMA 缓冲区等,其值可能在程序流程之外发生变化。volatile 关键字会告诉编译器不要优化该变量,每次都从内存中重新读取。

说明:如果没有 volatile,即使在 ISR 中设置了标志位,主循环也可能因为读取到缓存值而无法识别,从而产生 bug。这是一种在没有调试器的情况下很难发现的经典嵌入式 bug。

Q5. 边缘 AI 中为什么要使用模型量化(Quantization)?

答案:量化是一种将模型的权重与激活值从 32 位浮点数(FP32)转换为 8 位整数(INT8)的技术。借此可将模型体积缩小约 4 倍,推理速度提升 2~4 倍,并大幅降低内存占用与功耗。

说明:嵌入式设备的内存(仅数 MB)与算力都很有限。TFLite 的 INT8 量化模型即便在 Raspberry Pi 或 Cortex-M MCU 这类低配置设备上也能实现实时推理。不过精度可能会略有下降(通常在 1~2% 以内)。


参考资料

현재 단락 (1/470)

嵌入式系统(Embedded System)是为执行特定功能而将硬件与软件结合在一起的专用计算系统。洗衣机、汽车发动机控制单元(ECU)、智能温控器、医疗设备等,我们身边无数的设备中都内置着它。

작성 글자: 0원문 글자: 15,989작성 단락: 0/470