第9章:C/C++ 嵌入式编程
C/C++ 是嵌入式开发的基石,也是连接硬件与软件的桥梁。本章将从物联网开发的角度回顾 C/C++ 核心知识,并介绍在资源受限环境下的编程技巧。
9.1 C 语言基础回顾
9.1.1 指针与内存管理
在嵌入式开发中,直接操作寄存器是家常便饭,指针是必不可少的工具。
- 寄存器操作:
*关键词// 定义一个指向 0x40021000 地址的指针(假设这是 GPIO 寄存器) volatile unsigned int *GPIO_MODER = (unsigned int *)0x40021000; *GPIO_MODER |= (1 << 4); // 设置第4位volatile*:告诉编译器不要优化该变量,因为硬件状态可能随时改变。
9.1.2 结构体与联合体
- **位域 (Bit-field)**:节省内存,精确控制硬件寄存器的每一位。
struct StatusReg { unsigned int overflow : 1; unsigned int interrupt_enable : 1; unsigned int reserved : 6; };
9.2 C++ 面向对象编程
在 Arduino 和 ESP32 开发中,C++ 被广泛使用。
- 封装:将传感器驱动封装成类。
class Led { private: int pin; public: Led(int p) : pin(p) { pinMode(pin, OUTPUT); } void on() { digitalWrite(pin, HIGH); } void off() { digitalWrite(pin, LOW); } };
9.3 嵌入式编程高级特性
9.3.1 中断处理 (Interrupt)
中断是实时系统的核心。
- 原则:中断服务函数 (ISR) 必须短小精悍。不要在 ISR 中使用
delay()或printf()。 - 实现:
void IRAM_ATTR onTimer() { flag = true; // 仅设置标志位,繁重工作交给主循环 }
9.3.2 内存优化
- **PROGMEM (AVR)**:将常量数据存储在 Flash 而非 RAM 中。
- **栈溢出 (Stack Overflow)**:避免深层递归和在栈上分配大数组。
9.3.3 FreeRTOS 多任务
ESP32 和 STM32 常运行 FreeRTOS。
- Task:独立的执行线程。
- Queue:任务间通信的安全通道。
- Semaphore:资源访问控制。
9.4 项目实战:智能门锁系统
我们使用 ESP32 实现一个简单的模拟智能门锁。
需求
- 通过按钮模拟指纹输入。
- 验证通过后驱动舵机(模拟开锁)。
- LED 灯指示状态(红灯:关,绿灯:开)。
- 自动上锁(5秒后)。
代码实现
#include <ESP32Servo.h>
const int BUTTON_PIN = 14;
const int LED_PIN = 2;
const int SERVO_PIN = 13;
Servo myServo;
bool isLocked = true;
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
myServo.attach(SERVO_PIN);
lockDoor();
}
void loop() {
if (digitalRead(BUTTON_PIN) == LOW) { // 按下按钮(模拟指纹识别成功)
unlockDoor();
delay(5000); // 保持5秒
lockDoor();
}
}
void unlockDoor() {
isLocked = false;
digitalWrite(LED_PIN, HIGH);
myServo.write(90); // 舵机转动开锁
}
void lockDoor() {
isLocked = true;
digitalWrite(LED_PIN, LOW);
myServo.write(0); // 舵机复位
}掌握了底层的控制,下一章我们将使用更高效的 Python 来进行快速开发和数据处理。