Arduino Mega

Arduino Mega 2560 详细指南

1. Arduino Mega 概览

1.1 核心规格对比

// Arduino Mega 2560 vs UNO 对比
/*
                Mega 2560        UNO
微控制器:     ATmega2560      ATmega328P
工作电压:     5V              5V
数字I/O引脚:  54个            14个
PWM引脚:      15个            6个
模拟输入引脚: 16个            6个
串口:        4个             1个
闪存:        256KB           32KB
SRAM:        8KB             2KB
EEPROM:      4KB             1KB
时钟速度:    16MHz           16MHz
*/

// Mega 2560 优势:
// 1. 更多I/O引脚,适合复杂项目
// 2. 更多串口,便于多设备通信
// 3. 更大的内存,适合复杂程序
// 4. 更多定时器,更灵活的PWM

1.2 引脚布局详解

                  USB Type-B
             ┌─────────────────┐
             │                 │
             └─────────────────┘
┌─────────────────────────────────────┐
│                                     │
│ D53    SCK        AREF     NC      │
│ D52    MISO       GND      NC      │
│ D51    MOSI  PWM  A15(69)  NC      │
│ D50    SS    PWM  A14(68)  NC      │
│ D10    PWM        A13(67)  SCL     │
│ D9     PWM        A12(66)  SDA     │
│ D8             3.3V A11(65)  RESET  │
│ D7             5V   A10(64)  3.3V   │
│ D6     PWM       GND A9(63)  5V     │
│ D5     PWM       GND A8(62)  GND    │
│ D4             VIN  A7(61)  RESET  │
│ D3     PWM  INT5 A6(60)  RX1(19)   │
│ D2     PWM  INT4 A5(59)  TX1(18)   │
│ D1     TX   INT3 A4(58)  RX2(17)   │
│ D0     RX   INT2 A3(57)  TX2(16)   │
│ D15    RX3       A2(56)  PWM D14   │
│ D22    SCL       A1(55)  PWM D13   │
│ D23    SDA       A0(54)  PWM D12   │
└─────────────────────────────────────┘
// 继续有更多引脚...

2. 特殊引脚功能

2.1 串口资源

// Mega有4个硬件串口
/*
Serial   : 0(RX), 1(TX)    - 与USB通信
Serial1  : 19(RX1), 18(TX1) - 第一个额外串口
Serial2  : 17(RX2), 16(TX2) - 第二个额外串口
Serial3  : 15(RX3), 14(TX3) - 第三个额外串口
*/

// 多串口通信示例
void setup() {
  // 初始化所有串口
  Serial.begin(9600);    // USB/PC通信
  Serial1.begin(9600);   // GPS模块
  Serial2.begin(115200); // 蓝牙模块
  Serial3.begin(19200);  // 无线模块
  
  Serial.println("All serial ports initialized");
}

void loop() {
  // 处理来自不同串口的数据
  if (Serial1.available()) {
    String gpsData = Serial1.readStringUntil('\n');
    Serial.print("GPS: ");
    Serial.println(gpsData);
  }
  
  if (Serial2.available()) {
    String bluetoothData = Serial2.readStringUntil('\n');
    Serial.print("Bluetooth: ");
    Serial.println(bluetoothData);
  }
}

2.2 中断引脚

// Mega有6个外部中断引脚
/*
INT0 : D2
INT1 : D3
INT2 : D21
INT3 : D20
INT4 : D19
INT5 : D18
*/

// 多中断示例
const int interruptPins[] = {2, 3, 18, 19, 20, 21};
volatile bool interruptFlags[] = {false, false, false, false, false, false};

void setup() {
  Serial.begin(9600);
  
  // 设置所有中断引脚
  for (int i = 0; i < 6; i++) {
    pinMode(interruptPins[i], INPUT_PULLUP);
  }
  
  // 配置中断(全部下降沿触发)
  attachInterrupt(digitalPinToInterrupt(2), isr0, FALLING);
  attachInterrupt(digitalPinToInterrupt(3), isr1, FALLING);
  attachInterrupt(digitalPinToInterrupt(18), isr2, FALLING);
  attachInterrupt(digitalPinToInterrupt(19), isr3, FALLING);
  attachInterrupt(digitalPinToInterrupt(20), isr4, FALLING);
  attachInterrupt(digitalPinToInterrupt(21), isr5, FALLING);
}

