Contents
书接上文
昨天已经hello world了,我们已经进入了嵌入式开发的世界。
发现问题
很多场景,需要将配置信息保存到板子上,即使断电也无妨。如何搞呢?
找答案
搜索发现:
- arduino 的所有板子都内置有“电可擦可编程只读存储器”–一种掉电后数据不丢失的存储芯片。英文简称:EEPROM (Electrically Erasable Programmable Read-Only Memory)。以我手里的r3为例,就有1K的存储空间。
- Arduino 提供了类库:EEPROM,实现将数据持久化到存储芯片中。
- EEPROM API,只能将【字节型】的数据的存入EEPROM,也就是一次只能写入1个字节。如果要存储多个字节的数据类型,又需要怎么做呢?
实践
我今天要做的就是实现浮点型数据的存、取类库,如何写一个类库呢?
哈哈,官网有完美教程
我先根据教程实现了它的官方示例类库:Morse(让LED闪出SOS信号)。
再来实现我的类库,哈哈
技术方案选型
搜索到了一篇文章,文中介绍,用“共用体”可以方便实现浮点型数据的存、取;
了解一下技术概念
共用体
:将几个不同(类型不同,但长度相同)的变量放到同一段内存中,共同占用这一段内存数据,使各变量的内存数据始终保持一致。
例如:一个float类型的数据,需要占用4个字节的存储空间。因此我们可以把一个float拆分为4个字节,然后逐字节的写入EEPROM,来达到保存float数据的目的。但是手动计算的话,比较麻烦。
这里我们使用共用体,通过其它数据结果,快捷的把float数据拆分为4个字节。
- 首先定义一个名为data的共用体结构,共用体中有两个类型不同的成员变量:
union data { float a; // 浮点型,占用4个字节 byte b[4]; // 字节型数组,占用4个字节。 // 这两个类型的变量都是占用4个字节, // 且是相同的4个字节,所以能始终保持数据一致, // 其中一个变了,另一个也随之改变。 };
- 再申明一个data类型的变量col:
data col;
- 现在你可以通过 col.a 访问这个共用体中的 float 类型成员 a,也可以通过 col.b 访问这个共用体中的 byte 类型成员 b。
col.a 和 col.b 共同占用四个字节的地址。
给 col.a 赋值后,通过 col.b 即可拆分 float 为4个字节。
好了,了解了“共同体”,我们来写这个类库吧。
首先定义.h文件(头文件)
写C的人对这个都很熟悉(写java的也不陌生,哈哈,毕竟我们初学编程语言时,也接触了C);
FloatEepRom.h
/**
* FloatEepRom.h - Library for writing float data to EEPROM.
* Created by Fick Song, Ma6 31, 2018.
* For personal use.
* 用于持久化/读取浮点型数据
*/
#ifndef FloatEepRom_h
#define FloatEepRom_h
#include "Arduino.h"
union FloatUnionData
{
float f; // 浮点型,占用4个字节
byte b[4]; // 字节型数组,占用4个字节。
};
class FloatEepRom
{
public:
FloatEepRom(void);
void writeFloat(int addr,float value);
float readFloat(int addr);
};
#endif
接着是cpp文件
FloatEepRom.cpp
/*
* FloatEepRom.cpp - Library for flashing Morse code.
* Created by Fick Song, May 31, 2018.
* For testing Library creating.
*/
#include "Arduino.h"
#include "FloatEepRom.h"
#include <EEPROM.h>
FloatEepRom::FloatEepRom()
{}
void FloatEepRom::writeFloat(int addr,float value)
{
if((addr + 4) >= EEPROM.length()){
return;
}
FloatUnionData data;
data.f = value;
for(int i=0;i<4;i++)
EEPROM.update(addr + i, data.b[i]);
}
float FloatEepRom::readFloat(int addr)
{
if((addr + 4) >= EEPROM.length()){
return 0.0;
}
FloatUnionData data;
for(int i=0;i<4;i++){
data.b[i]=EEPROM.read(addr + i);
}
return data.f;
}
然后是keywords.txt文件
keywords.txt
FloatEepRom KEYWORD1
writeFloat KEYWORD2
readFloat KEYWORD2
如果没有这个文件,在IDE里用我们的类库及方法时,不会有高亮提示,加了这个文件,就行了。
其中KEYWORD1表示,FloatEepRom是个类;
KEYWORD2表示,writeFloat,readFloat是方法,IDE就会根据规则高亮显示成黄色和灰色;
注意,文件中每一行中间是用制表符分隔的。不是空格。
将文件放入类库目录
- 先创建一个文件夹FloatEepRom(可以自定义文件夹的名字),将上述三个文件放进来;
- 将上述文件夹整体放入Arduino IDE的类库文件夹下,我的mac,目录是“/Users/xxx/Library/Arduino15/packages/arduino/hardware/avr/1.6.21/libraries”,
加到这个目录下,IDE会显示为“内置类库”;另外一个目录是“/Users/xxxx/Documents/Arduino/libraries”,这个目录是用户自定义类库的路径;如果想找到内置类库目录,打开Arduino IDE软件,打开首选项页面,再根据配置文件所在目录往下找,就可以找到了。
点击配置文件,进入其所在目录
在往下找即可,直到libraries,即是放类库的地方。
OK了,类库已经完成了。重启IDE就能用它了。
2018.05.31