开启左侧

Arduino入门之串口(二)

[复制链接]
发表于 2016-11-5 15:19:25 | 显示全部楼层 |阅读模式
本帖最后由 PPeach 于 2016-11-5 15:22 编辑

上一篇中介绍了几个我们常用的串口通讯的函数,这一篇中主要对于大多数小白比较头疼的串口命令的处理进行一定的介绍。

首先我们回顾一下上一遍中比较重要的一点:Serial.read()这一个函数。
从表层意思看来就是读取串口接收到的数据,但是需要特别注意的一点,该函数是从串口缓存区中一个数据一个数据进行读取的,并清除串口缓存区的该数据而不是统一的一次性全读出来再清除。这也就是串口数据处理的关键。

当我们使用单个数据作为控制命令的时候,我们只需要读什么判断什么就好,例如
  1. void setup()
  2. {
  3.   Serial.begin(9600);
  4.   pinMode(13 , OUTPUT);
  5. }

  6. void loop()
  7. {
  8.   char readChar = Serial.read();
  9.   if (readChar == 'o')
  10.   {
  11.     Serial.print(readChar);
  12.     digitalWrite(13 , HIGH);
  13.     Serial.println("   Open");
  14.     readChar = ' ';
  15.   }
  16.   else if (readChar == 'c')
  17.   {
  18.     Serial.print(readChar);
  19.     digitalWrite(13 , LOW);
  20.     Serial.println("   Close");
  21.     readChar = ' ';
  22.   }
  23. }
复制代码

Test1.png
在这段代码中,我们使用单个小写字符o和c进行对13脚的LED进行串口的开关控制。首先我将读进来的数据先保存在readChar这个变量当中,然后对其进行判断,判断完成后给readChar重新赋值一个在判断中通过没有用到的数据(类似清空变量),保证不会循环触发判断。我相信这个是很多新手入门的时候一定经历过的(当然控制命令可以不是o和c,是h和l也没有问题,我这里指的是单个字符的控制)。但是如果我们需要通过串口控制一个led的亮度的时候,我们该怎么处理呢?

当我们通过串口助手发送数据给Arduino,我们就需要判断Arduino接收到的数据类型,如果是整形就可以直接给analogWrite使用,但是如果是字符的话我们就需要进行转换使其成为数字再给analogWrite使用。这时候我们就需要如下的程序。
  1. /*
  2.   Character analysis operators

  3. Examples using the character analysis operators.
  4. Send any byte and the sketch will tell you about it.

  5. created 29 Nov 2010
  6. modified 2 Apr 2012
  7. by Tom Igoe

  8. This example code is in the public domain.
  9. */

  10. void setup() {
  11.   // Open serial communications and wait for port to open:
  12.   Serial.begin(9600);
  13.   while (!Serial) {
  14.     ; // wait for serial port to connect. Needed for Leonardo only
  15.   }

  16.   // send an intro:
  17.   Serial.println("send any byte and I'll tell you everything I can about it");
  18.   Serial.println();
  19. }

  20. void loop() {
  21.   // get any incoming bytes:
  22.   if (Serial.available() > 0) {
  23.     int thisChar = Serial.read();

  24.     // say what was sent:
  25.     Serial.print("You sent me: \'");
  26.     Serial.write(thisChar);
  27.     Serial.print("\'  ASCII Value: ");
  28.     Serial.println(thisChar);

  29.     // analyze what was sent:
  30.     if (isAlphaNumeric(thisChar)) {
  31.       Serial.println("it's alphanumeric");
  32.     }
  33.     if (isAlpha(thisChar)) {
  34.       Serial.println("it's alphabetic");
  35.     }
  36.     if (isAscii(thisChar)) {
  37.       Serial.println("it's ASCII");
  38.     }
  39.     if (isWhitespace(thisChar)) {
  40.       Serial.println("it's whitespace");
  41.     }
  42.     if (isControl(thisChar)) {
  43.       Serial.println("it's a control character");
  44.     }
  45.     if (isDigit(thisChar)) {
  46.       Serial.println("it's a numeric digit");
  47.     }
  48.     if (isGraph(thisChar)) {
  49.       Serial.println("it's a printable character that's not whitespace");
  50.     }
  51.     if (isLowerCase(thisChar)) {
  52.       Serial.println("it's lower case");
  53.     }
  54.     if (isPrintable(thisChar)) {
  55.       Serial.println("it's printable");
  56.     }
  57.     if (isPunct(thisChar)) {
  58.       Serial.println("it's punctuation");
  59.     }
  60.     if (isSpace(thisChar)) {
  61.       Serial.println("it's a space character");
  62.     }
  63.     if (isUpperCase(thisChar)) {
  64.       Serial.println("it's upper case");
  65.     }
  66.     if (isHexadecimalDigit(thisChar)) {
  67.       Serial.println("it's a valid hexadecimaldigit (i.e. 0 - 9, a - F, or A - F)");
  68.     }

  69.     // add some space and ask for another byte:
  70.     Serial.println();
  71.     Serial.println("Give me another byte:");
  72.     Serial.println();
  73.   }
  74. }
