1.前言
Ardunio与计算机通信最常用的方式就是串口通信。在Arduino控制器上,串口都是位于Rx和Tx两个引脚,Arduino的USB口通过一个转换芯片与这两个串口引脚连接。该转换芯片会通过USB接口在计算机上虚拟出一个用于Arduino通信的串口。当你使用串口功能的时候,就意味着你不能引用串口引脚作为输入或者输出。
要想使串口与计算机通信,首先需要先启用串口功能,初始化Arduino的串口通信功能,也就是:
- Serial.begin(speed)
其中参数speed指串口通信波特率,用于设定串口通信速率的参数。串口通信双方必须使用相同的波特率才可以正确通信。
波特率是一个衡量通信速度的参数,表示每秒传送的bit的个数。如9600波特表示每秒发送9600bit的数据,常用以下波特率:300,600,1200,2400,4800,9600,14400,19200,28800,38400,57600,115200。波特率高表示串口通信速率越快。
你可以使用Arduino IDE内置的串口监视器与Arduino板子通信。点击工具栏上的串口监视器按钮(注意设置相同波特率),我们接下来的实验就是用到它。
Arduino Mega上有三个额外的串口:Serial1,Serial2,Serial3。若有使用这三对引脚与您的个人电脑通信,你需要一个额外的USB转串口适配器;若要用它们来与外部的TTL串口设备进行通信,将Tx引脚连接到设备Rx引脚,将Rx引脚连接到设备的Tx引脚,将GND连接到设备的GND。
2.常用串口函数
接下来介绍一下串口常用函数。
2.1 begin —— 启用串口
- 打开串口,设置波特率。
- 对于Arduino Mega:Serial1.begin(speed) Serial2.begin(speed) Serial3.begin(speed)
2.2 end —— 停用串口
- 停用串口通信,使Rx和Tx引脚用于一般输入输出;
- 要重新使用串口通信,需要Serial.begin()语句;
- 对于Mega:Serial1.end() Serial2.end() Serial3.end();
2.3 print、println、printF —— 打印输出数据
- 打印输出数据 Serial.println 函数会在输出完指定数据后,再输出一组回车换行符。
2.4 read —— 读取传入的串口的数据
- 读取传入的串口的数据,每次都会返回1字节的数据。
- 在使用串口时,Arduino会在SRAM中开辟一段大小为64B的空间,串口接收到的数据都会被暂时存放在该空间中,称这个存储空间为缓冲区。
- 当调用read()函数时,就会从缓冲区中取出1B的数据。
2.5 available —— 当前缓冲区中接收到的数据字节数
- 当前缓冲区中接收到的数据字节数。通常我们都要判断缓存区中是否有数据,然后才调用read方法。
3.实验
那么,问题来了,串口到底有什么用?根据我自己的经验:
- 对于习惯于希望可以看到调试过程的我来说,我喜欢用串口打印调试信息,那么可能就有人问,一般情况下只有在需要调试的时候才显示调试结果,那么正式环境我又不想有调试信息,应该怎么办?其实,可以像下面这样:
#define BTSerial Serial1
#define MyDebugSerial Serial
//该条语句用于使能DEBUG输出信息,屏蔽掉就不会输出debug调试信息
#define DEBUG
#ifdef DEBUG
#define DBGLN(message) MyDebugSerial.println(message)
#else
#define DBGLN(message)
#endif
当不需要调试信息时就注释掉 #define DEBUG。
- 串口当然可以用来和符合串口通信协议的模块进行通信,比如 蓝牙模块HC06 Wifi模块ESP系列等等。这就意味着我们可以基于硬件串口功能区开发我们所需功能。
3.1 与电脑串口通信,读取数据并原样返回数据
/**
* @Desc 读取数据并原样返回数据
* @author 单片机菜鸟
* @Date 2016/12/10
*/
void setup() {
// 初始化串口
Serial.begin(9600);
//等待串口准备好
while(!Serial);
}
void loop() {
//如果缓冲区中有数据,则读取并输出
if(Serial.available()>0){
char ch = Serial.read();
Serial.print(ch);
}
}
打开Arduino IDE自带的串口监视器进行调试(要设置相同波特率),当进行串口通信时,Arduino控制器上就会看到标有RX TX的2个LED灯闪烁提示,如没有意外,应该显示如下(我自己随便写的):
3.2 串口控制开关灯
/**
* @Desc 串口控制开关灯
* @author 单片机菜鸟
* @Date 2016/12/10
* 注意:LED的一端接到5V,另外一端接到输出引脚,低电平亮
*/
#define LED_START 2
#define LED_END 9
void setup() {
// 初始化串口
Serial.begin(9600);
//等待串口准备好
while(!Serial);
led_Init();
}
void loop() {
//如果缓冲区中有数据,则读取并输出
if(Serial.available() > 0){
char ch = Serial.read();
Serial.print(ch);
//开灯
if(ch == 'a'){
led_On();
}else if(ch == 'b'){
led_Off();
}
}
}
/**
* @Desc 初始化LED
*/
void led_Init(){
// 将2-9号引脚设置为输出状态
for(int i=LED_START;i<=LED_END;i++){
pinMode(i,OUTPUT);
digitalWrite(i,HIGH);//灭掉LED
}
}
/**
* @Desc 打开LED
*/
void led_On(){
//从引脚2到9引脚,点亮LED
for(int i=LED_START;i<=LED_END;i++){
digitalWrite(i,LOW);//LED亮
}
}
/**
* @Desc 关闭LED
*/
void led_Off(){
//从引脚2到9引脚,关闭LED
for(int i=LED_START;i<=LED_END;i++){
digitalWrite(i,HIGH);//LED灭
}
}
我的实验结果就是灯根据我的指令亮灭.
4.总结
总体来说,这节课不难,在理解串口基础上运用串口提供的一些函数就能进行基本的串口通信开发。