数据存储器是一块2KB大小的静态随机存储器(SRAM)。其中一部分空间分配给了通用寄存器和I/O寄存器,其余部分一般用于存储全局变量,堆栈数据和支持动态内存分配。它的存取速度快,但掉电后数据会丢失。
程序存储器是一块32KB大小的闪存(Flash),其中0.5KB用于引导程序。它可以多次擦写,掉电后数据不会丢失,一般用于存储程序。
电可擦写可编程只读存储器(EEPROM)是一块1KB大小的独立数据存储空间。它和程序存储器一样可以用于保存程序运行中的数据,但在掉电后数据不会丢失。
Arduino IDE提供了几个EEPROM的示例,eeprom_write示例将0引脚上的模拟信号转换为数字信号,并将转换结果以字节的形式保存到EEPROM中:
// eeprom_write.ino
#include 《eeprom.h》
  
int addr = 0;
 
void setup() {
}
 
void loop() {
   int val = analogRead(0) / 4;
 
   EEPROM.write(addr, val);
 
   addr = addr + 1;
   if (addr == EEPROM.length()) {
     addr = 0;
   }
 
   delay(100);
}
和eeprom_write示例相反,eeprom_read示例将EEPROM中的数据以字节的形式读出,并打印到串口0上:
// eeprom_read.ino
#include 《eeprom.h》
int address = 0;
byte value;
 
void setup() {
   Serial.begin(9600);
   while (!Serial) {
     ;
   }
}
 
void loop() {
   value = EEPROM.read(address);
 
   Serial.print(address);
   Serial.print("\t");
   Serial.print(value, DEC);
   Serial.println();
 
   address = address + 1;
   if (address == EEPROM.length()) {
     address = 0;
   }
 
   delay(500);
}
与EEPROM相关的Arduino库函数有:
EEPROM.write(address, val):向EEPROM指定地址写入一个字节的数据
address:指定数据写入的地址
val:写入的数据
EEPROM.read(address):从EEPROM指定地址读出一个字节的数据
address:指定数据读取的地址
函数返回读取的一个字节数据
EEPROM.length():获取EEPROM大小
函数返回EEPROM的大小
ATMega328P的EEPROM由3个寄存器控制,EEPROM地址寄存器(EEARH和EEARL)和EEPROM数据寄存器EEDR分别用于在写入或读取EEPROM时保存地址信息和数据信息。EEPROM控制寄存器EECR的结构如下图所示:
|  |  | EEPM1 | EEPM0 | EERIE | EEMPE | EEPE | EERE | 
将EEPROM主机写使能位EEMPE置1后,4个时钟周期内将EEPROM写使能位EEPE置1,就可以数据写入EEPROM的指定地址中;向EEPROM读使能位EERE写入1,则可以将EEPROM指定地址的数据读入EEDR寄存器中。
通过直接访问寄存器改写以上程序为:
// eeprom_write_reg.ino
#include <EEPROM.h>
int addr = 0;
void eeprom_write(int address, byte val);
void setup() {
}
void loop() {
  int val = analogRead(0) / 4;
  eeprom_write(addr, val);
  addr = addr + 1;
  if (addr == EEPROM.length()) {
    addr = 0;
  }
  delay(100);
}
void eeprom_write(int address, byte val) {
  while (EECR & (1 << EEPE));
  EEAR = address;
  EEDR = val;
  EECR |= (1 << EEMPE);
  EECR |= (1 << EEPE);
}
// eeprom_read.ino
#include <EEPROM.h>
int address = 0;
byte value;
byte eeprom_read(int address);
void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ;
  }
}
void loop() {
  value = eeprom_read(address);
  Serial.print(address);
  Serial.print("\t");
  Serial.print(value, DEC);
  Serial.println();
  address = address + 1;
  if (address == EEPROM.length()) {
    address = 0;
  }
  delay(500);
}
byte eeprom_read(int address) {
  while (EECR & (1 << EEPE));
  EEAR = address;
  EECR |= (1 << EERE);
  return EEDR;
} 
            四位数码管是一种常见的LED显示器件,主要用于显示数字信息。
Arduino-ESP32与ESP-IDF的版本对应表。
Arduino+ESP32上使用TFT_eSPI库快速点亮这个屏幕,驱动芯片ST7789
Queue 库提供了一个通用的 C++ 动态队列实现,专为在 Arduino 项目中使用而定制。
 
            本程序是小鹏物联网智能浇花套件的单机版程序(不连接物联网),供同学们参考。
 
            ArrayList 类是一个 C++ 模板类,它提供了 ArrayList 的实现,以便轻松存储任何指定类型的值。它允许使用索引进行高效存储和检索,支持排序操作。
 
            ESP32系列(包括ESP32-S3)搭载Xtensa双核处理器,默认情况下Arduino框架仅使用单核运行用户代码,通过多核编程,可以充分利用硬件资源来提升系统响应和性能。
在本文中,先解释 MSB(最高有效位)和 LSB(最低有效位)的概念,以及 MSBFIRST 和 LSBFIRST。然后展示了 MSBFIRST 和 LSBFIRST 的使用如何影响移位寄存器的输出。
TB6612是一款双路H桥型的直流电机驱动芯片,可以驱动两个直流电机并且控制其转速与方向,输入电压在3V~12V,因此在集成化、小型化的电机控制系统中,它可以作为理想的电机驱动器件。
 
            Arduino-ESP32项目提供的Preferences库是一个专为ESP32设计的非易失性存储解决方案,它替代了传统的Arduino EEPROM库,提供了更强大、更可靠的数据存储功能。
用于Arduino的Adafruit_GFX库为我们所有的LCD和OLED显示器提供了通用语法和图形功能集。这使Arduino程序可以轻松地在显示类型之间进行调整,而不必花太多精力……