// 中断服务程序
void isr0() { interruptFlags[0] = true; }
void isr1() { interruptFlags[1] = true; }
void isr2() { interruptFlags[2] = true; }
void isr3() { interruptFlags[3] = true; }
void isr4() { interruptFlags[4] = true; }
void isr5() { interruptFlags[5] = true; }

void loop() {
  // 检查并处理中断
  for (int i = 0; i < 6; i++) {
    if (interruptFlags[i]) {
      Serial.print("Interrupt ");
      Serial.print(i);
      Serial.println(" triggered");
      interruptFlags[i] = false;
    }
  }
}

3. 内存管理

3.1 大内存利用

// Mega有8KB SRAM,可以处理更大数据
#include <MemoryFree.h>

void setup() {
  Serial.begin(9600);
  Serial.print("Mega SRAM: ");
  Serial.print(freeMemory());
  Serial.println(" bytes free");
  
  // 创建大数组(UNO上可能失败)
  int bigArray[1000];  // 1000个整数 = 2000字节
  
  Serial.print("After array: ");
  Serial.print(freeMemory());
  Serial.println(" bytes free");
}

// 使用malloc动态分配内存
void useDynamicMemory() {
  // 动态分配1KB内存
  char* buffer = (char*)malloc(1024);
  
  if (buffer != NULL) {
    // 使用内存
    memset(buffer, 0, 1024);
    strcpy(buffer, "Dynamic memory test");
    
    Serial.println(buffer);
    
    // 释放内存
    free(buffer);
  } else {
    Serial.println("Memory allocation failed!");
  }
}

3.2 程序优化技巧

// 利用大内存的技巧
class DataLogger {
private:
  static const int MAX_SAMPLES = 1000;
  float samples[MAX_SAMPLES];
  int sampleIndex = 0;
  
public:
  void addSample(float value) {
    if (sampleIndex < MAX_SAMPLES) {
      samples[sampleIndex++] = value;
    }
  }
  
  void analyze() {
    float sum = 0, min = samples[0], max = samples[0];
    
    for (int i = 0; i < sampleIndex; i++) {
      sum += samples[i];
      if (samples[i] < min) min = samples[i];
      if (samples[i] > max) max = samples[i];
    }
    
    Serial.print("Samples: ");
    Serial.println(sampleIndex);
    Serial.print("Average: ");
    Serial.println(sum / sampleIndex);
    Serial.print("Min: ");
    Serial.println(min);
    Serial.print("Max: ");
    Serial.println(max);
  }
};

DataLogger logger;

void setup() {
  Serial.begin(9600);
}

void loop() {
  // 采集传感器数据
  float temperature = random(200, 300) / 10.0;
  logger.addSample(temperature);
  
  // 每采集100个样本分析一次
  static int count = 0;
  if (count++ >= 100) {
    logger.analyze();
    count = 0;
  }
  
  delay(100);
}

4. 多传感器系统

4.1 大规模I/O控制

// 控制多个LED和读取多个传感器
const int NUM_LEDS = 20;
const int NUM_SENSORS = 8;

int ledPins[NUM_LEDS] = {
  22, 23, 24, 25, 26, 27, 28, 29,
  30, 31, 32, 33, 34, 35, 36, 37,
  38, 39, 40, 41
};

int sensorPins[NUM_SENSORS] = {A0, A1, A2, A3, A4, A5, A6, A7};

void setup() {
  Serial.begin(115200);
  
  // 初始化所有LED引脚
  for (int i = 0; i < NUM_LEDS; i++) {
    pinMode(ledPins[i], OUTPUT);
  }
  
  // 初始化所有传感器引脚(模拟输入自动设置)
  Serial.println("Mega Multi-IO System Ready");
}

void loop() {
  // 读取所有传感器
  Serial.println("=== Sensor Readings ===");
  for (int i = 0; i < NUM_SENSORS; i++) {
    int value = analogRead(sensorPins[i]);
    Serial.print("A");
    Serial.print(i);
    Serial.print(": ");
    Serial.print(value);
    Serial.print("\t");
    
    // 根据传感器值控制LED
    if (value > 512) {
      digitalWrite(ledPins[i], HIGH);
    } else {
      digitalWrite(ledPins[i], LOW);
    }
  }
  Serial.println();
  
  // LED流水灯效果
  static int currentLed = 0;
  for (int i = 0; i < NUM_LEDS; i++) {
    digitalWrite(ledPins[i], (i == currentLed) ? HIGH : LOW);
  }
  currentLed = (currentLed + 1) % NUM_LEDS;
  
  delay(200);
}

