嵌入式系统课程设计报告样例1.docx

上传人:b****8 文档编号:30449886 上传时间:2023-08-15 格式:DOCX 页数:34 大小:596.21KB
下载 相关 举报
嵌入式系统课程设计报告样例1.docx_第1页
第1页 / 共34页
嵌入式系统课程设计报告样例1.docx_第2页
第2页 / 共34页
嵌入式系统课程设计报告样例1.docx_第3页
第3页 / 共34页
嵌入式系统课程设计报告样例1.docx_第4页
第4页 / 共34页
嵌入式系统课程设计报告样例1.docx_第5页
第5页 / 共34页
点击查看更多>>
下载资源
资源描述

嵌入式系统课程设计报告样例1.docx

《嵌入式系统课程设计报告样例1.docx》由会员分享,可在线阅读,更多相关《嵌入式系统课程设计报告样例1.docx(34页珍藏版)》请在冰豆网上搜索。

嵌入式系统课程设计报告样例1.docx

嵌入式系统课程设计报告样例1

 

《嵌入式系统》课程设计报告

 

设计课题:

基于web的嵌入式智能家

居控制系统

 

专业班级:

09电气

(1)班

学生姓名:

 黄礼智 

指导教师:

雷必成

设计时间:

2012学年第一学期

物理与电子工程学院

摘要

基于web的嵌入式智能家居控制系统采用了三星公司生产的S5PV210AH_A01141芯片,是一款ARM11芯片。

将嵌入式WEB远程控制系统应用在智能家居方面是未来发展的必然趋势。

智能家居、嵌入式系统和WEB服务器三者结合,通过构建嵌入式WEB服务器,研究设计通过WEB控制家电设备,以及在linux系统下搭建WEB服务器,使得用户可以随时随地地通过浏览器实现对家电设备的控制。

本文介绍了在ARM嵌入式系统上搭建boa服务器的方法,分析了各种控制方法,得出了实现基于web的嵌入式智能家居控制系统的最直接可行的方案。

最后利用C语言编译出了CGI程序和服务程序。

关键词

WEB;linux嵌入式;boa服务器;CGI

 

1.智能家居控制系统总体方案设计

1.1 系统总体架构设计

本文中整个控制系统那个分为3个模块:

中央处理器(ARM11),室内信号监测模块,控制执行模块。

中央处理器所在的模块由于涉及到高频信号,普通制板均达不到要求,因此直接采用ARM核心板,设计相应的控制板,两者结合使用。

从系统稳定性和搭建服务器难度上考虑,linux系统成为不二的选择。

Linux系统平台下容易搭建服务器,linux系统也不断在被优化,它的稳定性更是经受住了时间检验。

linux设备驱动都是用C语言编写的,对于学过C语言的我们更有利于深入。

下面是系统的整体结构图:

传感器

家居控制系统

BOA服务器

Linux

控制

客户端浏览器

开关

显示

 

图2-1 系统结构图

2. 嵌入式WEB服务器BOA的建立

搭建BOA的主要步骤如下[2]:

(1)下载BOA服务器源码,我们可以从网上下到boa-0.94.13.tar.gz。

将压缩包解压到linux系统任意目录下。

(2)打开BOA位于内核源码中Boa/src/define.h,查看其DocumentRoot后面的目录,默认为ect/boa。

此目录为Boa服务器的根目录,当boa服务器运行后,会从该目录读取配置文件,配置文件中保存着服务器配置信息。

用户可根据需要对define.h中的根目录进行修改,一般情况下木有修改必要,本次设计也没有对该项进行修改。

(3)生成makefile文件:

在boa/src/目录下执行./configure命令。

(4)修改该makefile文件:

因为要在arm环境下建立BOA服务器,所以要将makefile中的编译器gcc改成arm-linux-gcc,在PC机上建立则无需修改。

具体修改如下:

找到CC=gcc改为CC=arm-linux-gcc;找到CPP=gcc-E改为CPP=arm-linux-gcc-E。

(5)执行#make命令。

make编译时用2.95.3以上的版本会出错:

util.c:

100:

1:

pasting“t”and“->”doesnotgiveavalidpreprocessingtokenmake:

[util.o]Error1。

解决方法:

修改compat.h中的#defineTIMEZONE_OFFSET(foo)foo##->tm_gmtoff为:

#defineTIMEZONE_OFFSET(foo)foo->tm_gmtoff。

(6)去除调试编译信息:

#/boa程序所在目录/arm-linux-stripboa

(7)配置BOA配置文件,配置文件中指定了网页和cgi程序所在目录等信息,具体如下[3]:

●Port80//侦听端口

●Userroot//用户名

●Grouproot//用户组

●ErrorLog/dev/console//错误日志

●AccessLog/dev/null//访问日志

●ServerNamefriendly-arm//服务器名称

