|
本帖最后由 t3486784401 于 2018-12-11 02:44 编辑
【背景】
想必接触过 AVR 的各位都或多或少接触过 Arduino,简单说就是一个积木式平台,有着众多的代码库。
用着很高层的语法(C++)干着很底层(单片机)的工作,不求代码效率,但求效果晃瞎眼。
之前一直对于 Arduino 不屑,认为除了官方的核心板外,其他的系统/电路很难做到兼容。
事实证明太小瞧这平台了,基本上给定个能力较AVR差不多的处理器,就可以找到对应的内核,
再接下来你连的外设(传感器、驱动器、IO总线)找到对应的库就可以直接编译出结果了。
【Arduino 的呼吸灯】
闲来无事,想看看呼吸灯这样的操作有没有现成的库,结果真找着了(JLed),效果不多讲,但调用的代码着实晃瞎眼。
(至此各位可以回忆下标准 C 怎么写个呼吸灯、怎么封装个库):
- #include <jled.h>
- // breathe LED for 5 times, LED is connected to pin 9 (PWM capable) gpio
- JLed led = JLed(9).Breathe(2000).Repeat(5).DelayAfter(2000);
- void setup()
- {
- }
- void loop()
- {
- led.Update();
- }
复制代码
这里解释下(Arduino大神请移步下一节):
Arduino 程序有两个入口点(区别于C的main):setup 和 loop,分别执行一次/永久循环。这结构我总觉得类似 Verilog 当中的 initial 和 always...
由于是 C++,故全局实例化了一个 Jled 类,然后类实例直接操作板载 LED,由后台 Update 实现呼吸灯效果。
【Fluent Interface】
本来用这个库的时候,想着无非就是调用几个类成员函数,设定速度、电平、效果就完事了,结果被那行实例定义晃瞎了。
JLed led = JLed(9).Breathe(2000).Repeat(5).DelayAfter(2000);
这行代码信息量略大,实现的功能大致为:
在虚拟引脚9上定义 JLed 类,设定一个2000ms的呼吸灯,重复呼吸5次,每次呼吸间隔熄灭2000ms
仔细想来,如果这些函数返回了类的引用,在 C++ 语法里这么写没毛病,当然你分开一行行调用设定也可以。
另外由于设定的都是属性,这些调用的先后顺序无所谓,例如把 Repeat 和 DelayAfter 换一换,不影响最终效果。这可读性真不是盖的。
在 .md 文件当中看到了这种代码风给的名称:“Fluent Interface”,直译过来就是 :“流式接口”。
搜索了下这种接口风格,是为提升代码可读性而设计的,典型的例子如 C++::iostream,那一堆 << << >> >> 符号就是重载的流式接口。
一个单片机的编译器(GNU这个组织真心不说啥了),居然标准地支持 C++ 到如此地步,说实在的让人不寒而栗。
【后记】
说到呼吸灯,哪怕是汇编也能在 M64 上码出一模一样的运行结果。但封装这个灯光库的歪果仁,恐怕不单单是为了晃瞎观众那么简单。
总之搬运过来给大家分享,如有不当之处还请各位前辈指教。
P.S. 我用了第三方的处理器 + 第四方的内核库 + 第五方的灯光库,在 Arduino 平台上居然合成了可以正确运行的 HEX 文件,真心佩服这兼容性。
P.S.2. 以下是库源文件地址,有兴趣各位可移步瞻仰:https://github.com/jandelgado/jled |
阿莫论坛20周年了!感谢大家的支持与爱护!!
月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!
|