友情提示:380元/半年,儿童学编程,就上码丁实验室。
我是潘,曾经是个工程师。这是 “Arduino 公开课” 系列的入门教程。经过前面一共18课的基础学习,我们已经掌握了 Arduino 的基本操作,现在是时候进入更深的一个层面。后面几节课会介绍 Arduino 的各类通信协议和内部运作机制。掌握这些知识后,你就可以称为砖家了。有任何疑问请在评论区提出,我会逐一回答。
Arduino 支持串口、I2C、SPI、ISP等几个通信协议。其中,每次写入程序、监测传感器反馈数据时都用到了串口。可以说,串口是人机交互中用到最频繁的一个接口。
但是之前除了按“Upload”写入程序外,串口的作用都是接受传感器的反馈,那么是否可以反过来,通过串口向 Arduino 发送数据,控制 Arduino 呢?其实,很简单。
这次实验我们只需一块 Arduino Uno,通过 USB 接上电脑,写入下面的程序,打开串口监视器,我们输入什么,监视器就会反馈什么:
1
2
3
4
5
6
7
8
9
10
11
|
charincomingByte=“”; //储存输入的字符
voidsetup(){
Serial.begin(9600); // 设置通信码率,必须跟串口监视器一致
}
voidloop(){
if(Serial.available()>0){//监测串口缓存,当有数据输入时,执行下面语句
incomingByte= char(Serial.read());//读取输入的字符,转换为字符,并赋值给incomingByte
Serial.print(“I received: “);
Serial.println(incomingByte);
}
}
|
是不是很无聊?但其中的学问却很多!
1
|
if(Serial.available()>0)
|
首先,该语句用于判断串口缓存中是否有值,如果有才执行赋值和打印,如果没有这个语句,串口监视器会不断循环打印值为空的语句,俗称刷屏了。
其次,Serial.read() 读取串口缓存的数据,每次一个字符值,注意字符值是数字,比如字符“a”得到的结果是“97”,所以需要char() 将其转换为字符值。
现在简单修改一下程序,控制开发板上的LED,输入1打开,输入其他任意字符关闭:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
charincomingByte=“”; //储存输入的字符
voidsetup(){
Serial.begin(9600); // 设置通信码率,必须跟串口监视器一致
pinMode(13,OUTPUT);
}
voidloop(){
if(Serial.available()>0){//监测串口缓存,当有数据输入时,执行下面语句
incomingByte= char(Serial.read());//读取输入的字符,转换为字符,并赋值给incomingByte
if(incomingByte==’1′){
digitalWrite(13,HIGH);
}
else{
digitalWrite(13,LOW);
}
}
}
|
现在问题来了,Serial.read() 每次只能读取一个字符值,如果输入的是一串字符,Arduino 怎么接收?我们修改一下第一个程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
/*
作者:Ardui.co
效果:通过串口向 Arduino 输入字符串
版本:1.0
更新时间:2017年3月6日
*/
StringincomingByte=“”; //用 String 声明字符串变量
voidsetup(){
Serial.begin(9600); // 设置通信码率,必须跟串口监视器一致
pinMode(13,INPUT);
}
voidloop(){
while(Serial.available()>0){//监测串口缓存,当有数据输入时,循环赋值给incomingByte
incomingByte+= char(Serial.read());//读取单个字符值,转换为字符,并按顺序一个个赋值给incomingByte
delay(2);//不能省略,因为读取缓冲区数据需要时间
}
if(incomingByte.length()>0){//如果incomingByte有字符串,执行下面语句
Serial.println(incomingByte);
incomingByte=“”;//清空变量,准备下次输入
}
}
|
该程序的核心是:
1
|
incomingByte+=char(Serial.read())
|
既然 Serial.read() ,每次只能从串口缓存中读取一个值,那么我们就把每个值,通过 while 语句一个个地赋予字符串变量 incomingByte。
疑问又出现了,Arduino 串口的缓存有多大呢?如果输入一个超大的字符串,是否会溢出?
Arduino串口缓冲区默认为64字节,如果你单次传输的数据较多可以将
#arduino安装目录#\hardware\arduino\cores\arduino\HardwareSerial.cpp中的
#define SERIAL_BUFFER_SIZE 64 修改为 #define SERIAL_BUFFER_SIZE 128 这样就有128字节的缓冲区了。
值得注意的是,程序中delay(2)不能删略,因为读取缓冲区数据需要时间,如果上一个字符没有读取完毕时,进入第二个字符读取的循环,就会出现错误。