●DocumentRoot/home/plg//指定文件根目录

●DirectoryIndexindex.html//指定默认首页名称

●KeepAliveMax1000//最大连接数

●KeepAliveTimeout10//设置连接超时时间单位:

S

●MimeTypes/etc/mime.types//设置媒体类型路径

●DefaultTypetext/plain

●CGIPath/bin//cgi程序所在位置

●AddTypeapplication/x-httpd-cgicgi

以上是本次毕业设计的配置,一般需要更改的地方有:

User和Group通常设为0;DocumentRoot项,根据实际情况设置网页等文件所在的路径,默认在/www目录下,考虑到ftp传输,故将其设置在了ftp传输的根目录下面/home/plg。

CGIPath项设置cgi程序所在位置,若根目录下没有bin这个目录,自动会在根目录下寻找cgi文件,也可以不修改,如果不修改,则需要将cgi程序同index.html一起放在根目录下。

其余采用默认,但需要注意的是,/etc/目录下必须有mime.types文件,若没有,只需要去linuxPC系统里复制即可。

接下来运行BOA服务器,在PC端输入开发板设置的静态IP地址(这里默认是:

192.168.1.230)。

就可以看到index.html页面了!

至此BOA服务器搭建完成。

3.界面设计、CGI程序和驱动程序编写

3.1 界面设计

网页页面主要有各种表格和图片组成,用frontpage软件足够实现。

页面的内容可以根据实际需要进行添加或删减。

对于我们电气工程专业的学生来讲,有两个关键问题需要解决:

1、网页用什么样的格式向服务器提交数据。

2、服务器反馈回来的信息如何在网页上表现出来。

1)网页提交数据表格类型选取:

在参考类似设计的时候,看到友善之臂的tiny210用户手册中的网页管道控制LED例子[1],其网页控制输入表格是用radio的:

inputtype="radio"value="ping"name="type",这种一组可以包含多个不同值的输入方式对设计是很有利的,因此,直接选用radio作为网页提交数据的表格类型。

2)服务器反馈信息显示:

一般情况下,网页数据更新需要用到其它语言编写网页脚本,现有的知识水平无法直接解决这个问题。

退而求其次,决定使用C语言文件操作函数来对网页源码进行修改。

为了方便实现这个操作,在网页设计时,做了如下约定:

1 网页需要更新显示的内容用图片显示;

2 网页所调用的图片采用统一命名,同一类图片文件名仅相差一个字符;

3 网页要具备自动刷新功能;

这样做的好处是,用C语言文件操作函数修改一个字符,就能更改整个状态显示。

3.2 CGI简介

1.定义[4]:

CGI(CommonGatewayInterface)是HTTP服务器与你的或其它机器上的程序进行“交谈”的一种工具,其程序须运行在网络服务器上。

2.功能:

绝大多数的CGI程序被用来解释处理杰自表单的输入信息,并在服务器产生相应的处理,或将相应的信息反馈给浏览器。

CGI程序使网页具有交互功能。

3.运行环境:

CGI程序在UNIX操作系统上CERN或NCSA格式的服务器上运行。

在其它操作系统(如:

windowsNT及windows95等)的服务器上也广泛地使用CGI程序,同时它也适用于各种类型机器。

4.CGI处理步骤:

⑴通过Internet把用户请求送到服务器。

⑵服务器接收用户请求并交给CGI程序处理。

⑶CGI程序把处理结果传送给服务器。

⑷服务器把结果送回到用户。

总结下,cgi程序就是网页和PC机交谈的工具,它没有特定的语言规范,只是一种中间程序,我们可以用shell语言编写,也可以用C语言编写编程生成cgi文件。

网页在执行ACTION=**.cgi的时候会调用**.cgi程序。

本文设计最初参考网页控制led例程,故仍然采取命名leds.cgi,以表对原作的感谢。

一下是网页部分源码[1]:

类型

速率

 跑马灯

慢速

 计数器

.....

......

这段源码的第一句表示:

当用户按下提交按钮时,网页会以GET的方式向服务器传输提交的数据,提交的数据保存在网页环境变量QUERY_STRING中,然后调用leds.cgi程序,在CGI程序中用指令读出QUERY_STRING中的内容:

用C语言很简单,令指针变量data=getenv("QUERY_STRING")即可。

3.3 网页提交数据的两种方式:

GET/POST

从效果上讲GET和POST都是用来提交网页数据的,而我们也只是讨论到它们传输数据格式不同而已。

在对数据处理时,用GET方式比POST方式来的简单,因为POST必须用单表单,这处理起来相对麻烦[5]。

在传输数据量方面,GET最多只能传输1024字节,而且数据是以明文形式跟在url后面的,很显然,这也会导致数据安全问题,因为你的账户名和密码可以在历史记录中被看到,造成泄漏[5]。

