8040浏览
查看: 8040|回复: 1

[进阶] arduino宏的应用实例0--用宏处理串口指令(转)

[复制链接]
在最近的工作中发现c++的宏真是一个很有意思的东西,合理的运用宏能让你少写很多的重复代码。
下面说说宏在处理串口命令时的应用。

我想要达成的目的:通过在串口输入类似命令行的语句更改我设置的全局变量。
比如说有一个全局变量bool b。
当我在串口中输入"bOn;"或"bOff;"时,b的值更改为true和false。
全局变量float f;
当在串口输入"f=10;"时,更改f的值为10;

首先来看看最基本的实现。
  1. bool b = true;
  2. float f = 0;
  3. void setup() {
  4.   // put your setup code here, to run once:
  5.   Serial.begin(9600);
  6. }
  7. void loop() {
  8.   // put your main code here, to run repeatedly:
  9. }
  10. void serialEvent()
  11. {
  12.   //串口指令以换行符';'结尾
  13.   String s = Serial.readStringUntil(';');
  14.   procCmd(s);
  15. }
  16. void procCmd(String s)
  17. {
  18.   if (s.startsWith("bOn"))
  19.   {
  20.     b = true;
  21.   }
  22.   if (s.startsWith("bOff"))
  23.   {
  24.     b = false;
  25.   }
  26.   if (s.startsWith("f="))
  27.   {
  28.     s.remove(2);
  29.     f = s.toFloat();
  30.   }
  31. }
复制代码
是不是很简单,当时当有几十个变量时又怎么办呢?很多人的第一想法肯定是复制,然后改名,当然这样并没有错,我的第一想法也是这样,但是做了几遍之后我就厌烦了,这种方法一点也不优雅,就是重复性的无聊工作,而且一旦忘记修改哪个变量就会造成编译错误,同时也产生了大片的重复性代码。
解决重复性工作最好的方式就是抽象出相同的东西,然后重构。
这里,用两个宏就能描述这个结构:
  1. #define boolCmd(cmd)  do{if(s.startsWith(""#cmd"On")){cmd = true;}if (s.startsWith(""#cmd"Off")){cmd = false;}}while(0)
  2. #define doubleCmd(cmd) do{String s1 = ""#cmd""; if(s.startsWith(""#cmd"=")){s.remove(0, s1.length()+1);cmd=s.toFloat();}}while(0)
复制代码

这两个宏中"#cmd"将cmd这个字符当成字符串来处理,于是命令中的"bOn"中的"b"可以被我们替换成""#cmd"On",代替任意的变量名,而处理语句中的cmd代表的是这个变量本身,是不是很有意思,相当于在命令中直接引用了变量的名称。
对float的处理也是相同的。重构之后的代码变成了这样:
  1. #define boolCmd(cmd)  do{if(s.startsWith(""#cmd"On")){cmd = true;}if (s.startsWith(""#cmd"Off")){cmd = false;}}while(0)
  2. #define floatCmd(cmd) do{String s1 = ""#cmd""; if(s.startsWith(""#cmd"=")){s.remove(0, s1.length()+1);cmd=s.toFloat();}}while(0)
  3. bool b = true;
  4. float f = 0;
  5. void setup() {
  6.   // put your setup code here, to run once:
  7.   Serial.begin(9600);
  8. }
  9. void loop() {
  10.   // put your main code here, to run repeatedly:
  11. }
  12. void serialEvent()
  13. {
  14.   //串口指令以换行符';'结尾
  15.   String s = Serial.readStringUntil(';');
  16.   procCmd(s);
  17. }
  18. void procCmd(String s)
  19. {
  20.   boolCmd(b);
  21.   floatCmd(f);
  22. }
复制代码

是不是看起来简单多了,而且如果有其他变量需要修改,只需要用这两个宏在串口处理函数中注册就可以了,极大的减少了重复性工作。
同时我还定义了另一个宏:
  1. #define prt(cmd) do{String s1 = ""#cmd""; if(s.startsWith("?"#cmd"")){Serial.println(cmd);}}while(0)
复制代码
通过输入"?变量名;",就能打印我想查看的变量。
这类的应用还有很多很多,大家可以自行扩展。
最后或许有人会说用字符串处理效率太低,确实也比较占用空间,但我的观点是一个有意义的语句在调试时要直观的多,如果条件允许,这样绝对是值得的。

dsweiliang  初级技神

发表于 2016-5-4 09:37:13

学习学习
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail