串口是单片机中一种重要的数据通讯接口,本期我们就来学习一下Arduino的串口基础操作。首先我们来了解一下Arduino开发板的串口资源。在UNO及NANO板上,只有一组串口(Serial0),这个串口通过一个转换芯片(ATmega8、ATmega32、CH340、CP2102等)可以连接到电脑的USB口,也就是我们用来下载程序的接口,在板上引出的引脚中,也可以不通过转换芯片,这个主要用于与其他串口设备(电子模块或其它单片机)通讯。而在mega2560板上,则有4组串口:Serial0- Serial3,其中Serial0连接了转换芯片用于与电脑USB接口连接,其余三组则是直接从芯片引脚引出。

发送数据

下面来看看第一个例程:串口发送字符串"Hello world!"到电脑。

在初始化函数中,执行了启动串口的函数,并且设置了串口的波特率为115200(即每秒传输115200个二进制位,注意:进行串口通讯的设备波特率必须一致)。在主循环中,不断地发送字符串"Hello world!",每发送一次等待1秒。下面是ArduinoIDE串口监视器接收到的内容:

如果将输出函数改为Serial.println(),则在串口监视器中看到:

第二个例程,串口输出数字0-9,每个数字之间显示一个空格,每次输出数字9之后则换行,重新输出0-9。

串口监视器显示内容:

现在我们来思考一个问题,在上面例程中串口输出引用了变量"i"的值,那么,电脑收到的是"i"的真实值吗?比如当i=8时,电脑收到的是"8"这个值吗?为了验证这个问题,我们将程序改一下,只输出0-2三个值,并且不加空格,不换行,然后换用串口调试助手来观察收到的数据。

先用ArduinoIDE的串口监视器查看:

从监视器中看到,按预订的显示了"012",没有空格及换行,接着,看看串口调试助手"十六进制显示"得到的内容:

注意上图中"红框"位置,勾选了"十六进制显示",如果不选这个选项则看到结果与ArduinoIDE串口监视器的一样。从串口调试助手中我们看到,实际收到的是十六进制的"0x30,0x31,0x32",它们对应的十进制值应为"48,49,50",并不是其本身的值(十进制"0,1,2"的十六进制值应为:0x00,0x01,0x02),这实际就是"0,1,2"三个字符对应的ASCII码,也就是说Serial.print()及Serial.println()实际是将放入的变量及字符串以ASCII码的形式发送,这是因为在屏幕上显示一个值,如"0",需要提供的是"0"对应的ASCII码,而如果将"0"的值发过去,显示的将不是零。加下来,我们再改进一下程序,将Serial.print()换成Serial.write(),然后连续发送"0,1,2"的实际值及"0,1,2"对应的ASCII码"0x30,0x31,0x32",然后看看串口调试助手的显示内容。

串口调试助手十六进制显示:

关闭十六进制显示:

从上面的试验,我们可以看到,Serial.print()、Serial.println()与Serial.write()的区别,前两个是发送的ASCII码,而后面这个才是发送变量的值本身。接下来,我们再改写程序,用Serial.write()实现输出"Hello world!"。

以上给出了两个例程,注意Serial.write()的两种用法,下面是串口调试助手在"十六进制显示"关闭和开启两种状态下的显示结果:

下面附上从"百度百科"下载的ASCII码对照表,以供大家参考:

通过上面例程的学习,我们应该能够灵活地掌握Serial.print()、Serial.println()与Serial.write()的特点及用法。Serial.println()输出时实际上是在Serial.print()的基础上增加了"0x0d,0x0a"的输出,或者也可以用Serial.print("")来实现回车换行,另外Serial.println()输出单变量时还可以用ArduinoIDE自带的"串口绘图仪"打印该变量的变化曲线。而Serial.write()常用于串口双机或多机通讯,传递变量实际值用于控制或计算时用,这一点是很重要的,比如某个传感器的实际测量值要通过串口传输,则一般直接传递器实测值,而不是ASCII码,这个将在进阶课程的"串口双机+多机通讯中"中详细讲解。

