搜索
bottom↓
回复: 26

【分享】分享C++运算符重载的典范:Arduino访问EEPROM

[复制链接]

出200入2554汤圆

发表于 2020-8-4 03:40:11 | 显示全部楼层 |阅读模式
偶然间翻看 Arduino 访问 AVR-EEPROM 库源码,发现其 C++ 运算符重载封装非常巧妙,特来分享之。

从 Arduino IDE 当中拷贝出源码如下(C++):

对比几种常见的 EEPROM 访问方式,可以看到封装的魔力。
假定有需求:读取 EEPROM-04H 的字节,加 1 以后存入 EEPROM-08H 位置。

访问方式1(C寄存器),对于 AVR 来说就是 EEAR EEDR EECR 三个寄存器转来转去:

  EEAR= 0x04;
  EECR= ...;
  unsigned char tmp= EEDR;
  EEAR= 0x08;
  EEDR= tmp+1;
  EECR= ...;

访问方式2(C库),C库封装屏蔽了寄存器内容,但是引入了读写函数:

  EEPROMwrite(0x08, EEPROMread(0x04) +1);

访问方式3(C++库),C++库连读写函数都屏蔽了,只剩下 C 样子的运算符:

  EEPROM[0x08]= EEPROM[0x04] +1;

上述访问方式 3,就是 Arduino 进行 C++ 封装后的样子,全局出现了一个 EEPROM 数组,可以使用 [ ] 对其元素进行赋值、运算、比较。
C指针无法解决的问题(EEPROM 地址空间与 RAM 不通用),放在 C++ 里配合运算符重载,分分钟把 EEPROM 抽象成一个广义数组。

说是封装的过程晦涩难懂(可以去看源码,一眼望去简直天书),但用起来简直返璞归真。
这里还只是 AVR 片上的 EEPROM 访问,从寄存器一路封装到原始运算符;
如果是 24C01 这样 I2C 器件,做成 C 库后再重载 C++ 运算符,直接就是硬件抽象层(HAL),应用层代码一行不改。

-------------------------------------------------------------------------------------------------------------------------

以上,分享 Arduino 访问 AVR-EEPROM 的 C++ 库,其运算符重载非常巧妙可供借鉴。个人一点愚见,欢迎大家指点。

最后祝大家身体健康,工作顺利!


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出105入79汤圆

发表于 2020-8-4 04:52:09 | 显示全部楼层
超赞 , 十年前看不起Arduino,十年后仰望Arduino  

出10入284汤圆

发表于 2020-8-4 07:20:17 来自手机 | 显示全部楼层
qwe2231695 发表于 2020-8-4 04:52
超赞 , 十年前看不起Arduino,十年后仰望Arduino

现在看不起 看不起Arduino 的人

出0入4汤圆

发表于 2020-8-4 12:12:19 | 显示全部楼层
就一个头文件吗

出0入0汤圆

发表于 2020-8-4 12:22:55 | 显示全部楼层
怎一个牛逼了得

出615入1076汤圆

发表于 2020-8-4 12:37:09 来自手机 | 显示全部楼层
喜欢 方式 2,方式 3 用着没安全感(怕遇到 bug 不好调试),且扩展性不好,譬如,如果是 flash 这种介质,如何操作?

出200入2554汤圆

 楼主| 发表于 2020-8-4 12:47:24 | 显示全部楼层
dukelec 发表于 2020-8-4 12:37
喜欢 方式 2,方式 3 用着没安全感(怕遇到 bug 不好调试),且扩展性不好,譬如,如果是 flash 这种介质, ...

方式 2 成熟不容易出错,这个是事实;

说方式 3 扩展性不好的,你是认真的么? FLASH 也可以封装到 C++ 层啊,SPM 指令一路封装上去,照样数组访问。
C++ 的优势在于高层的移植性,代价是封装上去需要功力

出200入2554汤圆

 楼主| 发表于 2020-8-4 12:48:39 | 显示全部楼层

封装这个库的人,简直把 C++ 各种特性用到了极致

出200入2554汤圆

 楼主| 发表于 2020-8-4 12:49:14 | 显示全部楼层
ztrx 发表于 2020-8-4 12:12
就一个头文件吗

就一个头文件,连实现都在里边了

出615入1076汤圆

发表于 2020-8-4 12:54:21 来自手机 | 显示全部楼层
t3486784401 发表于 2020-8-4 12:47
方式 2 成熟不容易出错,这个是事实;

说方式 3 扩展性不好的,你是认真的么? FLASH 也可以封装到 C++  ...

如果操作 flash,封裝了之後,什麼時候擦除 Page?什麼時候 sync?不用用戶處理?

說回 i2c 接口的 EEPROM,協議可以一次讀寫多字節,包裝成數組之後,怎麼區分一次讀寫一個字節,還是多個字節?

Linux 內核那麼龐大複雜,都能乾淨清爽的用 C 實現,我實在找不到 MCU 使用 C++ 的理由。。。

出200入2554汤圆

 楼主| 发表于 2020-8-4 16:44:07 | 显示全部楼层
dukelec 发表于 2020-8-4 12:54
如果操作 flash,封裝了之後,什麼時候擦除 Page?什麼時候 sync?不用用戶處理?

說回 i2c 接口的 EEPR ...

C++ 是拿前人代码,快速做出样机的;C 则是慢慢打磨,优化效率的。

封装 FLASH 写入也许效率不高;但封装 FLASH 读取完全可以有很好的效率。
I2C 拿来重载运算符有何不可?至少我 1L 类库的全部接口都可以做到兼容封装。

出615入1076汤圆

发表于 2020-8-4 19:22:59 | 显示全部楼层
t3486784401 发表于 2020-8-4 16:44
C++ 是拿前人代码,快速做出样机的;C 则是慢慢打磨,优化效率的。

