找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 27165|回复: 9
打印 上一主题 下一主题
收起左侧

Arduino学习6-Arduino串口接收字符串

  [复制链接]
跳转到指定楼层
楼主
用惯Arduino串口传输的朋友都知道,Arduino的Serial.read()每次只能读一个字节,但是有时想进行字符串通讯,就很麻烦了。
废话少讲,直接上完整例子:

编译只要一块Arduino,不需要任何外置元件。
用Arduino编译器的串口监视器即可看到结果,我们打什么文字进去,下面就会返回什么文字
String comdata = "";

void setup()
{
   
Serial.begin(9600);
}

void loop()
{
   
while (Serial.available() > 0)  
    {
        
comdata += char(Serial.read());
        
delay(2);
    }
   
if (comdata.length() > 0)
    {
        
Serial.println(comdata);
        
comdata = "";
    }
}



代码很简单,comdata是一个字符串类型变量。Serial.available()是当前串口缓冲池的数据量。Serial.read()是读缓冲池的语句,每次只能读一个字节。
用了String类型变量,很简单的实现了字符到字符串的加入,还有字符串输出,赋值等麻烦问题,所以很简单的代码就能处理串口数据。
特别留意的是读串口时的delay(2)不能删掉,否则串口缓冲区不够时间接受数据。即使调小延时也会出错。具体数值也可以实验决定。

再提醒一个:comdata说是一个字符串,也是一个数组,引用每个字的话可以用comdata[0],comdata[1]。。。comdata[n]。如果我们要每个字节取出的话,可以每个引用。


效果:输入什么字符串,输出就是什么。
输入:

按send之后:




再附送一个例子,在串口输入1011101..的话,就会令Arduino的D2~Dx引脚产生高/低电平,当然,一次发送的数据视Arduino引脚数而定,比如Arduino UNO/nano之类的,只有D2~D13十二个引脚。我们打12个数字就好。比如101101011010,如果中间有非0和1的字符,则自动跳过该位设置:比如122202221222这样。因为2不是允许范围内,就只设置D2/D6/D10的值了:String comdata = "";
void setup()
{
  
Serial.begin(9600);
  
for(int i = 2; i <= 13; i++) pinMode(i, OUTPUT);
}

void loop()
{
  
while (Serial.available() > 0)
  {
   
comdata += int(Serial.read()) - '0';
   
delay(2);
  }
  
if(comdata.length() > 0)
  {
   
for(int i = 0; i < comdata.length(); i++)
    {
      
if(comdata[i]=='0'||comdata[i]=='1')
      {
        
digitalWrite(i + 2, comdata[i] - '0');
        
Serial.print("Pin ");
        
Serial.print(i + 2);
        
Serial.print(" is ");
        
Serial.println(comdata[i]);
      }
    }
   
comdata = "";
  }
}










再来一个:进阶版(有待测试)
输入六个逗号分隔数比如:50,20,5,255,20,20
就能令Arduino的PWM引脚(3,5,6,9,10,11):按照PWM值发光。所以逗号分割数必须是0~255


String comdata = "";
int numdata[6] = {0}, PWMPin[6] = {3, 5, 6, 9, 10, 11}, mark = 0;
void setup()
{
  
for(int i = 0; i < 6; i++) pinMode(PWMPin[i], OUTPUT);
  
Serial.begin(9600);
}

void loop()
{
  
int j = 0;
  
while (Serial.available() > 0)
  {
   
comdata += char(Serial.read());
   
delay(2);
   
mark = 1;
  }

  
if(mark == 1)
  {
   
Serial.println(comdata);
   
Serial.println(comdata.length());
   
for(int i = 0; i < comdata.length() ; i++)
    {
      
if(comdata[i] == ',')
      {
        
j++;
      }
      
else
      
{
        
numdata[j] = numdata[j] * 10 + (comdata[i] - '0');
      }
    }
   
comdata = String("");


   
for(int i = 0; i < 6; i++)
    {
      
Serial.print("Pin ");
      
Serial.print(PWMPin[i]);
      
Serial.print(" = ");
      
Serial.println(numdata[i]);
      
analogWrite(PWMPin[i], numdata[i]);
      
numdata[i] = 0;
    }
   
mark = 0;
  }
}


(补充) - 在串口读取多个字符串,并且转换为数字数组

功能如题目。
在串口收到逗号分割的6串数字比如
100,200,45,4,87,99
然后在6个PWM端口3, 5, 6, 9, 10, 11输出对应PWM值


