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 主要应用场景:
-
需要大量I/O的项目:
- 3D打印机
- CNC机器
- 机器人控制系统
- 大型LED阵列
-
多通信接口需求:
- 物联网网关
- 数据采集系统
- 工业控制器
-
大内存需求:
- 数据记录器
- 复杂算法处理
- 图像处理
-
多任务系统:
- 实时控制系统
- 多传感器融合
- 复杂状态机
选择建议:
- 如果项目需要超过14个数字IO或6个模拟输入,选择Mega
- 如果需要多个串口与其他设备通信,选择Mega
- 如果程序超过30KB或需要处理大量数据,选择Mega
- 对于简单项目,UNO更经济实惠
Mega的强大功能使其成为复杂电子项目的理想选择!
本文来自博客园,作者:ukyo--碳水化合物,转载请注明原文链接:https://www.cnblogs.com/ukzq/p/19432328

浙公网安备 33010602011771号