4.2 矩阵键盘

// 4x4矩阵键盘连接
#include <Keypad.h>

const byte ROWS = 4;
const byte COLS = 4;

char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};

// Mega有足够引脚直接连接
byte rowPins[ROWS] = {22, 23, 24, 25};
byte colPins[COLS] = {26, 27, 28, 29};

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

void setup() {
  Serial.begin(9600);
  Serial.println("4x4 Keypad Test");
}

void loop() {
  char key = keypad.getKey();
  
  if (key) {
    Serial.print("Key Pressed: ");
    Serial.println(key);
    
    // 执行相应操作
    switch(key) {
      case 'A':
        Serial.println("Function A");
        break;
      case 'B':
        Serial.println("Function B");
        break;
      // ... 其他按键处理
    }
  }
}

5. 高级通信项目

5.1 多设备网关

// Mega作为通信网关
#include <SoftwareSerial.h>

// 定义多个软串口(Mega也可以使用软串口)
SoftwareSerial gpsSerial(50, 51);   // RX, TX
SoftwareSerial xbeeSerial(52, 53);  // RX, TX

void setup() {
  // 硬件串口
  Serial.begin(9600);    // USB/PC
  Serial1.begin(9600);   // 蓝牙
  Serial2.begin(115200); // WiFi
  
  // 软串口
  gpsSerial.begin(4800);
  xbeeSerial.begin(9600);
  
  Serial.println("Multi-protocol Gateway Ready");
}

void loop() {
  // 转发GPS数据到WiFi
  if (gpsSerial.available()) {
    String gpsData = gpsSerial.readStringUntil('\n');
    Serial2.println("GPS: " + gpsData);
    Serial.println("GPS: " + gpsData);
  }
  
  // 转发XBee数据到蓝牙
  if (xbeeSerial.available()) {
    String sensorData = xbeeSerial.readStringUntil('\n');
    Serial1.println("SENSOR: " + sensorData);
    Serial.println("XBee: " + sensorData);
  }
  
  // 处理来自PC的命令
  if (Serial.available()) {
    String command = Serial.readStringUntil('\n');
    processCommand(command);
  }
}

void processCommand(String cmd) {
  if (cmd == "GET_STATUS") {
    Serial.println("Status: All systems OK");
  }
  // 更多命令处理...
}

5.2 CAN总线通信

// CAN总线控制器(需要MCP2515模块)
#include <mcp_can.h>
#include <SPI.h>

#define CAN_INT 2      // 中断引脚
#define CS_PIN 10      // SPI片选

MCP_CAN CAN(CS_PIN);

void setup() {
  Serial.begin(115200);
  
  // 初始化CAN总线
  while (CAN_OK != CAN.begin(CAN_500KBPS)) {
    Serial.println("CAN init fail, retry...");
    delay(100);
  }
  Serial.println("CAN init ok!");
}

void loop() {
  // 接收CAN消息
  if (digitalRead(CAN_INT) == LOW) {
    receiveCANMessage();
  }
  
  // 定期发送状态消息
  static unsigned long lastSend = 0;
  if (millis() - lastSend > 1000) {
    sendCANMessage(0x100, "Hello from Mega");
    lastSend = millis();
  }
}

void receiveCANMessage() {
  unsigned char len = 0;
  unsigned char buf[8];
  
  if (CAN_MSGAVAIL == CAN.checkReceive()) {
    CAN.readMsgBuf(&len, buf);
    
    unsigned long canId = CAN.getCanId();
    
    Serial.print("CAN ID: 0x");
    Serial.print(canId, HEX);
    Serial.print(", Data: ");
    
    for (int i = 0; i < len; i++) {
      Serial.print(buf[i], HEX);
      Serial.print(" ");
    }
    Serial.println();
  }
}

void sendCANMessage(unsigned long id, const char* message) {
  CAN.sendMsgBuf(id, 0, strlen(message), (unsigned char*)message);
}

6. 机器人控制系统

6.1 多舵机控制

// 控制机械臂的多个舵机
#include <Servo.h>

#define NUM_SERVOS 6
Servo servos[NUM_SERVOS];

int servoPins[NUM_SERVOS] = {2, 3, 4, 5, 6, 7};
int servoAngles[NUM_SERVOS] = {90, 90, 90, 90, 90, 90};

