Arduino Nano Every

元器件
开发板
库存 180

介绍

Arduino Nano系列的升级版,基于ATmega4809主控,5V/20MHz,48KB Flash,6KB SRAM,256B EEPROM,14路数字IO(6路PWM,全部可作外部中断),8路10位ADC,Micro-USB接口。相比经典Nano:更大的Flash和SRAM、更强的PWM、所有IO均可中断、内置硬件乘法器。尺寸与经典Nano完全兼容(18×45mm),代码迁移无缝

规格参数

参数
I2C1路(A4=SDA,A5=SCL)
SPI1路
SRAM6KB
Flash48KB
EEPROM256B
串口1路硬UART
主频20MHz内部振荡器
尺寸18mm×45mm
重量约6g
数字IO14路(全部支持外部中断,6路PWM)
USB接口Micro-USB
板载LEDD13
bootloaderOptiboot(Atmel SAMD11桥接)
主控芯片ATmega4809
工作电压5V DC
模拟输入8路(A0-A7,10位ADC)
输入电压7-18V(推荐7-12V)

代码例程

Arduino Nano Every — 代码例程.md
# Arduino Nano Every (ATmega4809) 代码例程

## 例程 1:Flash 模拟 EEPROM(替代 256B 硬件 EEPROM 不够用)

```cpp
// Nano Every - FlashStorage 库实现大容量非易失存储
// 安装: 库管理器搜索 "FlashStorage" by Arduino

#include <FlashStorage.h>

// 定义存储结构(最大Flash一页=256B)
struct ConfigData {
    uint8_t  magic;         // 校验字
    uint32_t bootCount;
    float    calibration;
    char     deviceName[32];
};

// 声明Flash存储对象(变量名即标识符)
FlashStorage(flash_config, ConfigData);

ConfigData config;

void setup() {
    Serial.begin(115200);
    delay(500);
    
    // 读取Flash
    config = flash_config.read();
    
    // 检查是否首次启动(magic校验)
    if (config.magic != 0xAA) {
        Serial.println("First boot! Initializing config...");
        config.magic = 0xAA;
        config.bootCount = 0;
        config.calibration = 1.0f;
        strcpy(config.deviceName, "Every-001");
    }
    
    config.bootCount++;
    Serial.print("Boot count: ");
    Serial.println(config.bootCount);
    
    // 写回Flash
    flash_config.write(config);
    Serial.println("Config saved to Flash.");
}

void loop() {
    // Flash写次数有限(~10,000次),不要在loop中频繁写入
}
```

---

## 例程 2:全部14路外部中断演示

```cpp
// Nano Every - 多路外部中断演示
// Every 所有 14 个数字 IO 均支持外部中断!

volatile int interruptCounts[14] = {0};
const int PINS[14] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13};

// D0/D1 为串口引脚,演示时注意不要冲突
void isr0()  { interruptCounts[0]++; }
void isr1()  { interruptCounts[1]++; }
void isr2()  { interruptCounts[2]++; }
void isr3()  { interruptCounts[3]++; }
void isr4()  { interruptCounts[4]++; }
void isr5()  { interruptCounts[5]++; }
void isr6()  { interruptCounts[6]++; }
void isr7()  { interruptCounts[7]++; }
void isr8()  { interruptCounts[8]++; }
void isr9()  { interruptCounts[9]++; }
void isr10() { interruptCounts[10]++; }
void isr11() { interruptCounts[11]++; }
void isr12() { interruptCounts[12]++; }
void isr13() { interruptCounts[13]++; }

void (*isrList[14])() = {isr0,isr1,isr2,isr3,isr4,isr5,isr6,isr7,
                         isr8,isr9,isr10,isr11,isr12,isr13};

void setup() {
    Serial.begin(115200);
    
    // 以 D2-D7 为例配置中断(避开串口D0/D1)
    for (int i = 2; i <= 7; i++) {
        pinMode(PINS[i], INPUT_PULLUP);
        attachInterrupt(digitalPinToInterrupt(PINS[i]), isrList[i], FALLING);
    }
    
    Serial.println("Multi-interrupt demo. Ground pins D2-D7 to trigger.");
}

void loop() {
    static unsigned long lastPrint = 0;
    if (millis() - lastPrint > 1000) {
        lastPrint = millis();
        Serial.println("--- Interrupt Counts ---");
        for (int i = 2; i <= 7; i++) {
            Serial.print("D"); Serial.print(i);
            Serial.print(": "); Serial.println(interruptCounts[i]);
        }
    }
}
```

---

## 例程 3:TCA0 定时器高精度PWM

