第6讲 内存子系统

Arduino UNO R3主处理器ATMega328P的芯片内部拥有3种存储器:数据存储器,程序存储器和电可擦写可编程存储器,它们各自有不同的用途。

1. 数据存储器

  数据存储器是一块2KB大小的静态随机存储器(SRAM)。其中一部分空间分配给了通用寄存器和I/O寄存器,其余部分一般用于存储全局变量,堆栈数据和支持动态内存分配。它的存取速度快,但掉电后数据会丢失。

2. 程序存储器

  程序存储器是一块32KB大小的闪存(Flash),其中0.5KB用于引导程序。它可以多次擦写,掉电后数据不会丢失,一般用于存储程序。

3. 电可擦可编程只读存储器

  电可擦写可编程只读存储器(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的大小


  ATMega328PEEPROM3个寄存器控制,EEPROM地址寄存器(EEARHEEARLEEPROM数据寄存器EEDR分别用于在写入或读取EEPROM时保存地址信息和数据信息。EEPROM控制寄存器EECR的结构如下图所示:



EEPM1

EEPM0

EERIE

EEMPE

EEPE

EERE

EEPROM主机写使能位EEMPE1后,4个时钟周期内将EEPROM写使能位EEPE1,就可以数据写入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;
}


 


评论:
相关文章

ESP32 使用DAC模拟输出完成两路呼吸灯

ESP32的DAC函数可以实现真正的模拟输出。


在 ESP32 上使用 LEDC (PWM)

ESP32 没有Arduino输出 PWM 的 analogWrite(pin, value) 方法,取而代之的 ESP32 有一个 LEDC 来实现PWM功能。


Arduino UNO R4 WiFi 官方介绍文档

本文档作为UNO R4 WiFi的技术概览,您将找到一系列资源和指南链接,帮助您开始下一个项目。


OneButton: 用于使用单个按钮进行多用途输入的Arduino库

Arduino OneButton库是一个用于简化按钮操作的库,它可以轻松地处理按钮的单击、双击和长按等操作。适用于Arduino开发板以及ESP32等其他基于Arduino的开发板。