POST没有数据长度上的限制,理论上可以无限大,只是受服务器处理能力限制。

如果数据是以POST提交的话,则需要先读取CONTENT_LENGTH环境变量,取得输入数据的长度后,再由标准输入设备取得这个长度的数据[5]。

两种方式提交的数据都有自己的编码格式,在网上可以查到相关资料,本次设计提交的数据比较简单,暂时也不用考虑安全问题,因此采用了GET的传输格式[5]。

3.4 CGI程序的编写

为了避免更多错误,提高编程效率,在用CGI处理GET提交的数据之前,我用fprint函数对指针data获取到的变量输出到文本文件上,以此确定GET数据的真实格式,同样的方法也适用POST,因为网上的资料只提供了编码方式,却没有具体的实际数据给出。

用fprint函数输出后,得到了字符串:

type1=ping3&type2=ping3&type3=ping2&type4=ping3....这样一来就很好处理了:

char*data;//指针变量,用于储存环境变量QUERY_STRING的字符串

FILE*fp;//文件指针

inttype[8]={};//用来保存type的组别

intping[8]={};//用来保存type组相应的值

chari,j,k;

data=getenv("QUERY_STRING");//获取环境变量的字符串

for(i=0,j=4,k=10;i<8;i++,j+=12,k+=12)//截取组别和相对应的值

{

type[i]=(int)*(data+j)-48;//获取组别,转化为整型变量

ping[i]=(int)*(data+k)-48;//获取值,转化为整型变量

}

注:

指针变量data保存的是字符串,数值1和字符“1”的ASCII值相差48,因此将字符串里的字符强制转化为整形后,减去48就为实际数值。

经过上面程序处理后,数组type和ping元素是一一对应的。

这样处理能够简化解码步骤,方便后续程序处理。

解码步骤完成后,接下来就是要将数据保存在文本文档中,供系统读取:

if((fp=fopen("007.txt","w+"))==NULL)//打开一个007.txt文件,若不存在则新建。

exit(0);//文件操作失败则退出

for(i=0;i<8;i++)//把组名按顺序输出到007.txt中

{

fprintf(fp,"%d",type[i]);

}

for(i=0;i<8;i++)

{

fprintf(fp,"%d",ping[i]);//把各组对应的值按顺序输出到007.txt中。

}

fclose(fp);//关闭文件

以上cgi程序实现了对网页提交的数据解码和保存。

但在实际操作时,调用cgi程序后,需要载入新的页面或者刷新网页,所以要求cgi程序能够向服务器返回一段网页源代码。

按照我目前掌握的C语言水平,向浏览器返回源代码只能通过printf()函数,但是如果要求返回的是一个完整的页面的话就需要成百上千条printf()语句,而且,网页源代码中的特殊符号和格式控制符会干扰C语言编译,处理起来相当麻烦。

当了解到shell语言能够很方便的将一个文件返回时,就采用程序调用的方式解决上面的问题:

1)建立一个文本类型的文件(led-result.template),文件的命名也是采用参考例程原来的命名。

将网页源代码保存在这个文件里。

2)用shell语言编写一个cgi程序:

#!

/bin/sh

echo"Content-type:

text/html;charset=gb2312"//一定要先返回的标签

echo

/bin/catled-result.template//将文本文档led-result.template里的数据输出

exit0

并将其命名为led.cgi。

3)在leds.cgi里调用led.cgi

Leds.cgi是由C语言编写的,linuxC语言中程序调用十分方便,仅用一个system()函数就可以实现:

system("/home/plg/led.cgi")。

调用时需要将被调用程序的路径一起作为参数输入。

至此为止,CGI程序编写任务就完成了。

3.5 驱动程序的编写

3.5.1 传感器信息采集驱动

这套智能家居系统信息交互是通过嵌入式芯片的GPIO口电平信号实现的。

传感器最终传给IO口的是高或者低电平信号,驱动程序的任务就是读取连接着传感器的IO口电平信号,根据信号信息更新网页信息。

GPIO口的电平读取原理和按键读取原理是一样的。

因此不必再自己编写底层驱动,传感器信息采集驱动只需要调用按键驱动读取GPIO口即可。

下面是一个按键例程[1]:

intbuttons_fd;//保存设备编号

charbuttons[8]={'0','0','0','0','0','0','0','0'};//用于保存按键当前状态

buttons_fd=open("/dev/buttons",0);//打开按键驱动设备

if(buttons_fd<0){

perror("opendevicebuttons");//打开失败则退出

exit

(1);

}

