您的位置 首页 > 数码极客

ft232rl如何与arduino通讯

串口是单片机中一种重要的数据通讯接口,本期我们就来学习一下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("\r\n")来实现回车换行,另外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"的模式下。

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

责任编辑: 鲁达

1.内容基于多重复合算法人工智能语言模型创作,旨在以深度学习研究为目的传播信息知识,内容观点与本网站无关,反馈举报请
2.仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证;
3.本站属于非营利性站点无毒无广告,请读者放心使用!

“ft232rl如何与arduino通讯”边界阅读