实验指导书:串口通信实验实验目的:通过程序,理解并验证串口通信的编程方法和机制。
本次实验分两个环节,第一环节为用程序发送字符串,用linux命令在另一窗口直接从串口读取;第二环节为用发送程序发送字符串,用接收程序在另一窗口读取串口并显示。
要求必须完成第一环节,而第二环节为选作。
本实验在虚拟机环境下完成,利用虚拟机创建两个虚拟串口,基于这两个虚拟串口完成串口通信实验。
实验内容:本次实验需要在linux环境下,用vi工具输入对应的程序,并编译通过,运行后观察结果是否正确。
一、设置虚拟机串口1.1 VMware的串口:一个虚拟机最多可以添加四个虚拟串口,有如下3个方法配置虚拟串口:(1) 连接一个虚拟串口到宿主机的物理串口。
(2) 连接一个虚拟串口到宿主机上的一个文件。
(3) 在两个虚拟机之间建立一个直接的连接,或者将虚拟机的串口与宿主机的应用程序连接。
1.2 为虚拟机添加串口首先要保证虚拟机下的linux处于关机(power off)状态,(1) 选择菜单中的虚拟机 设置(英文版为:VM -> Settings),在硬件(Hardware)标签页中,如果已有串行端口(serial port),则选中该串口,并点选移除。
(2) 点击Add按钮,在Add Hardware Wizard对话框中选择Serial Port,点击next,分两次添加两个串口,具体的选项如下图:串口2的设置:注意两个串口都使用了命名管道方式,但一个是服务器端,一个是客户端。
(3) 启动linux操作系统,测试两个串口是否设置成功在linux桌面空白处点击右键,打开两个终端窗口。
在其中一个窗口(称为窗口A)中,建立工作目录,并进入该目录。
即,执行下述命令:[1]cd /home[2]mkdir src[3]cd src[4]cat /dev/ttyS1 //注意是大写的S在另一个窗口(称为窗口B)执行下述命令:[5]cd /home/src[6]echo hello >/dev/ttyS0 //注意是大写的S此时,应在窗口A中显示出“hello”这个字符串,这表明窗口B通过串口/deb/ttyS0发送的字符串,通过串口连接,在窗口A的串口/dev/ttyS1上接收到了该字符串。
在窗口A输入Ctrl+c,可推出cat命令。
环境设置完毕。
可进入下面的代码编辑、编译、执行环节。
二、仅创建串口发送程序,用在linux下用cat命令直接读取串口该环节为用ttySend程序发送字符串,用linux的cat命令在另一窗口直接从串口读取[7]vi ttySend.c //创建ttySend.c文件,并输入下述代码ttySend.c:/******************************************************** File Name:send.c* Description:send data to serial_Port* Date:*******************************************************//******************头文件定义******************/#include <stdio.h>#include <string.h>#include <malloc.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <termios.h>#define max_buffer_size 100 /*定义缓冲区最大宽度*//*******************************************/int fd; /*定义设备文件描述符*/int flag_close;int open_serial(int k){if(k==0) /*串口选择*/{fd = open("/dev/ttyS0",O_RDWR|O_NOCTTY); /*读写方式打开串口*/perror("open /dev/ttyS0");}else{fd = open("/dev/ttyS1",O_RDWR|O_NOCTTY);perror("open /dev/ttyS1");}if(fd == -1) /*打开失败*/return -1;elsereturn 0;}/********************************************************************/int main(int argc, char *argv[ ] ){char sbuf[]={"Hello,this is a Serial_Port test!\n"};/*待发送的内容,以\n为结束标志*/ int sfd,retv,i;struct termios option;int length=sizeof(sbuf);/*发送缓冲区数据宽度*//*******************************************************************/open_serial(0); /*打开串口1*//*******************************************************************/printf("ready for sending data...\n"); /*准备开始发送数据*/tcgetattr(fd,&option);cfmakeraw(&option);/*****************************************************************/cfsetispeed(&option,B9600); /*波特率设置为9600bps*/cfsetospeed(&option,B9600);/*******************************************************************/tcsetattr(fd,TCSANOW,&option);retv=write(fd,sbuf,length); /*接收数据*/if(retv==-1)perror("write");printf("the number of char sent is %d\n",retv);flag_close = close(fd);if(flag_close == -1) /*判断是否成功关闭文件*/printf("Close the Device failur!\n");}输入完毕后保存退出。
执行命令:[8]gcc -o ttySend ttySend.c //编译,并指定生成文件为ttySend编译成功后,再linux桌面空白处点击右键,新建一个终端,执行下述命令:[9]cat /dev/ttyS1 //注意,是大写的S,用于接收发送端发送的字符串然后切换回刚才的编译窗口,执行下述命令:[10]./ttySend //发送字符串显示如下:此时,在接收的终端窗口,应显示如下:按ctrl+C可退出接收程序的等待循环三、ttySend程序发送,ttyReceive程序接收步骤一是用ttySend程序发送,用cat命令直接在另一个终端接收了串口的输出。
本步骤在步骤一的基础上,用ttySend程序发送,用ttyReceive程序接收。
在步骤一的接收窗口,按ctrl+C退出cat接收命令,并执行下述命令:[11]cd /home/src //进入工作目录[12]vi ttyReceive.c //创建ttyReceive.c文件,并输入下述代码ttyReceive.c/******************************************************** Filename:receive.c* Description:Receive data from Serial_Port* Date:*******************************************************//*********************头文件定义***********************/#include <stdio.h>#include <string.h>#include <malloc.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <termios.h>#include "math.h"#define max_buffer_size 100 /*定义缓冲区最大宽度*//*********************************************************/int fd,s;int open_serial(int k){if(k==0) /*串口选择*/{fd = open("/dev/ttyS0",O_RDWR|O_NOCTTY); /*读写方式打开串口*/ perror("open /dev/ttyS0");}else{fd = open("/dev/ttyS1",O_RDWR|O_NOCTTY);perror("open /dev/ttyS1");}if(fd == -1) /*打开失败*/return -1;elsereturn 0;}/********************************************************************/int main(){char hd[max_buffer_size],*rbuf; /*定义接收缓冲区*/int flag_close, retv,i,ncount=0;struct termios opt;int realdata=0;/*******************************************************************/open_serial(1); /*打开串口1*//*******************************************************************/tcgetattr(fd,&opt);cfmakeraw(&opt);/*****************************************************************/ cfsetispeed(&opt,B9600); /*波特率设置为9600bps*/ cfsetospeed(&opt,B9600);/*******************************************************************/tcsetattr(fd,TCSANOW,&opt);rbuf=hd; /*数据保存*/printf("ready for receiving data...\n");retv=read(fd,rbuf,1); /*接收数据*/if(retv==-1){printf("read error:%d\n",retv);perror("read"); /*读状态标志判断*/}/*************************开始接收数据******************************/while(*rbuf!='\n') /*判断数据是否接收完毕*/{ncount+=1;rbuf++;retv=read(fd,rbuf,1);if(retv==-1){printf("read error in while\n");perror("read");}}/*******************************************************************/ printf("The data received is:\n"); /*输出接收到的数据*/for(i=0;i<ncount;i++){printf("%c",hd[i]);}printf("\n");flag_close =close(fd);if(flag_close == -1) /*判断是否成功关闭文件*/printf("Close the Device failur!\n");}输入完毕后保存退出。