for(;;){

charcurrent_buttons[8];//按键值读取缓存

intcount_of_changed_key;//输出格式控制

//用read()函数读取实际按键值放入缓存中

if(read(buttons_fd,current_buttons,sizeofcurrent_buttons)!

=sizeofcurrent_buttons){

perror("readbuttons:

");//读取失败则显示错误信息

exit

(1);

}

//循环比较数组buttons[i]和current_buttons[i]中的值,若不相等说明按键i状态改变

for(i=0,count_of_changed_key=0;i

if(buttons[i]!

=current_buttons[i]){

buttons[i]=current_buttons[i];//更新button中的值,为下次比较做准备

printf("%skey%dis%s",count_of_changed_key?

",":

"",i+1,buttons[i]=='0'?

"up":

"down");//输出按键状态

count_of_changed_key++;

}

}

if(count_of_changed_key){

printf("\n");//格式控制

}

}

close(buttons_fd);

return0;

了解了按键例程功能后,我们就可以对它进行移植了。

在执行buttons[i]=current_buttons[i];后,button[i]已经保存了相应按键的最新状态,因此可以在这条语句后面加上判断语句,用于更新网页信息:

FILE*fp;

if((fp=fopen("led-result.template","r+"))==NULL)//以读写方式打开网页源码文件

exit(0);

switch(i)//定位到网页源代码中的指定位置

{

case0:

fseek(fp,1864L,0);break;

case1:

fseek(fp,2064L,0);break;

case2:

fseek(fp,2264L,0);break;

case3:

fseek(fp,2464L,0);break;

case4:

fseek(fp,4495L,0);break;

case5:

fseek(fp,4695L,0);break;

case6:

fseek(fp,4895L,0);break;

case7:

fseek(fp,5095L,0);

}

if(buttons[i]=='1')//判断按键状态

fprintf(fp,”1”);//根据案件状态修改网页源码的值,以更改网页显示

else

fprintf(fp,”0”);

fclose(fp);

注:

fseek(fp,nL,0)函数是文件定位函数,这里它的作用是定位到fp文件从头开始第n个位置。

这里实际上是对网页源码进行修改。

至此,传感器传来的电平信息都会在网页源码中体现,只要刷新网页,就能够看到端口的最新信息。

最后,用交叉编译成生成驱动程序——button。

3.5.2 模拟开关控制驱动

模拟开关控制驱动也是通过GPIO口控制模拟开关的,其本质是控制GPIO口的高点电平的输出。

与传感器信息采集驱动一样,也有现存的驱动可供调用,就是LED灯控制驱动,是在/dev下的leds。

也就是说我们可以直接通过调用驱动控制,举个简单例子:

fd=open("/dev/leds",0);//打开led驱动程序

if(fd<0)

{

perror("opendeviceleds");//显示错误信息

exit

(1);

}

ioctl(fd,0,3);//关闭第三盏led灯(IO口状态为高电平)

close(fd);//关闭驱动程序

打开leds这个驱动后,只需要用ioctl()函数就可以实现对IO口状态控制。

模拟开关驱动主要负责读取cgi程序生成的007.txt文件中的数据,根据数据内容改变GPIO口的状态,同时将GPIO口的状态反馈给网页。

数据读取:

chartype_tmp[8]={};//用于存放读取的组别字符信息

charping_tmp[8]={};//用于存放对应组别字符数值

inttype[8]={};//用于存放转化为整形后的组别信息

intping[8]={};//用于存放转化为整形后的数值信息

inti,fd;

if((fp=fopen("007.txt","r"))==NULL)//用读的方式打开007.txt文件

exit(0);

fread(type_tmp,1,8,fp);//在fp文件中读取8个1个字节大小数据,保存在type_tmp中

fread(ping_tmp,1,8,fp);

fclose(fp);

for(i=0;i<8;i++)

{

type[i]=(int)*(type_tmp+i)-48;//转换为数值

ping[i]=(int)*(ping_tmp+i)-48;

}

数据读取后重新分类保存在type[]和ping[]中,根据数值改变GPIO口状态:

for(i=0;i<8;i++)

{

num=type[i]-1;//因为总共只有4个led灯口,用num变量控制复用。

if(num>=4)

num-=4;

if(ping[i]==1)//根据组别和数据控制led端口的状态。

ioctl(fd,1,num);

elseif(ping[i]==2)

ioctl(fd,0,num);

}

端口状态改变后,向网页反馈状态信息,同样利用更改网页源码实现:

if((fp=fopen("led-result.template","r+"))==NULL)//原理同传感器信息采集驱动中部分程序

exit(0);

for(i=0;i<8;i++)

{

switch(i)

{

case0:

fseek(fp,2589L,0);break;

case1:

fseek(fp,2704L,0);break;

case2:

fseek(fp,2819L,0);break;

case3:

fseek(fp,2934L,0);break;

case4:

fseek(fp,5220L,0);break;

case5:

fseek(fp,5335L,0);break;

case6:

fseek(fp,5450L,0);break;

case7:

fseek(fp,5565L,0);break;

}

if(ping[i]==1)

fprintf(fp,"1");

elseif(ping[i]==

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 材料科学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1