首页 理论教育 Energia软件实现UART通信

Energia软件实现UART通信

时间:2023-11-17 理论教育 版权反馈
【摘要】:UART是通用异步收发器的缩写,一般称为串口。UART有两根数据线:发送和接送,如图8-2所示。UART通信一般采用一对一的通信方式。通信一方的TXD连接另一方的RXD,一方的RXD连接另一方的TXD,两个线可以实现同时收/发数据,这称为全双工。MSP430G2 LaunchPad使用MSP430G2553控制器,只有一组串行端口,即P1.1和P1.2。1)UART串口工作原理在LaunchPad与其他器件通信的过程中,数据传输实际上都是以数字信号的形式进行的,串口通信也是如此。

Energia软件实现UART通信

UART(universal asynchronous receiver transmitter)是通用异步收发器的缩写,一般称为串口。UART有两根数据线:发送(TXD)和接送(RXD),如图8-2所示。UART通信一般采用一对一的通信方式。通信一方的TXD连接另一方的RXD,一方的RXD连接另一方的TXD,两个线可以实现同时收/发数据,这称为全双工。UART也可以采用一对多的通信方式,这里就不做介绍了。

在第3章中我们已经接触到串口的基本用法,通过LaunchPad上的USB接口与计算机进行串口通信。除此之外,还可以使用串口引脚连接其他的串口设备进行通信。

MSP430G2 LaunchPad使用MSP430G2553控制器,只有一组串行端口,即P1.1(TXD)和P1.2(RXD)。

1)UART串口工作原理

在LaunchPad与其他器件通信的过程中,数据传输实际上都是以数字信号(即电平的高低变化)的形式进行的,串口通信也是如此。当使用Serial.print()函数输出数据时,LaunchPad的发送端(TXD)会输出一连串的数字信号,这一连串的数字信号被称为数据帧(data frame)。

例如,当使用Serial.print(‘a‘)语句发送数据时,实际发送的数据帧格式如图8-3所示。

图8-3 UART数据帧格式

UART通信协议的数据帧首先是一个起始位,然后是7~8位可选的数据位、0~1位可选的地址判断位、0~1位可选的奇偶检验位和1~2位可选的高电平停止位。

(1)起始位。起始位是高电平到低电平的下降沿触发的,是一组数据帧开始传输的信号。

(2)数据位。数据位是一个数据包,其中承载了实际发送数据的数据段。当LaunchPad通过串口发送一个数据时,实际的数据可能不是8位,比如,标准的ASCII码是7位(0~127),而扩展的ASCII码则是8位(0~255)。如果数据使用标准ASCII码,那么每个数据包将使用7位数据。LaunchPad默认使用8位数据位。

(3)地址位。0表示前面7~8位传输的是数据,1表示前面7~8位传输的是地址,这对于一主机多个从机通信是有用的。对于1对1的连接方式是没有用的,可以省略。

(4)校验位。检验位是串口通信中一种简单的检错方式。可以设置为偶检验或者奇校验。也可以没有校验位。默认无检验位。

(5)停止位。每段数据帧的最后都有1~2位停止位(高电平),表示该段数据帧传输结束。默认是1位停止位。

当串口通信速率比较高或者外部干扰较大时,可能会出现数据丢失的情况。为了保证数据传输的稳定性,最简单的方式就是降低通信波特率或增加停止位和校验位。

2)HardwareSerial类库成员函数

Energia提供了一个HardwareSerial类,我们一直在使用的Serial是预先定义好的HardwareSerial类的一个对象。该类定义了很多成员函数。

(1)available()函数。

功能:获取串口接收到的数据个数,即获取串口接收缓存区中的字节数。接收缓存区默认情况下最多可以保存64 B的数据。

语法:Serial.available()。

参数:无。

返回值:可读取的字节数。

(2)begin()。

功能:初始化串口,配置串口的比特率

语法:Serial.begin(speed)。

参数:speed,波特率。

返回值:无。

(3)end()。

功能:结束串口通信,释放该串口占用的数字引脚,使它们可以作为普通数据引脚使用。

语法:Serial.end()。

参数:无。

返回值:无。

(4)find()。

功能:从串口缓存区读取数据,直至读到指定的字符串。

语法:Serial.find(target)。

参数:target,需要搜索的字符串或字符。

返回值:boolean型值,为true表示找到,为false表示没有找到。

(5)find Until()。

功能:从串口缓存区读取数据,直至读到指定的字符串或指定的停止符。

语法:Serial.find Until(target,terminal)。

参数:target,需要搜索的字符串或字符;terminal,停止符。

返回值:boolean型值,true表示找到,false表示没有找到。

(6)flush()。

功能:清空输入缓存区的内容。

语法:Serial.flush()。

参数:无。

返回值:无。

(7)parseFloat()。

功能:从串口缓存区返回第一个有效的float类型数据。

语法:Serial.parseFloat()。

参数:无。