void setup() {
  Serial.begin(9600);
  
  // 初始化所有舵机
  for (int i = 0; i < NUM_SERVOS; i++) {
    servos[i].attach(servoPins[i]);
    servos[i].write(servoAngles[i]);
  }
  
  Serial.println("6-DOF Robotic Arm Ready");
}

void loop() {
  // 从串口接收控制命令
  if (Serial.available()) {
    String command = Serial.readStringUntil('\n');
    processArmCommand(command);
  }
  
  // 平滑移动到目标位置
  smoothMove();
  
  delay(20);
}

void processArmCommand(String cmd) {
  // 命令格式: "SERVO_ID:ANGLE"
  // 例如: "1:120" - 设置舵机1到120度
  
  int colonIndex = cmd.indexOf(':');
  if (colonIndex > 0) {
    int servoId = cmd.substring(0, colonIndex).toInt();
    int targetAngle = cmd.substring(colonIndex + 1).toInt();
    
    if (servoId >= 0 && servoId < NUM_SERVOS) {
      servoAngles[servoId] = constrain(targetAngle, 0, 180);
      Serial.print("Servo ");
      Serial.print(servoId);
      Serial.print(" target: ");
      Serial.println(servoAngles[servoId]);
    }
  }
}

void smoothMove() {
  for (int i = 0; i < NUM_SERVOS; i++) {
    int currentAngle = servos[i].read();
    
    if (currentAngle != servoAngles[i]) {
      // 每次移动1度,实现平滑移动
      if (currentAngle < servoAngles[i]) {
        servos[i].write(currentAngle + 1);
      } else {
        servos[i].write(currentAngle - 1);
      }
    }
  }
}

6.2 步进电机控制

// 控制多个步进电机
#include <Stepper.h>

#define STEPS_PER_REVOLUTION 200

// 创建4个步进电机对象
Stepper stepper1(STEPS_PER_REVOLUTION, 22, 23, 24, 25);
Stepper stepper2(STEPS_PER_REVOLUTION, 26, 27, 28, 29);
Stepper stepper3(STEPS_PER_REVOLUTION, 30, 31, 32, 33);
Stepper stepper4(STEPS_PER_REVOLUTION, 34, 35, 36, 37);

void setup() {
  Serial.begin(9600);
  
  // 设置电机速度
  stepper1.setSpeed(60);  // RPM
  stepper2.setSpeed(60);
  stepper3.setSpeed(60);
  stepper4.setSpeed(60);
  
  Serial.println("4-Axis CNC Control Ready");
}

void loop() {
  // G代码解析和执行
  if (Serial.available()) {
    String gcode = Serial.readStringUntil('\n');
    executeGCode(gcode);
  }
  
  // 演示模式
  static unsigned long lastMove = 0;
  if (millis() - lastMove > 5000) {
    demoMovement();
    lastMove = millis();
  }
}

void executeGCode(String gcode) {
  gcode.toUpperCase();
  gcode.trim();
  
  Serial.print("Executing: ");
  Serial.println(gcode);
  
  // 简单G代码解析
  if (gcode.startsWith("G01")) {  // 直线插补
    // 解析坐标参数
    int xPos = getParameter(gcode, 'X');
    int yPos = getParameter(gcode, 'Y');
    int zPos = getParameter(gcode, 'Z');
    
    // 控制电机移动
    stepper1.step(xPos);
    stepper2.step(yPos);
    stepper3.step(zPos);
  }
}

int getParameter(String gcode, char param) {
  int index = gcode.indexOf(param);
  if (index != -1) {
    return gcode.substring(index + 1).toInt();
  }
  return 0;
}

void demoMovement() {
  stepper1.step(100);
  stepper2.step(-100);
  stepper3.step(50);
  stepper4.step(-50);
  
  delay(1000);
  
  stepper1.step(-100);
  stepper2.step(100);
  stepper3.step(-50);
  stepper4.step(50);
}

7. 数据采集系统

7.1 多通道数据采集

// 16通道模拟数据采集
const int NUM_CHANNELS = 16;
const int SAMPLE_RATE = 100;  // Hz
const int BUFFER_SIZE = 1000;

int analogPins[NUM_CHANNELS] = {
  A0, A1, A2, A3, A4, A5, A6, A7,
  A8, A9, A10, A11, A12, A13, A14, A15
};

int dataBuffer[NUM_CHANNELS][BUFFER_SIZE];
int bufferIndex = 0;

