嵌入式Linux系统串口和以太网编程
更新时间:2023-10-16 10:54:01 阅读量: 综合文库 文档下载
- 嵌入式LINUX推荐度:
- 相关推荐
中国地质大学(北京)
实 验 报 告
课程名称:嵌入式系统
实验名称:嵌入式Linux系统串口和以太网编程 姓 名: 学 号: 班 级:
指导教师:曾 卫 华 评 分: 实验时间: 2013.5
实验题目:嵌入式Linux系统串口和以太网编程
一、实验目的
1、 熟悉Linux环境
2、 掌握嵌入式开发的基本流程,培养解决问题的能力 3、 掌握Linux串口及以太网socket的应用程序开发 4、 自学嵌入式Linux中多线程编程基础
二、实验内容
本次实验通过编写服务器(开发板)与客户端(虚拟机ubuntu)上的应用程序,来实现服务器与客户端之间信息的透明转发,构成类似于聊天的功能。该功能实现包括两个方面。
其一:服务器通过串口从终端(电脑键盘)上读取(read)数据,再通过网络(clifd)把读取到的数据发送到客户端,客户端在接收到数据后在显示器上打印出来; 其二:客户端把数据通过网络发送到主机上,主机接收到数据后通过串口写到电脑终端软件(SecureCRT)进行显示。实验流程图如下:
图一:总体框架图
三、基础知识
1、 掌握linux串口和以太网socket应用程序开发方法:
串口配置:?打开串口,获得串口的使用句柄fd ??获取原先配置参数并进行保存??设置波特率??设置奇偶校验位??设置??设置停止位??设置最少接受字符和等待时间??设置数据位、无流控等相关参数??激活最新配置??结束时还原串口原先配置。 网络socket编程:
服务器端:?创建一个socket??bind(),给socket注册服务器端口地址??listen(),
1 / 15
开始监听已经绑定的端口,创建监听队列??accept(),返回一个新的socket,阻塞等待客户端client的连接?? send(),recv()发送和接收数据??close(),关闭服务器。客户端:?创建一个socket??connect(),建立与服务器的连接??send(),recv()发送和接收数据???close(),关闭客户端。 2、 掌握linux系统中线程的使用方法:
在linux中创建新的线程可以使用两种方式:pthread_create()函数和fork()函数。 pthread_create()使用:
int pthread_create(pthread_t *restrict thread, const pthread_attr_t *restrict attr,
void *(*start_routine)(void*), void *restrict arg);
参数:thread输出线程id,attr 线程属性, 默认NULL,start_routine线程执行函数,arg线程执行参数 。函数成功时返回0, 否则返回错误码。 fork()函数的使用:
一个现有进程可以调用fork函数创建一个新进程。由fork创建的新进程被称为子进程(child process)。fork函数被调用一次但返回两次。两次返回的唯一区别是子进程中返回0值而父进程中返回子进程ID。这样,对于程序,只要判断fork函数的返回值,就知道自己是处于父进程还是子进程中。
四、实现过程
1、 4.4.3交叉编译工具的PATH已经生效,在任意目录下能够执行arm-linux-gcc –v 2、 在开发板上进行内核以及根文件系统的移植,构建嵌入式linux系统 3、 nfs网络文件系统的配置:
1.打开nfs1175.exe
2.配置板子ip,使其和电脑ip在同一个网段
3.挂载:在板子上运行 #mount -t nfs -o nolock 202.204.100.66:/f/aaa/LINUX/Share /mnt/nfs
4.使用 cd /mnt/nfs/0522 进入nfs共享目录下,ls 显示共享目录下的文件; 4、 仔细阅读提供的代码server.c和client.c Target为服务器,Ubuntu为客户端。修改和
完善代码,在原代码的基础上实现新的功能
5、 交叉编译server.c(# arm-linux-gcc -lpthread -o server server.c) 6、 本地编译client.c(# gcc -o client client.c -lpthread)
7、 在板子上运行server可执行文件: #chmod 777 server,运行server: #./server 8、 在ubuntu上运行client程序:# ./client 202.204.100.67;
五、 实验结果
客户端运行client与服务器端运行server建立通信
2 / 15
服务器端:
客户端:
按下$中断通信 服务器端:
客户端:
六、心得体会
在这一次的实验中,我们先建立硬件实验平台,又建立主机软件开发环境,接着为实验进行各项配置,最后完成了各个实验中的多种功能。很重要的一点,前期的硬件、软件准备
3 / 15
必须完整无误地实现,这是后续的实验能顺利进行的前提。
本实验中,已经给出了串口程序和socket编程的程序,需要我们自学多线程编程的知识并结合已经学过的串口和以太网编程来修改和完善代码,在原代码的基础上实现新的功能。即便如此,还是不太简单的。在这一次的实验中,我深深地感受到基础知识不扎实的严重后果:在实际的开发过程中会遇到各种各样的问题(如线程的使用,程序代码的容错处理,莫名问题的解决等)。究其原因还是对知识的掌握不够牢固,一知半解。所以,必须要详细了解其实现过程和原理才能够尽量避免开发过程中错误的发生,提高开发进度。
通过这一次的实验对于嵌入式linux的开发过程有了一个总体的把握和认识,我深知目
前所掌握的嵌入式linux知识还只是皮毛,必须还要进一步的深入才能够有所提升。这也是我今后需要提高的方向。
最后感谢曾卫华老师的悉心教导!
附录(程序源码)
客户端代码: #include
#define SERVER_PORT 20000 // define the defualt connect port id
#define CLIENT_PORT ((20001+rand())e536) // define the defualt client port as a random port
#define BUFFER_SIZE 256
#define LENGTH_OF_LISTEN_QUEUE 10 //length of listen queue in server #define WELCOME_MESSAGE \
void usage(char* name) { }
struct sockaddr_in servaddr,cliaddr; int servfd,clifd,length = 0;
4 / 15
printf( \
struct sockaddr_in servaddr,cliaddr; socklen_t socklen = sizeof (servaddr);
char buf[BUFFER_SIZE],buf2[BUFFER_SIZE]; pthread_t tidp,tidp2; int pth;int runflag=0;
void *Thread1(void *arg) { }
void *Thread2(void *arg) { }
int main(int argc, char** argv) {
if(argc < 2 ) { }
if((clifd = socket(AF_INET,SOCK_STREAM,0)) < 0 ) //tcp {
printf( \ exit( 1 );
5 / 15
while(runflag){
memset(buf,0,BUFFER_SIZE);
length = recv(clifd, buf,BUFFER_SIZE, 0);
if(strstr(buf,\if(length > 0) printf(\ }
printf(\while(runflag){ }
memset(buf2,0,BUFFER_SIZE);
scanf(\if(strstr(buf2,\
usage(argv[0]); exit( 1 );
}
srand(time(NULL)); // initialize random generator
bzero( & cliaddr, sizeof (cliaddr)); cliaddr.sin_family = AF_INET;
cliaddr.sin_port = htons(CLIENT_PORT); cliaddr.sin_addr.s_addr = htons(INADDR_ANY);
if(bind(clifd,(struct sockaddr* )&cliaddr,sizeof(cliaddr)) < 0 ) {
printf( \ exit( 1 );
}//绑定的目的是让其端口是随机的,否则端口是自增1 //一般情况下client端不用绑定
bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; inet_aton(argv[1], &servaddr.sin_addr); servaddr.sin_port = htons(SERVER_PORT);
if(connect(clifd,( struct sockaddr *)&servaddr, socklen) < 0) { }
runflag=1;
6 / 15
printf( \ exit(1);
pth=pthread_create(&tidp,NULL,Thread1,NULL); if(pth!=0) {printf(\
pth=pthread_create(&tidp2,NULL,Thread2,NULL); if(pth!=0) {printf(\pthread_detach(tidp); pthread_detach(tidp2);
}
while(runflag){ ;}
close(clifd);
return 0;
服务器端代码: #include
#define SERVER_PORT 20000 //define the defualt connect port id #define LENGTH_OF_LISTEN_QUEUE 10 //length of listen queue in server
7 / 15
#define QUEUE 20 //length of listen queue in server #define BUFFER_SIZE 256
#define WELCOME_MESSAGE \ static struct termios g_newtio,g_oldtio;
static int speed_arr[] = {
B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300, B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300, };
static int name_arr[] = {
115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300, 115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300, };
/********************************************************************** * 函数名称: // 函数名称
* 功能描述: // 函数功能、性能等的描述
* 输入参数: // 输入参数说明,包括每个参数的作用、取值说明及参数间关系 * 输出参数: // 对输出参数的说明。 * 返 回 值: -1:Failed * 其它说明: // 其它说明
* 修改日期 版本号 修改人 修改内容 * ------------------------------------------------------------- * 2007/10/10 V1.0
XXXX XXXX
***********************************************************************/ int Init_COM(int Comm,int Baudrate,int Parity,int Stopbit,int Flagblock) {
int ret,i;
char dev_buf[16];
if(Comm > 3)
8 / 15
{ }
memset(dev_buf,0x00,sizeof(dev_buf)); sprintf(dev_buf,\
if(Flagblock) { } else { } if(ret < 0) { }
printf(\return -1;
ret = open(dev_buf, O_RDWR | O_NOCTTY | O_NONBLOCK); //以非阻塞方式打开; ret = open(dev_buf, O_RDWR | O_NOCTTY ); // 以默认阻塞方式打开; printf(\return -1;
if( tcgetattr(ret, &g_oldtio) < 0 ) { }
for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++) {
if(Baudrate == name_arr[i]) {
cfsetispeed(&g_newtio,speed_arr[i]); cfsetospeed(&g_newtio,speed_arr[i]);
9 / 15
printf(\ return -1;
}
}
break;
if(i>=sizeof(speed_arr) / sizeof(int)) {
printf(\
}
return -1;
switch (Parity) { // 设置奇偶校验位数
case 'n': case 'N':
g_newtio.c_cflag &= ~PARODD; //very important; zwh g_newtio.c_cflag &= ~PARENB; /* Clear parity enable */
break; case 'o': case 'O':
g_newtio.c_cflag |= PARENB; /* Enable parity */
g_newtio.c_cflag |= PARODD; /* 设置为奇效验*/
break; case 'e': case 'E':
g_newtio.c_cflag |= PARENB; /* Enable parity */ g_newtio.c_cflag &= ~PARODD; /* 转换为偶效验*/
break;
default:
printf(\
}
return -1;
/*stop bit */ switch(Stopbit)
10 / 15
{ }
g_newtio.c_iflag = 0; //输入无校验 g_newtio.c_oflag = 0; //输出不处理 g_newtio.c_lflag = 0; //RAW模式
g_newtio.c_cc[VTIME] = 1; /* unit: 1/10 second. */
g_newtio.c_cc[VMIN] = 1; /* minimal characters for reading */
case 1:
g_newtio.c_cflag &= ~CSTOPB;
break; case 2:
g_newtio.c_cflag |= CSTOPB;
break; default:
printf(\ return -1;
g_newtio.c_iflag &= ~INPCK; /* Disable parity checking */ }
11 / 15
g_newtio.c_cflag &= ~CRTSCTS; //NO flow control g_newtio.c_cflag &= ~CSIZE;
g_newtio.c_cflag |= CS8; //databit=8 g_newtio.c_cflag |= CLOCAL; //本地连接 g_newtio.c_cflag |= CREAD; //允许接收数据
if( tcsetattr(ret, TCSANOW, &g_newtio) != 0 ) /*success*/ { }
tcflush (ret, TCIOFLUSH); //清空输入输出队列
printf(\return -1;
return ret;
void RestoreComConfiguration(int fd,struct termios *ptios) { }
int fd;char buf[1024],buf2[1024]; int servfd,clifd;
struct sockaddr_in servaddr,cliaddr; int runflag=0;
void *Thread1(void *arg) { }
void *Thread2(void *arg) {int length=0;
while(runflag)
{char stdstr[1024]=\
length = recv(clifd, buf2,1024, 0); if(length > 0) { }
12 / 15
if( tcsetattr(fd, TCSANOW, ptios) != 0 ) { }
/*success*/
printf(\
printf(\while(runflag) { }
memset(buf,0,BUFFER_SIZE); read(fd,buf,1024);
send(clifd,buf,strlen(buf), 0);
if(strstr(buf,\
strcat(stdstr,buf2);strcat(stdstr,\
if(strstr(buf2,\write(fd,stdstr,strlen(stdstr));
}
}
void socket_init(void) {
if((servfd = socket(AF_INET,SOCK_STREAM, 0 )) < 0)
{ }
int main(int argc,char *argv[]) {
fd = Init_COM(COM0,115200,'N',1,BLOCK_MODE); socket_init(); pthread_t tidp,tidp2;
13 / 15
printf(\ exit(1);
}
bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERVER_PORT); servaddr.sin_addr.s_addr = htons(INADDR_ANY);
if(bind(servfd,(struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
printf( \ exit(1);
}
if(listen(servfd,QUEUE) < 0) // LENGTH_OF_LISTEN_QUEUE { }
socklen_t length = sizeof(cliaddr);
printf( \ exit(1);
clifd = accept(servfd,( struct sockaddr *) &cliaddr, &length);
if(clifd < 0) { printf( \
int pth;
if(fd >= 0) RestoreComConfiguration(fd,&g_oldtio);
runflag=1;
pth=pthread_create(&tidp,NULL,Thread1,NULL); if(pth!=0) {printf(\
pth=pthread_create(&tidp2,NULL,Thread2,NULL); if(pth!=0) {printf(\pthread_detach(tidp); pthread_detach(tidp2); while(runflag){
;
}
}
close(clifd);close(fd);close(servfd); return 0;
14 / 15
正在阅读:
嵌入式Linux系统串口和以太网编程10-16
二年级语文下册第一单元第一课《找春天》作11-01
新闻作品与案例分析答案04-16
“职业生涯规划”主题班会08-10
政府行文排版标准01-31
多姿多彩的风作文800字07-07
转正申请书2022年最新版【10篇】参考03-25
林果站一季度工作小结及下阶段工作思路10-04
20XX年幼儿园辅导员下半年工作计划范文12-11
- 多层物业服务方案
- (审判实务)习惯法与少数民族地区民间纠纷解决问题(孙 潋)
- 人教版新课标六年级下册语文全册教案
- 词语打卡
- photoshop实习报告
- 钢结构设计原理综合测试2
- 2014年期末练习题
- 高中数学中的逆向思维解题方法探讨
- 名师原创 全国通用2014-2015学年高二寒假作业 政治(一)Word版
- 北航《建筑结构检测鉴定与加固》在线作业三
- XX县卫生监督所工程建设项目可行性研究报告
- 小学四年级观察作文经典评语
- 浅谈110KV变电站电气一次设计-程泉焱(1)
- 安全员考试题库
- 国家电网公司变电运维管理规定(试行)
- 义务教育课程标准稿征求意见提纲
- 教学秘书面试技巧
- 钢结构工程施工组织设计
- 水利工程概论论文
- 09届九年级数学第四次模拟试卷
- 以太网
- 串口
- 嵌入式
- 编程
- 系统
- Linux
- 整式的乘除培优
- 深圳市拆除重建类城市更新项目操作基本程序
- 三年级下册英语素材-单词趣味记忆法
- 建筑一体化屋顶光伏电站施工组织设计
- 2017年钢结构桥梁行业现状及发展趋势分析(目录)
- 毛概试卷五
- 鞠萍姐姐讲故事 120集目录
- 最简单易懂的化学方程式的配平方法
- 实验四 Matlab图形绘制
- 历史在歌声中回荡 - 从命歌曲的演变看中共成立90周年
- 汇编语言习题答案1-7
- 南沙
- 14秋现代人力资源开发与管理期末(教师)
- 六年级数学(下)期末复习(二)
- 2011环境微生物学考研试题及答案 - 图文
- 英语论文 翻译
- 2019新课标人美版小学美三年级下册3《画中的线条》案例 doc
- 作文素材一材多用 公开课教案
- 烟草调制与分级
- 有色金属材料练习题