```cpp
// Nano Every - TCA0 高精度PWM(16位,最高65535级)
// 相比经典Nano 8位(0-255),精度大幅提升

void setup() {
    Serial.begin(115200);
    
    // 使用 Arduino 标准 API 即可(内部自动使用 TCA0)
    pinMode(9, OUTPUT);
    pinMode(10, OUTPUT);
}

void loop() {
    // 16位渐变(0-65535),但 analogWrite 仍为 8 位 API
    // 如需16位分辨率,直接操作 TCA0 寄存器:
    
    // 配置 TCA0 为 16 位模式,D9(W0) D10(W1)
    TCA0.SINGLE.CTRLB = TCA_SINGLE_WGMODE_SINGLESLOPE_gc | TCA_SINGLE_CMP0EN_bm;
    TCA0.SINGLE.PER = 65535;  // 16 位分辨率
    
    // 16位呼吸灯
    for (uint16_t duty = 0; duty < 65535; duty += 256) {
        TCA0.SINGLE.CMP0 = duty;
        delayMicroseconds(500);
    }
    for (uint16_t duty = 65535; duty > 0; duty -= 256) {
        TCA0.SINGLE.CMP0 = duty;
        delayMicroseconds(500);
    }
}
```

---

## 例程 4:超低功耗睡眠模式

```cpp
// Nano Every - 休眠与唤醒(功耗降至 μA 级)
#include <avr/sleep.h>

const int WAKE_PIN = 2;  // 唤醒引脚

void setup() {
    Serial.begin(115200);
    delay(1000);
    
    pinMode(WAKE_PIN, INPUT_PULLUP);
    pinMode(13, OUTPUT);
    digitalWrite(13, HIGH);
    
    Serial.println("Entering sleep in 3 seconds...");
    Serial.println("Pull D2 LOW to wake up.");
    delay(3000);
    
    // 配置唤醒源(D2 下降沿)
    attachInterrupt(digitalPinToInterrupt(WAKE_PIN), wakeISR, FALLING);
    
    // 进入 Power-Down 模式
    Serial.println("Sleeping now... (will resume after wake)");
    Serial.flush();
    
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    sleep_enable();
    sleep_cpu();  // ← CPU 在此处停止
    
    // --- 唤醒后从下面继续执行 ---
    sleep_disable();
    digitalWrite(13, LOW);
    Serial.println("Woke up!");
}

void wakeISR() {
    // 仅用于唤醒,无需操作
}

void loop() {
    Serial.print("Working... uptime: ");
    Serial.println(millis());
    delay(2000);
    
    // 再次休眠
    Serial.println("Sleeping again...");
    Serial.flush();
    sleep_enable();
    sleep_cpu();
    sleep_disable();
    Serial.println("Woke again!");
}
```

---

## 例程 5:高速 ADC 连续采样(4809 支持 150ksps)

```cpp
// Nano Every - ADC 连续采样(ATmega4809 ADC 最高 150ksps)
#define ADC_BUFFER_SIZE 256

volatile uint16_t adcBuffer[ADC_BUFFER_SIZE];
volatile uint8_t  adcIndex = 0;
volatile bool     adcComplete = false;

void setup() {
    Serial.begin(115200);
    
    // 配置 ADC0 自由运行模式(Free-Running)
    ADC0.CTRLA = ADC_ENABLE_bm | ADC_FREERUN_bm;   // 使能 + 自由运行
    ADC0.CTRLB = ADC_PRESC_DIV4_gc;                 // 预分频=4
    ADC0.CTRLC = ADC_REFSEL_VDD_gc;                 // 基准=VDD(5V)
    ADC0.CTRLE = 64;                                 // 采样持续时间
    ADC0.MUXPOS = ADC_MUXPOS_AIN0_gc;               // A0 输入
    ADC0.INTCTRL = ADC_RESRDY_bm;                    // 结果就绪中断
    ADC0.COMMAND = ADC_STCONV_bm;                    // 开始转换
}

// ADC 结果就绪中断
ISR(ADC0_RESRDY_vect) {
    adcBuffer[adcIndex] = ADC0.RES;
    adcIndex++;
    if (adcIndex >= ADC_BUFFER_SIZE) {
        adcIndex = 0;
        adcComplete = true;
        ADC0.CTRLA &= ~ADC_ENABLE_bm;  // 停止ADC
    }
}

void loop() {
    if (adcComplete) {
        adcComplete = false;
        
        // 输出采样数据
        Serial.println("--- ADC Buffer (256 samples) ---");
        for (int i = 0; i < ADC_BUFFER_SIZE; i++) {
            float voltage = adcBuffer[i] * (5.0f / 1023.0f);
            Serial.println(voltage, 3);
        }
        
        // 重新启动
        adcIndex = 0;
        ADC0.CTRLA |= ADC_ENABLE_bm;
        ADC0.COMMAND = ADC_STCONV_bm;
    }
}
```

> **编译提示**:Arduino IDE → `Tools → Board → Arduino Nano Every`,需安装 `Arduino megaAVR Boards`。上述代码中直接操作寄存器的部分(例程3/5)为 ATmega4809 特有,无法在经典 Nano 上运行。

参考资料

暂无参考文献