接收数据

上面我们学习了串口发送,现在来学习一下串口的接收。当串口发送数据时,数据是从TX引脚一位一位地发送出去的,而接收数据时则是从RX引脚一位一位的接收进来,每传输完成一个字节,就会做相应的处理,这个处理是在串口中断中进行,Arduino库的处理方法是在存储空间中分配了一个64字节的串口数据缓存空间(通过修改库文件可以修改缓存区大小),当接收一个字节的数据后,就会把它存放到该存储空间中,下一个到来的字节数据跟在上一个字节的后面,当存储空间"装满"后,则最先收到的字节数据会被"挤出",即满足"先进先出"的顺序,当我们读取数据时,也是按照这个顺序。

当接收到数据后,我们可以通过函数Serial.available()查看缓存区内的字节数,然后用Serial.read()读取数据,要注意的是这个函数一次只能读取一个字节,当接收到多个字节数据时就要反复调用这个函数读取数据,另外:这个函数在读取一个字节后则该字节的数据便从缓存区中清除。如果只读取,而不清除可以用Serial.peek()。读取数据,我们可以用"主动查询"的方法,也可以使用"触发事件"的方法。主动查询即不管缓存区有没有数据,都在固定的时刻去查看缓存区;而触发事件方式则是当缓存区内有数据时,触发一个"事件",这个可以粗略地理解为一个中断,然后在一个处理函数中去读取数据,这个处理函数的函数名是固定的即:serialEvent()。这个方法的优点在于我们不用每次都去查看缓存区,这样可以提高程序的效率。下面我们以"触发事件"的方式来做一个试验,当串口接收到到字符"k"时则打开板上13号引脚连接的LED,当收到字符"g"时则关闭该LED,如果收到其他字符则串口输出"Input error code!"。

将上述代码下载到开发板中,打开ArduinoIDE的串口监视器,在该界面的最上方输入字符k,点击"发送",则板上由13号引脚控制的LED点亮;然后输入字符g并发送,则LED关闭;如果输入其他字符,则在监视器的接收区显示"Input error code!"。

上述代码在UNO、NANO、MEGA2560中都适用,而在MEGA2560板中,如果要使用其他串口,如串口1,则在基本的函名中"Serial"的后面加上串口编号即可,例如启动串口1:Serial1.begin(115200)(其编号为0-3,0省略不写),而相应的串口事件函数名为:serialEvent1()。

另外,当串口与一些设备通讯,需要特定的数据位、停止位、奇偶校验时,可以参考下表的值进行配置:

配置的方法如下,例如设置为数据位8,偶校验,两个停止位:

Serial.begin(115200 , SERIAL_8E2);

在默认情况下,即缺省第二个参数时,串口工作于"SERIAL_8N1"的模式下。

关于串口通讯的基础内容就讲到这里。关于串口发送接收的协议制定、多机通讯将在进阶课程中详细讲解。欢迎关注、在评论区留言讨论。

android 串口调试助手_Arduino入门 第八节-串口通讯(基础篇)相关推荐

  1. 《STM32从零开始学习历程》——USART串口通讯实验篇1——中断接收与发送

    <STM32从零开始学习历程>@EnzoReventon USART串口通讯实验篇1--中断接收与发送 最近开始接触了STM32F4xx系列单片机,对于我这个从零开始学习的小白来说,可谓困 ...

  2. 《STM32从零开始学习历程》——USART串口通讯实验篇2——指令控制LED灯实验

    <STM32从零开始学习历程>@EnzoReventon USART串口通讯实验篇2--指令控制LED灯实验 本实验是在<USART串口通讯实验篇1--中断接收与发送>的基础上 ...

  3. android 串口调试助手_PLC串口通信调试工具amp;调试过程

    串口通信是一种简单的通信方式,通过连接少量线缆即可完成数据通信.做串口通信调试,一般需要进行如下几个过程:1.确认上位机通信;2.确认下位机通信.3.上.下位机联调通信.(上位机是指PLC,下位机是指 ...

  4. java串口调试助手_基于 QML的 串口调试助手

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/weixin_38416696/arti ...

  5. Android端MVVM从入门到实战(第三篇) - DataBinding数据绑定

    前言 上一章内容中的代码,如果我们延迟以后重新给实体类赋值,会发现UI并没更新,在更早的内容中我们讲到过,需要用LiveData去通知观察者更新,不过这里我们要讲一下另外一个方法,也是更基本的方法 - ...

  6. Android端MVVM从入门到实战(第四篇) - DataBinding运算符

    前言 之前的文章中我们了解了DataBinding的基础用法和数据绑定,这一章我们来了解一下DataBinding中的运算符,以便我们在实战中能熟练的运用这些运算符方便我们的开发. 参考代码地址:Gi ...

  7. 【面试宝典】软件测试工程师2021烫手精华版(第八章Python基础篇)

    第八章 Python 基础 斐波那契数列求 N? 字符串反序输出? print(a_str[::-1]) 判断回文? astr[::-1] == a_str 统计python 源代码文件中代码行数,去 ...

  8. 串口通讯基础及S3C2410 UART控制器

    数据通信的基本方式可分为并行通信与串行通信两种: 并行通信:是指利用多条数据传输线将一个资料的各位同时传送.它的特点是传输速度快,适用于短距离通信,但要求通讯速率较高的应用场合. 串行通信:是指利用一 ...

  9. vscode php插件_「PHP从入门到颈椎病康复」基础篇——HelloWorld

    需要的前驱知识 在学习这篇文章之前,需要有一点HTML的基础,需要的小伙伴可以点开我的主页,查看<「HTML从入门到颈椎病康复」>系列文章. 啥玩意是php PHP:"超文本预处 ...

最新文章

  1. Asp.Net SignalR 集线器不使用代理的实现
  2. 畅想下计算机/计算型设备的未来
  3. python中分支结构与c语言中有何区别_C语言的分支语句有哪几种?C语言分支结构的基本形式是什么,区别是什么?...
  4. create view必须是批处理中仅有的语句_sqlserver 脚本和批处理指令小结
  5. [转帖]Runtime, Engine, VM 的区别是什么?
  6. 3、以太网基础知识——ARP地址解析协议原理
  7. 需求规格说明书格式及要求
  8. uploadify php处理程序,uploadify 后台处理
  9. Java中移位操作运算符的理解
  10. python模块下载失败_python 安装tushare模块出错的一个解决方法
  11. 无限递归替换文件内的某个字符串
  12. 史上最全android分辨率
  13. 如何制作出色的R可重现示例
  14. AtCoder Beginner Contest 173 D - Chat in a Circle
  15. 致敬ATSS | Dynamic ATSS再造ATSS辉煌!!!
  16. SQL注入漏洞-SQL盲注
  17. 常见电子书类型及阅读器
  18. 【前端】js关于鼠标划过事件
  19. matplotlib is required for plotting.
  20. edcoder数据结构第1关:基于BF算法的病毒感染监测

热门文章

  1. gtk_widget_modify_bg的用法
  2. android 实现代码混淆
  3. even though和even if的区别
  4. Eclipse·Maven·构建SpringMVC简单工程-3
  5. 2016 版 Laravel 系列入门教程(三)【最适合中国人的 Laravel 教程】
  6. 开源呼叫中心软件 GOautodial 存在两个漏洞,可导致RCE
  7. 微软将 Teams 移动应用纳入漏洞奖励计划,最高奖金3万美元
  8. 火眼:利用FTA 服务器0day攻击全球百家企业的是 FIN11
  9. 美国政府发布关键海事行业的网络安全规划
  10. MITRE 发布 2020 CWE Top 25 榜单