代码注释很详细了,就不再说明了。
  1.     //定义一个comdata字符串变量,赋初值为空值
  2.     String comdata = "";
  3.     //numdata是分拆之后的数字数组
  4.     int numdata[6] = {0}, PWMPin[6] = {3, 5, 6, 9, 10, 11}, mark = 0;
  5.     void setup()
  6.     {
  7.     //定义0~6脚是输出
  8.       for(int i = 0; i < 6; i++) pinMode(PWMPin[i], OUTPUT);
  9.       Serial.begin(9600);
  10.     }
  11.      
  12.     void loop()
  13.     {
  14.     //j是分拆之后数字数组的位置记数
  15.       int j = 0;
  16.      
  17.       //不断循环检测串口缓存,一个个读入字符串,
  18.       while (Serial.available() > 0)
  19.       {
  20.       //读入之后将字符串,串接到comdata上面。
  21.         comdata += char(Serial.read());
  22.           //延时一会,让串口缓存准备好下一个数字,不延时会导致数据丢失,
  23.         delay(2);
  24.         //标记串口读过数据,如果没有数据的话,直接不执行这个while了。
  25.         mark = 1;
  26.       }
  27.      
  28.       if(mark == 1)  //如果接收到数据则执行comdata分析操作,否则什么都不做。
  29.       {
  30.       //显示刚才输入的字符串(可选语句)
  31.         Serial.println(comdata);
  32.           //显示刚才输入的字符串长度(可选语句)
  33.         Serial.println(comdata.length());
  34.      
  35.      /*******************下面是重点*******************/
  36.      //以串口读取字符串长度循环,
  37.         for(int i = 0; i < comdata.length() ; i++)
  38.         {
  39.         //逐个分析comdata[i]字符串的文字,如果碰到文字是分隔符(这里选择逗号分割)则将结果数组位置下移一位
  40.         //即比如11,22,33,55开始的11记到numdata[0];碰到逗号就j等于1了,
  41.         //再转换就转换到numdata[1];再碰到逗号就记到numdata[2];以此类推,直到字符串结束
  42.           if(comdata[i] == ',')
  43.           {
  44.             j++;
  45.           }
  46.           else
  47.           {
  48.              //如果没有逗号的话,就将读到的数字*10加上以前读入的数字,
  49.              //并且(comdata[i] - '0')就是将字符'0'的ASCII码转换成数字0(下面不再叙述此问题,直接视作数字0)。
  50.              //比如输入数字是12345,有5次没有碰到逗号的机会,就会执行5次此语句。
  51.              //因为左边的数字先获取到,并且numdata[0]等于0,
  52.              //所以第一次循环是numdata[0] = 0*10+1 = 1
  53.              //第二次numdata[0]等于1,循环是numdata[0] = 1*10+2 = 12
  54.              //第三次是numdata[0]等于12,循环是numdata[0] = 12*10+3 = 123
  55.              //第四次是numdata[0]等于123,循环是numdata[0] = 123*10+4 = 1234
  56.              //如此类推,字符串将被变成数字0。
  57.             numdata[j] = numdata[j] * 10 + (comdata[i] - '0');
  58.           }
  59.         }
  60.         //comdata的字符串已经全部转换到numdata了,清空comdata以便下一次使用,
  61.         //如果不请空的话,本次结果极有可能干扰下一次。
  62.         comdata = String("");
  63.      
  64.      
  65.         //循环输出numdata的内容,并且写到PWM引脚
  66.         for(int i = 0; i < 6; i++)
  67.         {
  68.           Serial.print("Pin ");
  69.           Serial.print(PWMPin[i]);
  70.           Serial.print(" = ");
  71.           Serial.println(numdata[i]);
  72.           analogWrite(PWMPin[i], numdata[i]);
  73.           numdata[i] = 0;
  74.         }
  75.         //输出之后必须将读到数据的mark置0,不置0下次循环就不能使用了。
  76.         mark = 0;
  77.       }
  78.     }
复制代码


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:280474 发表于 2018-1-28 19:17 | 只看该作者
感谢分享!很棒的教程
回复

使用道具 举报

板凳
ID:340398 发表于 2018-5-29 12:20 | 只看该作者
感谢分享!很棒的教程
回复

使用道具 举报

地板
ID:333719 发表于 2018-5-29 22:17 | 只看该作者

感谢分享!很棒的教程
回复

使用道具 举报

5#
ID:32574 发表于 2018-8-24 22:35 | 只看该作者
谢谢老师分享
回复

使用道具 举报

6#
ID:370919 发表于 2018-8-29 14:58 | 只看该作者
哎,看得头痛还一知半解的,怎么办?
回复

使用道具 举报

7#
ID:360931 发表于 2018-9-3 20:14 来自手机 | 只看该作者
非常清晰,受教了,谢谢!
回复

使用道具 举报

8#
ID:436581 发表于 2018-11-30 15:18 | 只看该作者
可以请问下怎么把字符输出到显示屏上吗
回复

使用道具 举报

9#
ID:426684 发表于 2018-12-2 09:52 | 只看该作者
1,2,3,4,5,6  最后一位显示错误.
回复

使用道具 举报

10#
ID:79544 发表于 2019-3-14 09:48 | 只看该作者
感谢分享,学习啦。楼主:假如是FF000100FF该如何解析,2个FF是包头和包尾中间是有效数据。
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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