封装 FLASH 写入也许效率不高;但封 ...
I2C 拿来重载运算符有何不可?至少我 1L 类库的全部接口都可以做到兼容封装。


那你是每次都寫一個字節?譬如我想同時寫 20 個字節到 i2c eeprom,且只用一條 i2c 命令,可以做到嗎?

出200入2554汤圆

 楼主| 发表于 2020-8-4 20:01:49 | 显示全部楼层
dukelec 发表于 2020-8-4 19:22
那你是每次都寫一個字節?譬如我想同時寫 20 個字節到 i2c eeprom,且只用一條 i2c 命令,可以做到嗎? ...

运行的高效,和代码的灵活是矛盾的。

试问 20 个字节如果跨了页面边界,你的 C 能用一条 i2c 搞定么?
纠结这个,不如看看别人怎么用 EEPROM ,例如做文件系统

出615入1076汤圆

发表于 2020-8-4 20:26:14 来自手机 | 显示全部楼层
t3486784401 发表于 2020-8-4 20:01
运行的高效,和代码的灵活是矛盾的。

试问 20 个字节如果跨了页面边界,你的 C 能用一条 i2c 搞定么?

我的錯,專門去瞄了一眼 at24c02 手冊,單次讀數據長度沒限制,單次最多寫 8 字節數據,且不能超過 8 字節對齊(一頁 8 字節)。

上述 20 個字節至少寫 3 次,讀至少只用 1 次。

但是,我還是不能接受包裝成數組之後,一次只讀寫一個字節,效率太低了。。。

出200入2554汤圆

 楼主| 发表于 2020-8-4 20:44:31 | 显示全部楼层
dukelec 发表于 2020-8-4 20:26
我的錯,專門去瞄了一眼 at24c02 手冊,單次讀數據長度沒限制,單次最多寫 8 字節數據,且不能超過 8 字 ...

封装个 uint32_t 或者 uint64_t 的读写接口/运算符,就可以读写 DWORD 和 QWORD 了。
算是个折中方案,但是一样不支持数组。

出0入93汤圆

发表于 2020-8-5 08:29:23 来自手机 | 显示全部楼层
t3486784401 发表于 2020-8-4 20:44
封装个 uint32_t 或者 uint64_t 的读写接口/运算符,就可以读写 DWORD 和 QWORD 了。
算是个折中方案,但 ...

C++支持数组是很简单的事情,只不过在这里没啥意义就是了,一个函数搞定的事情,要被折腾得又长又臭。
最简单的,eeprom[address]返回vector<unsigned char>,读写前先设定读写长度。

出100入101汤圆

发表于 2020-8-5 08:45:39 | 显示全部楼层
请教楼主,c++嵌入应用多么?

出200入2554汤圆

 楼主| 发表于 2020-8-5 11:30:54 | 显示全部楼层
fengyunyu 发表于 2020-8-5 08:45
请教楼主,c++嵌入应用多么?

带操作系统的多,直接编单片机的少

出200入2554汤圆

 楼主| 发表于 2020-8-5 11:31:51 | 显示全部楼层
takashiki 发表于 2020-8-5 08:29
C++支持数组是很简单的事情,只不过在这里没啥意义就是了,一个函数搞定的事情,要被折腾得又长又臭。
最 ...

的确,这种需求适合用函数搞定

出0入0汤圆

发表于 2020-8-25 13:34:43 | 显示全部楼层
杀鸡焉用牛刀。单片机而已,c足够好用了

出0入0汤圆

发表于 2020-8-25 22:58:24 | 显示全部楼层
C++有其优点,特别是在底层的寄存器操作上有优势。
C++封装得好的话,能把很多问题简化。
可以看看:https://arobenko.gitbooks.io/bare_metal_cpp/content/

出0入0汤圆

发表于 2020-8-26 07:22:48 | 显示全部楼层
谁看懂了,可以解释一下语句的意识吗,看不懂,好复杂

出0入16汤圆

发表于 2020-8-26 08:44:18 | 显示全部楼层
C就是没有this指针,注定面向过程,C++很强大

出200入2554汤圆

 楼主| 发表于 2020-8-27 13:22:10 | 显示全部楼层
cnxh 发表于 2020-8-26 07:22
谁看懂了,可以解释一下语句的意识吗,看不懂,好复杂

大致用 C 的结构体和 函数指针 类比一下吧。

C++ 引入类 class,对应升级版的 C 结构体 struct。
类当中除了有变量,还有成员函数,类似于 struct 当中有变量和函数指针。

C++ 引入运算符重载,就是把运算符在底层也当成函数处理,
这样一来就可以重新定义运算符的动作(甚至“+”定义成减法都随你),然后就有了这篇帖子的内容。

出200入2554汤圆

 楼主| 发表于 2020-8-27 13:24:24 | 显示全部楼层
Ajkx007 发表于 2020-8-25 13:34
杀鸡焉用牛刀。单片机而已,c足够好用了

写工程 C 足够;

快速在几十种方案里逐个验证可行性,C++真的很快。

出200入2554汤圆

 楼主| 发表于 2020-8-27 13:39:26 | 显示全部楼层
初音之恋 发表于 2020-8-26 08:44
C就是没有this指针,注定面向过程,C++很强大

一直觉着 C++ 和 HDL 有很大相似

出200入2554汤圆

 楼主| 发表于 2020-8-27 13:48:30 | 显示全部楼层
yzhu 发表于 2020-8-25 22:58
C++有其优点,特别是在底层的寄存器操作上有优势。
C++封装得好的话,能把很多问题简化。
可以看看:https: ...

好物,就是网速略慢
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-6-18 23:08

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表