返回值:float类型数据。

(8)parseInt()。

功能:从串口缓存区返回第一个有效的int类型数据。

语法:Serial.parseInt()。

参数:无。

返回值:int类型数据。

(9)peek()。

功能:从串口缓存区返回1字节的数据,但不会从接送缓存区删除该数据。

语法:Serial.peek()。

参数:无。

返回值:返回接收缓存区的第1字节的数据;如果没有可读数据,则返回-1。

(10)print()。

功能:将数据输出到串口。数据以ASCII码形式输出。如果想以字节形式输出数据,则需要使用write()函数。

语法:Serial.print(val);(www.xing528.com)

Serial.print(val,format)。

参数:val,需要输出的数据;

format,分两种情况:①输出的进制形式,包括BIN(二进制)、DEC(十进制)、OCT(八进制)、HEX(十六进制);②指定输出的float类型数据带有小数点的位数(默认为2位)。

返回值:输出的字节数。

(11)println()。其使用方式和print()函数相同,这里就不再展开。区别在于println()函数将数据输出到串口之后,还接着输出回车换行符。

(12)read()。

功能:从串口读取数据。与peek()函数不同,read()函数每读取1字符后,就会从接收缓存区移除该字节。

语法:Serial.read()。

参数:无。

返回值:返回接收缓存区的第1字节的数据;如果没有可读数据,则返回-1。

(13)readBytes()。

功能:从接收缓存区读取指定长度的字符,并将其存入一个数组中。若等待数据时间超过设定的超时时间,则退出该函数。

语法:Serial.readBytes(buffer,length)。

参数:buffer,用于存储数据的数组(char[]或者byte[]);

length,需要读取的字符长度。

返回值:读到的字节数;如果没有读到效长度的数据,则返回0。

(14)readBytes Until()。

功能:从接收缓存区读取指定长度的字符,并将其存入一个数组中。如果读到停止符,或者等待数据时间超过设定的超时时间,则退出该函数。

语法:Serial.readBytes Until(character,buffer,length)。

参数:character,停止符;

buffer,用于存储数据的数组(char[]或者byte[]);

length,需要读取的字符长度。

返回值:读到的字节数;如果没有读到效长度的数据,则返回0。

(15)set Timeout()。

功能:设置超时时间。用于设置Serial.readBytes()函数和Serial.readBytesUntil()函数的等待串口数据时间。

语法:Serial.set Timeout(time)。

参数:time,超时时间,单位ms。

返回值:无。

(16)write()。

功能:将数据输出到串口。数据以字节形式输出。

语法:Serial.write(val);

Serial.write(str);

Serial.write(buf,len)。

参数:val,需要输出的数据;

str,String类型的数据;

buf,数组型的数据;

len,缓存区的长度。

返回值:输出的字节数。

3)read()函数和peek()函数的区别

串口接收到的数据都会暂存在接收缓存区中,使用read()和peek()函数都是从接收缓存区中读取数据。不同的是,当使用read()读取数据后,会将该数据从接收缓存区中移除;而使用peek()读取数据时,不会移除接收缓存区中的数据。

表8-1列出了分别使用read()和peek()函数读取数据的示例代码,注意两个示例代码仅第11行和第12行不同。

表8-1 read()和peek()的区别

分别上传以上两个示例程序,打开串口监视器,向LaunchPad发送“hello”,则会看到如图8-4和图8-5所示的不同输出结果。

使用read()函数,串口依次输出了刚才发送的字符“hello”,输出完成后,串口进入等待状态,等待用户新的输入。而使用peek()函数在读取数据时,不会移除缓存区中的数据,因此使用available()获得的缓存区可读字节数不会改变,且每次读取时,都是读取当前缓存区的第1个字节‘h’,程序将无限循环下去。

图8-4 使用read()函数读取数据

图8-5 使用peek()函数读取数据

4)print()函数和write()函数的区别

这两个函数都可以输出数据,但输出形式并不相同。表8-2的示例程序对两个函数的差别进行了比较。

表8-2 print()函数与write()函数的区别

上传以上程序,打开串口监视器,输出结果如图8-6所示。

图8-6 print()与write()区别

当执行Serial.print(97)语句时,串口监视器会输出97;而当执行Serial.write(97)语句时,串口监视器会将97理解为ASCII码值而显示其对应的字符‘a’。

5)串口控制RGB LED色彩

第6章讲解了RGB LED的原理,并且利用随机数调节红、蓝和绿三个LED的显示亮度,组成一个绚丽的彩灯,本次实验我们将根据串口的输入调节RGB LED的色彩。示例的代码如表8-3所示。

上载以上程序,打开串口监视器,输入“255,0,0”后单击“Send”按键,红灯亮;输入“0,255,0”后点击“Send”按键,绿灯亮;输入“255,255,255”后单击“Send”按键,RGB LED为白色。

表8-3 串口控制RGB LED色彩示例代码清单

(续表)

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