复制代码
Test2.png
如上的程序可以再example中Strings的基础程序中找到。

通过该程序我们发现,当我通过串口助手发送255至Arduino时,Arduino实际接收到的是char类型。那么我们就需要通过转换使其成为整形。

如果需要数据转换,那我们就应该选择一个通讯的协议,可以使世界通用的,也可以是自己自定义的,为了方便起见,在数据量不大的情况下,我们可以选择采用自己定制的通讯协议。
在我们自定的协议中,我至少需要告诉接收端我什么时候是把数据发送完成。可以采用特殊字符结尾,也可以限定数据长度。这里我采用特殊字符结尾。我采用\n(换行符)的结尾方式。
  1. /*
  2.   String to Integer conversion

  3. Reads a serial input string until it sees a newline, then converts
  4. the string to a number if the characters are digits.

  5. The circuit:
  6. No external components needed.

  7. created 29 Nov 2010
  8. by Tom Igoe

  9. This example code is in the public domain.
  10. */

  11. String inString = "";    // string to hold input

  12. void setup() {
  13.   // Open serial communications and wait for port to open:
  14.   Serial.begin(9600);
  15.   while (!Serial) {
  16.     ; // wait for serial port to connect. Needed for Leonardo only
  17.   }

  18.   // send an intro:
  19.   Serial.println("\n\nString toInt():");
  20.   Serial.println();
  21. }

  22. void loop() {
  23.   // Read serial input:
  24.   while (Serial.available() > 0) {
  25.     int inChar = Serial.read();
  26.     if (isDigit(inChar)) {
  27.       // convert the incoming byte to a char
  28.       // and add it to the string:
  29.       inString += (char)inChar;
  30.     }
  31.     // if you get a newline, print the string,
  32.     // then the string's value:
  33.     if (inChar == '\n') {
  34.       Serial.print("Value:");
  35.       Serial.println(inString.toInt());
  36.       Serial.print("String: ");
  37.       Serial.println(inString);
  38.       // clear the string for new input:
  39.       inString = "";
  40.     }
  41.   }
  42. }
复制代码

该代码也可以在String中找到。这段代码中,首先其读取数据,再判断是否为数字(isDigit),如果是数字就进行字符串的累加。当读取到'\n'(换行符)时候,调用toInt()进行转换。所以注意这句话
  1. Serial.println(inString.toInt());
复制代码
其中,inString.toInt()的的到的结果就是一个整形数字,可以直接用在analogWrite中。

回复

使用道具 举报

发表于 2016-11-7 09:44:59 | 显示全部楼层
好赞
回复

使用道具 举报

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

本版积分规则

精彩课程推荐

关于我们

帮助中心

商务合作

点击这里给我发消息

关注微信公众号

Copyright © 2016-2017 i创学院 - 上海享渔教育科技有限公司 Powered by Discuz!     ( 沪ICP备16033954号-1 )