void setup() {
  Serial.begin(115200);
  Serial.println("16-Channel Data Acquisition System");
  
  // 设置采样定时器
  setupSamplingTimer();
}

void loop() {
  // 主循环处理数据
  static unsigned long lastProcess = 0;
  if (millis() - lastProcess > 1000) {
    processData();
    lastProcess = millis();
  }
  
  // 检查串口命令
  if (Serial.available()) {
    String cmd = Serial.readStringUntil('\n');
    if (cmd == "DOWNLOAD") {
      downloadData();
    }
  }
}

void setupSamplingTimer() {
  // 使用定时器1设置100Hz采样率
  cli();  // 禁用中断
  
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;
  
  // 16MHz / (prescaler * (OCR1A + 1)) = 100Hz
  // prescaler = 256, OCR1A = 624
  OCR1A = 624;
  TCCR1B |= (1 << WGM12);  // CTC模式
  TCCR1B |= (1 << CS12);   // 256预分频
  TIMSK1 |= (1 << OCIE1A); // 启用定时器比较中断
  
  sei();  // 启用中断
}

ISR(TIMER1_COMPA_vect) {
  // 定时器中断,采集所有通道
  for (int ch = 0; ch < NUM_CHANNELS; ch++) {
    dataBuffer[ch][bufferIndex] = analogRead(analogPins[ch]);
  }
  
  bufferIndex++;
  if (bufferIndex >= BUFFER_SIZE) {
    bufferIndex = 0;  // 环形缓冲区
  }
}

void processData() {
  Serial.println("=== Data Summary ===");
  
  for (int ch = 0; ch < NUM_CHANNELS; ch++) {
    long sum = 0;
    int minVal = 1024, maxVal = 0;
    
    for (int i = 0; i < BUFFER_SIZE; i++) {
      int val = dataBuffer[ch][i];
      sum += val;
      if (val < minVal) minVal = val;
      if (val > maxVal) maxVal = val;
    }
    
    Serial.print("CH");
    Serial.print(ch);
    Serial.print(": Avg=");
    Serial.print(sum / BUFFER_SIZE);
    Serial.print(" Min=");
    Serial.print(minVal);
    Serial.print(" Max=");
    Serial.println(maxVal);
  }
}

void downloadData() {
  Serial.println("START_DATA");
  
  for (int i = 0; i < BUFFER_SIZE; i++) {
    for (int ch = 0; ch < NUM_CHANNELS; ch++) {
      Serial.print(dataBuffer[ch][i]);
      Serial.print(",");
    }
    Serial.println();
  }
  
  Serial.println("END_DATA");
}

7.2 SD卡数据记录

// 多传感器数据记录到SD卡
#include <SD.h>
#include <SPI.h>

#define CS_PIN 53      // Mega的默认SD卡CS引脚
#define LOG_INTERVAL 1000  // 记录间隔(毫秒)

File dataFile;
unsigned long lastLogTime = 0;

void setup() {
  Serial.begin(9600);
  
  // 初始化SD卡
  Serial.print("Initializing SD card...");
  
  if (!SD.begin(CS_PIN)) {
    Serial.println("Card failed, or not present");
    return;
  }
  Serial.println("card initialized.");
  
  // 创建新数据文件
  char filename[20];
  sprintf(filename, "DATA_%lu.CSV", millis() / 1000);
  
  dataFile = SD.open(filename, FILE_WRITE);
  if (dataFile) {
    // 写入CSV头部
    dataFile.println("Timestamp,Temp,Humidity,Light,Pressure,Current,Voltage,Power");
    dataFile.close();
    Serial.print("Logging to: ");
    Serial.println(filename);
  }
}

void loop() {
  if (millis() - lastLogTime >= LOG_INTERVAL) {
    logData();
    lastLogTime = millis();
  }
  
  // 其他处理...
  delay(10);
}

void logData() {
  // 读取所有传感器
  float temperature = readTemperature();
  float humidity = readHumidity();
  int lightLevel = analogRead(A0);
  float pressure = readPressure();
  float current = readCurrent();
  float voltage = readVoltage();
  
  // 打开文件并写入数据
  dataFile = SD.open("datalog.csv", FILE_WRITE);
  if (dataFile) {
    dataFile.print(millis());
    dataFile.print(",");
    dataFile.print(temperature);
    dataFile.print(",");
    dataFile.print(humidity);
    dataFile.print(",");
    dataFile.print(lightLevel);
    dataFile.print(",");
    dataFile.print(pressure);
    dataFile.print(",");
    dataFile.print(current);
    dataFile.print(",");
    dataFile.print(voltage);
    dataFile.print(",");
    dataFile.println(current * voltage);  // 功率
    
    dataFile.close();
    
    // 串口输出
    static int logCount = 0;
    Serial.print("Log #");
    Serial.print(++logCount);
    Serial.println(" saved");
  }
}

8. 显示系统

8.1 多显示屏控制

// 控制多个LCD/OLED显示屏
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// I2C LCD显示屏
LiquidCrystal_I2C lcd1(0x27, 20, 4);  // 20x4 LCD
LiquidCrystal_I2C lcd2(0x3F, 16, 2);  // 16x2 LCD

// OLED显示屏
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 oled1(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
Adafruit_SSD1306 oled2(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

void setup() {
  Serial.begin(9600);
  
  // 初始化LCD1
  lcd1.init();
  lcd1.backlight();
  lcd1.setCursor(0, 0);
  lcd1.print("System Status");
  
  // 初始化LCD2
  lcd2.init();
  lcd2.backlight();
  lcd2.setCursor(0, 0);
  lcd2.print("Sensor Data");
  
  // 初始化OLED1
  if (!oled1.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("OLED1 allocation failed"));
  }
  oled1.clearDisplay();
  oled1.setTextSize(1);
  oled1.setTextColor(SSD1306_WHITE);
  
  // 初始化OLED2
  if (!oled2.begin(SSD1306_SWITCHCAPVCC, 0x3D)) {
    Serial.println(F("OLED2 allocation failed"));
  }
  oled2.clearDisplay();
  oled2.setTextSize(1);
  oled2.setTextColor(SSD1306_WHITE);
  
  Serial.println("Multi-Display System Ready");
}

void loop() {
  // 更新LCD1
  updateLCD1();
  
  // 更新LCD2
  updateLCD2();
  
  // 更新OLED1
  updateOLED1();
  
  // 更新OLED2
  updateOLED2();
  
  delay(1000);
}

void updateLCD1() {
  static int counter = 0;
  lcd1.setCursor(0, 1);
  lcd1.print("Uptime: ");
  lcd1.print(millis() / 1000);
  lcd1.print("s    ");
  
  lcd1.setCursor(0, 2);
  lcd1.print("Counter: ");
  lcd1.print(counter++);
  lcd1.print("    ");
}

void updateLCD2() {
  float temp = readTemperature();
  float hum = readHumidity();
  
  lcd2.setCursor(0, 1);
  lcd2.print("T:");
  lcd2.print(temp, 1);
  lcd2.print("C H:");
  lcd2.print(hum, 0);
  lcd2.print("% ");
}

void updateOLED1() {
  oled1.clearDisplay();
  oled1.setCursor(0, 0);
  oled1.println("=== SYSTEM INFO ===");
  oled1.print("Free RAM: ");
  oled1.print(freeMemory());
  oled1.println(" bytes");
  oled1.print("Voltage: ");
  oled1.print(readVoltage());
  oled1.println(" V");
  oled1.display();
}

void updateOLED2() {
  int sensorValues[8];
  for (int i = 0; i < 8; i++) {
    sensorValues[i] = analogRead(A0 + i);
  }
  
  oled2.clearDisplay();
  oled2.setCursor(0, 0);
  oled2.println("Sensor Readings:");
  
  for (int i = 0; i < 4; i++) {
    oled2.print("A");
    oled2.print(i);
    oled2.print(":");
    oled2.print(sensorValues[i]);
    oled2.print(" ");
  }
  
  oled2.setCursor(0, 16);
  for (int i = 4; i < 8; i++) {
    oled2.print("A");
    oled2.print(i);
    oled2.print(":");
    oled2.print(sensorValues[i]);
    oled2.print(" ");
  }
  
  oled2.display();
}

9. 性能优化技巧

9.1 Mega专用优化

// 利用Mega的大内存和多个定时器
#include <TimerOne.h>
#include <TimerThree.h>
#include <TimerFour.h>

// 多定时器示例
void setup() {
  Serial.begin(115200);
  
  // 定时器1 - 1Hz(系统心跳)
  Timer1.initialize(1000000);  // 1秒
  Timer1.attachInterrupt(timer1ISR);
  
  // 定时器3 - 10Hz(传感器读取)
  Timer3.initialize(100000);   // 0.1秒
  Timer3.attachInterrupt(timer3ISR);
  
  // 定时器4 - 100Hz(PID控制)
  Timer4.initialize(10000);    // 0.01秒
  Timer4.attachInterrupt(timer4ISR);
  
  Serial.println("Multi-timer system started");
}

void timer1ISR() {
  // 系统状态监测
  static int counter = 0;
  Serial.print("Heartbeat ");
  Serial.println(counter++);
}

void timer3ISR() {
  // 读取所有传感器
  readAllSensors();
}

void timer4ISR() {
  // PID控制计算
  updatePID();
}

// DMA式数据复制(更快)
void fastMemoryCopy(void* dest, void* src, size_t n) {
  uint8_t* d = (uint8_t*)dest;
  uint8_t* s = (uint8_t*)src;
  
  while (n--) {
    *d++ = *s++;
  }
}

9.2 引脚直接操作

// Mega引脚分组(提高操作速度)
/*
PORT A: 22-29 (PORTA)   - PA0-PA7
PORT B: 53-47 (PORTB)   - PB0-PB7
PORT C: 37-30 (PORTC)   - PC0-PC7
PORT D: 7-0 (PORTD)     - PD0-PD7
PORT E: 8-12 (PORTE)    - PE0-PE4
PORT F: A0-A7 (PORTF)   - PF0-PF7
PORT G: 41-43 (PORTG)   - PG0-PG2
PORT H: 16-19 (PORTH)   - PH0-PH3
PORT J: 14,15 (PORTJ)   - PJ0-PJ1
PORT K: A8-A15 (PORTK)  - PK0-PK7
PORT L: 42-49 (PORTL)   - PL0-PL7
*/

// 快速控制多个LED
void setup() {
  // 设置PORT L全部为输出(引脚42-49)
  DDRL = 0xFF;  // 全部设为输出
}

void loop() {
  // 流水灯效果 - 直接操作寄存器
  for (int i = 0; i < 8; i++) {
    PORTL = 1 << i;  // 一次只点亮一个LED
    delay(100);
  }
  
  // 呼吸灯效果
  for (int brightness = 0; brightness < 256; brightness++) {
    analogWrite(9, brightness);  // PWM引脚
    delay(5);
  }
  for (int brightness = 255; brightness >= 0; brightness--) {
    analogWrite(9, brightness);
    delay(5);
  }
}

10. 综合项目:3D打印机控制器

// 3D打印机主控制器
#include <Stepper.h>
#include <Servo.h>
#include <SD.h>
#include <LiquidCrystal_I2C.h>

// 定义引脚
#define X_STEP_PIN 54
#define X_DIR_PIN 55
#define X_ENABLE_PIN 38

#define Y_STEP_PIN 60
#define Y_DIR_PIN 61
#define Y_ENABLE_PIN 56

#define Z_STEP_PIN 46
#define Z_DIR_PIN 48
#define Z_ENABLE_PIN 62

#define E0_STEP_PIN 26
#define E0_DIR_PIN 28
#define E0_ENABLE_PIN 24

#define HEATER_PIN 10
#define FAN_PIN 9
#define BED_HEATER_PIN 8

#define TEMP_PIN A0
#define BED_TEMP_PIN A1

#define SD_CS_PIN 53

// 创建对象
LiquidCrystal_I2C lcd(0x27, 20, 4);

void setup() {
  Serial.begin(115200);
  Serial1.begin(115200);  // 用于触摸屏
  
  // 初始化LCD
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("3D Printer Ready");
  
  // 初始化步进电机引脚
  pinMode(X_STEP_PIN, OUTPUT);
  pinMode(X_DIR_PIN, OUTPUT);
  pinMode(X_ENABLE_PIN, OUTPUT);
  
  pinMode(Y_STEP_PIN, OUTPUT);
  pinMode(Y_DIR_PIN, OUTPUT);
  pinMode(Y_ENABLE_PIN, OUTPUT);
  
  pinMode(Z_STEP_PIN, OUTPUT);
  pinMode(Z_DIR_PIN, OUTPUT);
  pinMode(Z_ENABLE_PIN, OUTPUT);
  
  // 启用电机驱动器
  digitalWrite(X_ENABLE_PIN, LOW);
  digitalWrite(Y_ENABLE_PIN, LOW);
  digitalWrite(Z_ENABLE_PIN, LOW);
  
  // 初始化加热器和风扇
  pinMode(HEATER_PIN, OUTPUT);
  pinMode(FAN_PIN, OUTPUT);
  pinMode(BED_HEATER_PIN, OUTPUT);
  
  // 初始化SD卡
  if (!SD.begin(SD_CS_PIN)) {
    lcd.setCursor(0, 1);
    lcd.print("SD Card Error    ");
  } else {
    lcd.setCursor(0, 1);
    lcd.print("SD Card OK       ");
  }
  
  delay(2000);
  lcd.clear();
}

void loop() {
  // 主状态机
  static int state = 0;
  
  switch (state) {
    case 0:  // 空闲状态
      idleState();
      break;
      
    case 1:  // 加热状态
      heatingState();
      break;
      
    case 2:  // 打印状态
      printingState();
      break;
      
    case 3:  // 完成状态
      finishState();
      break;
  }
  
  // 检查命令
  checkCommands();
}

void idleState() {
  updateDisplay("Ready", "Temp: ", getTemperature(), "Bed: ", getBedTemperature());
  
  if (Serial.available()) {
    String cmd = Serial.readStringUntil('\n');
    if (cmd == "START_PRINT") {
      state = 1;  // 进入加热状态
    }
  }
}

void heatingState() {
  updateDisplay("Heating", "Target: 200C", "Current: ", getTemperature());
  
  // PID加热控制
  controlHeater(200);  // 目标温度200°C
  controlBedHeater(60); // 热床目标60°C
  
  if (abs(getTemperature() - 200) < 5 && abs(getBedTemperature() - 60) < 5) {
    state = 2;  // 进入打印状态
  }
}

void printingState() {
  static File gcodeFile;
  static bool fileOpened = false;
  
  if (!fileOpened) {
    gcodeFile = SD.open("print.gcode");
    if (gcodeFile) {
      fileOpened = true;
    }
  }
  
  if (gcodeFile.available()) {
    String line = gcodeFile.readStringUntil('\n');
    executeGCode(line);
  } else {
    state = 3;  // 进入完成状态
    gcodeFile.close();
    fileOpened = false;
  }
  
  updateDisplay("Printing", "Progress: ", getProgress(), "%");
}

void executeGCode(String line) {
  // 解析和执行G代码
  if (line.startsWith("G1")) {
    // 移动命令
    float x = getParam(line, 'X');
    float y = getParam(line, 'Y');
    float z = getParam(line, 'Z');
    float e = getParam(line, 'E');
    float f = getParam(line, 'F');
    
    moveTo(x, y, z, e, f);
  } else if (line.startsWith("M104")) {
    // 设置温度
    float s = getParam(line, 'S');
    setHotendTemp(s);
  }
}

void moveTo(float x, float y, float z, float e, float f) {
  // 计算步进电机步数并移动
  // 这里实现运动控制逻辑
}

void checkCommands() {
  if (Serial.available()) {
    String cmd = Serial.readStringUntil('\n');
    cmd.trim();
    
    if (cmd == "PAUSE") {
      // 暂停打印
    } else if (cmd == "RESUME") {
      // 恢复打印
    } else if (cmd == "STOP") {
      // 停止打印
      state = 0;
    }
  }
}

void updateDisplay(String line1, String line2, float val1, String line3, float val2) {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(line1);
  lcd.setCursor(0, 1);
  lcd.print(line2);
  lcd.print(val1);
  lcd.setCursor(0, 2);
  lcd.print(line3);
  lcd.print(val2);
}

总结

Arduino Mega 2560 主要应用场景:

  1. 需要大量I/O的项目

    • 3D打印机
    • CNC机器
    • 机器人控制系统
    • 大型LED阵列
  2. 多通信接口需求

    • 物联网网关
    • 数据采集系统
    • 工业控制器
  3. 大内存需求

    • 数据记录器
    • 复杂算法处理
    • 图像处理
  4. 多任务系统

    • 实时控制系统
    • 多传感器融合
    • 复杂状态机

选择建议

  • 如果项目需要超过14个数字IO或6个模拟输入,选择Mega
  • 如果需要多个串口与其他设备通信,选择Mega
  • 如果程序超过30KB或需要处理大量数据,选择Mega
  • 对于简单项目,UNO更经济实惠

Mega的强大功能使其成为复杂电子项目的理想选择!

posted @ 2026-01-02 16:56  ukyo--碳水化合物  阅读(2)  评论(0)    收藏  举报