天津电子信息职业技术学院
毕业论文
题目 物联网智能家居系统
姓 名
专业班级
指导教师
完成时间
天津电子信息职业技术学院 制
2017.1
摘 要:随着经济的高速增长。建立一个低成本、高效率的智能家居系统已成为当今世界的一个热点话题。目前越来越多的智能家居产品出现在市场上,其中以基于电话网的智能安防系统居多。目前在我国,使用家庭电话的用户越来越少,而且电话线路受地域的影响严重容易损坏,所以这类产品局限性很大。随着电信GSM网络覆盖范围的无缝化、广阔化以及手机的日益普及为基于GSM网络的智能家居系统提供了巨大的应用空间。
本文设计了一种基于GSM网络的智能家居系统。本系统采用cortexA8为系统控制核心,对家庭中出现的意外情况使用各种传感器进行采集,然后通过GSM模块把采集到的信息发送给管理人员,管理员根据收到的信息发送相关指令给GSM模块来控制现场执行机构,完成意外情况的排除。
关键词:智能家居 GSM 传感器 远程控制
目录
一、 绪论 --------------------------------------------------------- 1
(一) 智能家居概述 -------------------------------------------- 1
(二) 智能家居网络构成 ---------------------------------------- 2
1、家居网络控制平台 ---------------------------------------- 2
2、智能家居子系统 ------------------------------------------ 2
3、智能家居网络的信号传输介质 ------------------------------ 3
4、远程控制技术概括 ---------------------------------------- 4
5、智能家居控制系统的国内外发展现状 ------------------------ 5
二、系统需求分析及方案 -------------------------------------------- 6
(一)应用程序功能需求分析 ------------------------------------- 6
(二)开发环境需求分析 ----------------------------------------- 6
1、 硬件环境 ----------------------------------------------- 6
2、 软件环境 ----------------------------------------------- 7
三、硬件模块及其驱动设计实现 -------------------------------------- 7
(一) 主控模块 ------------------------------------------------ 7
(二) 通信模块 ----------------------------------------------- 7
1、 TC35模块简介 ------------------------------------------- 7
2、 TC35模块与cortexA8连接方式 ---------------------------- 7
3、传感器模块 ---------------------------------------------- 8
四、系统软件部分 ------------------------------------------------- 36
(一)主程序及大致流程 ---------------------------------------- 36
1、温度监测线程 ------------------------------------------- 37
2、视频监测线程 ------------------------------------------- 38
3、报警流程 ----------------------------------------------- 39
(二)短消息程序设计 ------------------------------------------ 40
1、 AT指令介绍 -------------------------------------------- 40
2、PDU编码规则 -------------------------------------------- 42
3、短信模式设置 ------------------------------------------- 42
4、短信的发送方法 ----------------------------------------- 43
五、测试及结论 --------------------------------------------------- 43
(一)测试原则 ------------------------------------------------ 43
(二)测试方案 ------------------------------------------------ 43
(三)结论 ---------------------------------------------------- 44 参 考 文 献 ------------------------------------------------------ 45
一、 绪论
21世纪是信息化的时代,物联网新技术推动了人类文明的进步。随着人们生活水平的提高以及科技的高速发展,智能化家居已成为一种必然趋势而深入千家万户。智能化家居是利用电力自动化、计算机、网络通信、信息、结构化布线、无线等技术将多种设备应用和综合功能组成一个强大的完善的系统。它以住房为平台,同时兼备网络家电、家电设备自动化、建筑、通信、远程医疗、家庭办公、娱乐等功能,集结构、服务、系统、管理为一体的舒适、节能、安全、便利、高效、娱乐、环保的居住环境。
本文介绍的智能化家居控制系统可以使得人们通过手机在任何时候、任意地点对家中的任意电器(例如:热水器、空调、电饭煲、灯光等)进行远程控制。你可以在下班途中,预先将家中的空调打开、电饭煲煮好香喷喷的米饭、让热水器提前烧好热水,而这一切的实现都仅仅是靠一条短信完成。
本系统采用cortexA8作为主控器件,远程控制是基于GSM网络短消息通信方式,AT指令作为系统控制命令,cortexA8通过对收到的信息进行解码来识别控制信号,用户只需向TC35模块发送相应指令即可实现远程控制操作。温度传感器完成现场信息的采集,cortexA8对数据进行及时的处理,实现实时测控;短消息发送部分采用基于GSM模块TC35和IT公司的电平转换芯片MAX232等器件构成的移动终端的硬件电路,完成短消息收发功能。
(一) 智能家居概述
进入21世纪,科学技术与生产力加速了社会的发展创造能力,随之而来的也是人类对于物质水平的大力需求,而居住的环境要求也成为了人们关注的领域,所以“智能化”这一概念也促使科技工作者们将其引入智能家居民应用方面的小区住宅以及小区建筑技术之中。由于计算机控制系统发展迅速,以及电子信息行业的发展成长快速,也大力促进了智能家居控制系统的产生。因为固定电话和互联网技术基本上是传统智能家居控制系统的技术核心,所以安装固定电话以及互联网成为了达到家庭用户传统智能家居控制系统的产生的根本硬件技术、以及硬件要求。但是随着电子技术、智能通信技术以及网络技术发展日新月异的今天,基于GSM网络通讯体统的低成本无限制智能家居控制系统成为广大居民以及中国居民享受新一代智能家居控制系统的变革捷径。
智能家居系统成为一种新兴的综合技术学科。智能家居系统也可被定义为
一个控制过程,或者控制系统,利用现在被大多数科技人员已掌握的计算机技术、网络布线技术、网络通信系统将其糅合,使之成为融合在家居控制中的多个子系统,并使其智能的结合在一起。
目前相比较其他时分多址技术手段而言,更加完美、成熟、应用更广泛的一种普及率很高的系统是GSM(Global System for Mobile communication)系统。在我国,已建成的基本覆盖全国的GSM数字蜂窝移动技术信息网,早已成为我国公众移动生活密不可分的一种技术之一。在GSM短信服务的基础上,智能家居控制系统是在移动网络通讯技术的短信应用功能的技术运用。
由于GSM网络通讯系统在全国范围实现了联网以及漫游能力,所以它的网络功能很强大,用户无需另外搭建网络,因此,在GSM网络覆盖率达到全国范围的情况下,为客户省下了昂贵的网络搭建费用以及维护网络费用。同时,它对用户数量的限制也十分少,也为客户克服了一般智能家居控制系统中系统成本高、维护艰难、并且网络覆盖范围小以及用户组数量少的缺点。相比传统网络智能家居控制系统在网络通信覆盖率上具有较大的优势,加之GSM本身就具有数据的输送功能,这也促成了GSM应用在广大生活中得到迅速普及。基于GSM的无线通讯智能系统还具有双线传送数据的功能、性能稳定。为客户在远程操控以及用户控制设备提供了强大技术平台。
远程操控系统应用广泛,遍及中国经济生活发展的各大领域。而且目前人们正在使用中的操控系统从成本、性能、稳定性、便捷性以及维护的难易方面基本都不能使人们最大程度的满意。所以,GSM网络通信技术的提出大大的提升了智能家居控制系统的完善程度。
(二) 智能家居网络构成
1、家居网络控制平台
智能家居主控制平台是智能家居控制系统的“心脏”部分,等效的可以说是智能家居的核心。对方可以通过手机短信的方式接受用户命令并实时操作,或者对对用户手机发送控制电器运转情况,对家庭总线和各个网络子系统实施连接,完成智能家居控制系统平台的链接构成。
2、智能家居子系统
智能家居系统的连接一般均为家电网络中的耗电类型的家电电器。例如冰箱、空调、电磁炉、热水器、电饭煲、电灯等家用电器。这些消耗电类型的家
庭电器可以在现场立即布线互联构成智能家居系统,与主控家居智能平台相连接,再进行现场网络综合布线连接智能家居子系统,就可以由用户利用协议中的操作指令短信操作家庭中电器设备了。
3、智能家居网络的信号传输介质
智能家居网络通讯形式多彩多样,可以采用不同的传输介质传输网络通讯信号,大体上有电力线、电话线、双绞线、无线方式。
(1) 电力线
基于电力线为传输介质的通信网络可以说是最方便的,因为现在家庭基本都已铺设供电源的电源线而且家中的电源线已经延伸到家庭生活的每个角落。而且,现在大部分家用电器设备都离不开电源。所以利用家中的电力线完成智能家居控制系统网络方案方便而且经济便宜。在国际上,首个实现家庭电器智能化的方案便是通过电力线作为信息传输载体的而达成的。
(2) 电话线
利用电话线作为网络信息传输载体起步虽然相较于电力线稍微晚一些,但是因为它具有布局简单、使用方便、安全性能好和易于大规模推广等优点,而且近期电话线的传输速率也完成了大幅度提升,所以它的应用和发展非常快,在美国已有成熟的产品。其中包括:3COM、Advanced Micro—Devices、AT&T、Compaq、Hewlett.Packard、Intel、IBM和Lucent Technologies等发起成立了“电话线家居网络协会”,至今己有100多个成员。
(3) 双绞线/同轴电缆
目前最通用的传输介质是用双绞线/同轴电缆。可是在基于双绞线/同轴电缆实际操作中最大的困难是需要另外铺设2/4根专用的传输线。但是它拥有通信可靠性和总线接口相对简单等优点,其仍然可以受到广泛用户的大批量应用。
(4) 无线方式
无线方式通过射频载波或者红外线等形式传输用户信息,“蓝牙技术”是最近发展最火热的无线通信方式。音频和视频信号、计算机网络信号、控制信号均可以利用蓝牙技术传输家庭用户信号。而且用无线方式传输信息时无需架设任何线路且实现极其方便灵活,非常适合在家庭网络中应用。
由于无线方式简单方便,易于架设,所以本论文便是使用的GSM无线技术平台操作的智能家居平台系统。
4、远程控制技术概括
本论文研究立于一个对于家居电器进行远程控制,以便于实现家居智能化的系统。远程控制指的是远端的家居控制者通过通信系统对现场的家居电器系统进行控制,其目的在于解除地域和环境对控制的限制,实现高集中的远程控制,最终实现生产资料和社会资源与通讯资源的优化配置。现代远程控制技术是计算机技术、通信技术、网络技术的集合,也是信息技术和控制技术的结合。
从用户角度来讲,需要的是一种方便、安全、可靠的一种传输方式。可以利用公共数据网或者通过架设专线来实现有线传输,然而在大多数情况下,传输距离、架线环境等条件限制了有线传输[2]。无线传输也有很多途径,如架设微波线路、(超)短波电台等都是通过自建的无线发射接收系统。然而无线传输架设成本高、频率资源的限制、容易受到地形地貌的影响、系统的架设和维护工作繁重,在业务量小、用户数量大、位置分散等应用场合中也受到很大限制。目前,经过三代发展的移动通信,移动通信体制中的时分多址技术中最完善、最成熟、应用最广的一种移动通信系统就是GSM系统[2]。在数据采集、远距离监控、GPS定位、缴费通知、无线报警等领域GMS都有着广泛的应用。在全国范围内GSM网络实现了联网和漫游,用户无需另外组网,GMS具有很强的网络能力,网络覆盖范围广阔,用户不必再花费节昂贵的建网费用和维护费用[2]。比传统的集群系统在无线网络覆盖上具有无法比拟的优势,加上GSM的SMS本身具备的数据传送功能,都使得这些应用得到迅速的普及[2]。GSM短信息系统性能稳定还可进行双向数据传输,为监控设备和远程数据传送通信提供了一个可靠、安全的支持平台。
短消息发送一般采用其专用控制信道(DCCH)来发送,短信息的服务端可以实时的了解到对方是否接收到短信息,一旦信息传送失败,短信中心实时得知被叫用户没有回复信息,网络管理端则会继续发送消息,以保证被叫方能收到短信息。所以,在GSM网络的一些主要的电信业务当中,此类短消息业务的信息传递是实时安全的[2]。每个短消息的信息量都是140个八位组(7比特编码,160个字符)不会超过140个字节,绝对可以满足单方面监测用户指标的信息量。综上所述,智能家居控制系统选用GSM的短消息控制方式,来实现智能家居设备的远程控制是可行的。
5、智能家居控制系统的国内外发展现状
目前,我国每年竣工的建筑面积达到20亿平米,智能家居/建筑的产值至少在1-2万亿元以上。
智能家居的发展分为三个阶段:
首先是家庭电子化(Home Electronics)阶段,这个时期主要是面向单个的电器,家庭电器之间并没有形成网络,亦没有大的联系。
其次是住宅自动化(Home Automation)阶段,这个时期是面向功能的阶段,一部分的家庭电器之间形成了简单的网络,主要是为了实现某个特定单一的功能,例如单一的自动抄表功能。
最后是家居智能化(欧洲称为Smart Home,美国称为 Wise House)阶段,这个时期是面向系统设计的阶段,系统通过家庭分布总线把住宅内各种与信息相关的通信设备、家用电器、报警装置并到网络节点中进行集中的监控、管理,保持家电与环境的协调,提供生活、工作、学习以及娱乐的各种优质服务,营造一种温馨舒适的家庭氛围。
智能家居控制系统提供高效、舒适的家居环境,确保住户的生命财产安全;集中或远程监控家居环境的温度、湿度以及风速等,空气中成分也可检验,为空气质量的提高提供依据;电视机、CD等娱乐设施也不再需要人们近距离调节;周围环境以及太阳光的强弱变化都可以合理利用,使能耗降低,资源合理利用,保护环境;提供现代化的通信、信息服务[12]。
在智能家居系统研发中,美国和欧洲一些发达国家一直处于领先地位。近年来,一大批国外知名企业先后挤身于智能家居的研发中尤其以美国微软公司及摩托罗拉公司等为首[12]。摩托罗拉公司开发的“居所之门”、IBM公司开发的“家庭主任”、微软公司开发的“梦幻之家”等均已日趋成熟[12]。在亚洲,日本韩国新等一些经济发达国家的主要企业也进军智能化家居系统的开发,对家居市场更是跃跃欲试。
经过哥本哈根会议,我国更加明确了节能减排,绿色建筑的目标,这就使住宅智能化凸显出了其合理规划,最大限度的节约能源的优势。如果我国大力推广绿色建筑,仅在铺设智能化系统上所需的新设备的生产上就有2000亿到3000亿人民币的新市场。而中国“智能家居网络”必在“智能化住宅”的框架下形成一个新型IT产业,而这一切必将对未来几十年我国房地产的健康有效发
展起着深远的影响。
由于智能家居系统还缺乏统一明确的国际标准,许多公司开发出的产品都是基于自己组的网络和信息交换协议,很多产品是针对特定的组网环境开发的,部分核心技术没有对外公布,技术复杂,直接导致了使用范围的局限性。再者,缺乏对应的第三方产品,各个接入设备之间不能兼容、互操作性差、不利于产品的扩充,因而进一步局限了产品的发展。再加上,有的系统成本过高,严重影响了产品的普及。因此设计一个符合国家国情和规范的集远程控制和本地控制为一体的智能家居控制系统是非常具有现实意义的,且势在必行。
作为智能家居的核心系统的智能家居的控制系统,它的设计功能的完善必将推动住宅智能化的发展。而系统功能的集成化、用户使用的傻瓜化以及市场的平民化将是智能家居控制器的发展趋势,系统也将逐步迈向绿色化。最终,我想全人类的梦想是智能家居控制系统将囊括所有的家事杂物,让我们真正的享受舒适温馨的家庭生活。
二、系统需求分析及方案
物联网智能家居要将各成体系、互不相连的子系统协调起来,就必须有一个兼容性强的中央家居处理平台,接受并处理控制设施发出的信息,然后传送信号给你希望控制的家电或者其他家居子系统。
(一)应用程序功能需求分析
本设计采用模块化设计,整个系统由通信模块、视频采集模块、传感器模块、Lcd模块组成。cortexA8通过对传感器模块传送来的信息进行判断,如果信息异常,则利用蜂鸣器以及LED实现报警,并通过GSM模块向用户发送报警信息。同时用户也可以根据需要,发送短信给GSM模块来控制相应的家电。实现对现场图像实时监控及工作位置实时控制。
(二)开发环境需求分析
1、 硬件环境
(1) 硬件配置原则
具有可靠性,可用性和安全性,在满足软件需求的条件下,具有完善的技术支持,能够满足个人学习和设计需要。
(2) 运行本软件所需的硬件资源
CPU: 800M及以上;内存容量: 内存达128M以上。
本系统采用cortexA8为中央处理平台。
2、 软件环境
(1) 系统软件配置规则
能够在指定的运行环境下,满足该软件的可靠性、安全性和可用性的要求。
(2) 系统软件的配置方案
配置有持续工作能力、高稳定性、高度可集成的开放式标准的操作系统,如Windows NT 、Windows2000、UNIX,Linux等。熟悉C++高级程序设计语言。
本系统采用Linux为操作系统。
三、硬件模块及其驱动设计实现
(一) 主控模块
本系统采用cortexA8为控制核心,cortexA8不断监测有没有异常信息,当发现异常信息时,则进入相应中断,利用cortexA8通过UART串口向GSM模块发送一系列AT指令并启动GSM模块发送报警短信给用户。再根据用户发送回来的指令打开相应的继电器来控制家用电器,完成现场控制和监测任务。
(二) 通信模块
1、 TC35模块简介
TC35是西门子公司推出的一种完整的无线GSM模块,主要由GSM基带处理器、GSM射频模块、供电模块(ASIC)、闪存、ZIF连接器、天线接口、SIM卡支架七部分组成。它可以快速、安全可靠地实现系统方案中的数据传输、短消息服务(Short Message Service)。模块的工作电压为3.3~4.8V。该模块有AT指令集接口,支持文本和PDU模式的短消息第三组的二类传真等。此外,TC35还拥有多方通话、电话簿功能、漫游检测等功能。TC35具有TALK、IDLE、省电模式三种常用工作模式。通过它的40管脚的ZIF连接器实现指令、数据、语音信号、控制信号的双向传输以及电源连接。TC35的核心是基带处理器,主要处理GSM终端内的语音、数据信号,蜂窝射频设备中所有的模拟和数字功能它也拥有。可支持EFR、FR和语音编码而不需要额外硬件电路。
2、 TC35模块与cortexA8连接方式
TC35模块主要通过串口与cortexA8进行连接,从而cortexA8实现对TC35模块的控制。考虑到系统设计接口的简单性并且与cortexA8的UART进行连接,所以只采用TC35的串口提供了的两线(TXD、RXD)控制线连接。系统采用软件
对TC35模块通信模块进行控制非常灵活,过多硬件信号的检测也很好地避免了。对于TC35的其它管脚在不使用的时候,如果该管脚为输出时,一般将该管脚悬空;如果该管脚为输入管脚,则需要将该管脚通过10Ω的电阻上拉。另外需要将IGT管脚上拉因为IGT管脚是控制TC35模块工作的管脚。并且cortexA8与该管脚进行连接,因此我们可以利用cortexA8来控制TC35模块的工作模式。由于TC35模块功能健全,TC35模块的电源管脚是并连在一起的,因此这里不需要做任何的射频处理和信号处理。此外,IGT管脚是TC35模快的启动脚,与cortexA8的ALE管脚相连接。系统加电后为使TC35i进入工作状态,必须在ALE管脚加一个大于100ms的低脉冲,电平下降持续时间不可超过1ms。以下为TC35模块的接口设计。
3、传感器模块
linux2.6内核的设备驱动模型中关心总线、设备和驱动这三个实体,总线将设备和驱动绑定。SOC系统中集成的独立的外设控制器、挂接在soc内存空间的外设不依附于PCI、USB、I2C、SPI等。基于这个背景linux发明了一种虚拟的总线,称为platform总线,相应的设备platform_device,而驱动称为platform_driver。
(1)
led
图3.1 led电路
采用platform框架 自动获取设备号,生成设备节点。
led驱动:
struct file_operations fops = {
}; .read = led_read, .ioctl = led_ioctl, .release = led_release, .open = led_open, .write = led_write,
static int led_probe(struct platform_device *devices)
{
struct resource *r; int ret; dev_t dev = MKDEV(led_major, led_minor); if(led_major) { } else { } if(ret) return ret; ret = alloc_chrdev_region(&dev, led_minor, count, devname); led_major = MAJOR(dev); ret = register_chrdev_region(dev, count, devname); cdev_init(&cdev, &fops); ret=cdev_add(&cdev, dev, 1); if(ret) goto out_unreg_chrdev; atomic_set(&num, 0); myclass = class_create(THIS_MODULE, devname);
goto out_cdevdel; device_create(myclass, NULL, dev, NULL, "%s""%d", devname, led_minor);
r = platform_get_resource(devices, IORESOURCE_MEM, 1); if (r == NULL) { } GPG3_DAT=r->start; return 0; goto out_class_destroy; r = platform_get_resource(devices, IORESOURCE_MEM, 0); if (r == NULL) { } GPG3_CON=r->start; goto out_class_destroy;
out_class_destroy:
device_destroy(myclass, dev); class_destroy(myclass);
out_cdevdel:
cdev_del(&cdev);
out_unreg_chrdev:
}
int led_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
unregister_chrdev_region(dev, count); return -EINVAL;
int tmp; if(cmd==CMDINIT) { } else { } return 0; if(atomic_sub_and_test(1,&num)) { } atomic_inc(&num); return 0; gpg3con = ioremap(GPG3_CON, 4); if(NULL == gpg3con) return -ENOMEM; gpg3dat = ioremap(GPG3_DAT, 4); if(NULL == gpg3dat) return -ENOMEM; tmp=ioread32(gpg3con); tmp=tmp&(~0xffff); iowrite32(0x1111|tmp, gpg3con); tmp=ioread32(gpg3dat); tmp=tmp&(~0xf); iowrite32(0x0|tmp, gpg3dat); m=cmd & 0xf; tmp=ioread32(gpg3dat); tmp=tmp&(~0xf); iowrite32(m, gpg3dat);
led应用程序设计
void led_init(void);
函数功能:打开led设备并
int led_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
函数功能:LED报警 输入参数:cmd 参数表示那个灯亮
void led_exit(void);
函数功能:关闭led设备
(2) 蜂鸣器
图3.2 pwm电路图
采用platform框架 自动获取设备号,生成设备节点。由于这个蜂鸣器是无源的,所以要想使其产生声音必须给他提供一个有一定频率的高低电平。所以这里我们采用S5PC100的PWM定时器来使蜂鸣器发出声音。
static int pwm_probe(struct platform_device *devices)
{
int ret; dev_t dev = MKDEV(pwm_major, pwm_minor); if(pwm_major) { } else { } if(ret) return ret; ret = alloc_chrdev_region(&dev, pwm_minor, count, devname); pwm_major = MAJOR(dev); ret = register_chrdev_region(dev, count, devname); cdev_init(&cdev, &fops); ret=cdev_add(&cdev, dev, 1); if(ret) goto out_unreg_chrdev; atomic_set(&num, 0); myclass = class_create(THIS_MODULE, devname); if (IS_ERR(myclass)) goto out_cdevdel; device_create(myclass, NULL, dev, NULL, "%s""%d", devname, pwm_minor);
r = platform_get_resource(devices, IORESOURCE_MEM, 0); if (r == NULL) { } GPD_CON1=r->start; goto out_class_destroy;
r = platform_get_resource(devices, IORESOURCE_MEM, 1); if (r == NULL) {
goto out_class_destroy;
}
TCFG0=r->start;
r = platform_get_resource(devices, IORESOURCE_MEM, 2); if (r == NULL) {
goto out_class_destroy;
}
TCFG1=r->start;
r = platform_get_resource(devices, IORESOURCE_MEM, 3); if (r == NULL) {
goto out_class_destroy;
}
TCNTB1=r->start;
r = platform_get_resource(devices, IORESOURCE_MEM, 4); if (r == NULL) {
goto out_class_destroy;
}
TCMPB1=r->start;
r = platform_get_resource(devices, IORESOURCE_MEM, 5); if (r == NULL) {
goto out_class_destroy;
}
TCON=r->start;
return 0;
out_class_destroy:
device_destroy(myclass, dev);
class_destroy(myclass);
out_cdevdel:
cdev_del(&cdev);
out_unreg_chrdev:
}
int pwm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
unregister_chrdev_region(dev, count); return -EINVAL; int tmp; if(cmd==CMDINIT) { if(atomic_sub_and_test(1,&num)) { gpdcon1 = ioremap(GPD_CON1, 4); if(NULL == gpdcon1) return -ENOMEM; tcfg0 = ioremap(TCFG0, 4); if(NULL == tcfg0) return -ENOMEM; tcfg1 = ioremap(TCFG1, 4); if(NULL == tcfg1) return -ENOMEM; tcntb1 = ioremap(TCNTB1, 4); if(NULL == tcntb1) return -ENOMEM; tcmpb1 = ioremap(TCMPB1, 4); if(NULL == tcmpb1) return -ENOMEM;
} } gtcon = ioremap(TCON, 4); if(NULL == gtcon) return -ENOMEM; tmp=ioread32(gpdcon1); tmp=tmp&(~0xf
} } iowrite32(tmp, gtcon); else if(cmd==CMDSTOP) { } return 0; tmp=ioread32(gtcon); tmp=tmp&(~(0x0f
蜂鸣器应用程序设计:
int beep_init(void);
函数功能:打开蜂鸣器设备文件
void beep_exit(void);
函数功能:关闭蜂鸣器设备文件
void beep_on(int num);
函数功能:在出现火灾时蜂鸣器报警 输入参数:int num 表示报警的次数
void beep_off(void);
函数功能:停止蜂鸣器响
(3)lm75温度传感器
I2C驱动三种方式:用户层驱动、sysfs接口驱动、字符设备接口驱动(项目采用方案)。
图3.3 lm75电路图
驱动程序设计:
static struct file_operations lm75_fops = {
};
static int lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
data = kzalloc(sizeof(struct lm75_data), GFP_KERNEL); if (!data) return -ENOMEM; int status; u8 set_mask, clr_mask; int new; my_client=client; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) .owner .read .open = THIS_MODULE, = lm75_read, = lm75_open, .release = lm75_release, return -EIO;
i2c_set_clientdata(client, data); mutex_init(&data->update_lock); set_mask = 0; clr_mask = (1 orig_conf = status; new = status & ~clr_mask; new |= set_mask; if (status != new) lm75_write_value(client, LM75_REG_CONF, new); dev_dbg(&client->dev, "Can't read config? %d\n", status); goto exit_free; dev_dbg(&client->dev, "Config %02x\n", new); devn = MKDEV(lm75_major, lm75_minor); if(lm75_major) { } else { } if(status) return status; status = alloc_chrdev_region(&devn, lm75_minor, count, devname); lm75_major = MAJOR(devn); status = register_chrdev_region(devn, count, devname); cdev_init(&cdev, &lm75_fops);
if(status) goto out_unreg_chrdev; myclass = class_create(THIS_MODULE, devname); if (IS_ERR(myclass)) goto out_cdevdel; device_create(myclass, NULL, devn, NULL, "%s""%d", devname, lm75_minor);
goto out;
out_cdevdel:
cdev_del(&cdev);
out_unreg_chrdev:
unregister_chrdev_region(devn, count);
exit_free:
kfree(data);
out:
}
static int lm75_read_value(struct i2c_client *client, u8 reg) {
}
static int lm75_write_value(struct i2c_client *client, u8 reg, u16 return status; int value; if (reg == LM75_REG_CONF) return i2c_smbus_read_byte_data(client, reg); value = i2c_smbus_read_word_data(client, reg); return (value
value)
{
}
static int __init sensors_lm75_init(void)
{
}
static void __exit sensors_lm75_exit(void)
{
}
由于lm75读出的是TEMP寄存器(16位)的值但是lm75TEMP寄存器是高9位有效,精度是0.5。在驱动中不宜使用浮点数运算,所以读出的值在应用层转换。
read (fd,buf,sizeof(buf));
函数功能:从buf中读取温度值
fd = open ("/dev/lm750",O_RDWR);
read (fd,buf,sizeof(buf));
m=atoi(buf);
n=m&0xff80;
if(n&0x8000)
{
n=n>>7;
if (reg == LM75_REG_CONF) return i2c_smbus_write_byte_data(client, reg, value); else return i2c_smbus_write_word_data(client, reg, swab16(value)); return i2c_add_driver(&lm75_driver); i2c_del_driver(&lm75_driver);
n=n-1;
n=~n;
n=n&0xfe;
n=-n;
}
else
{
n=n>>7;
}
tmp=n*0.5;
(4)视屏模块
图3.4 V4L2流程
V4L2采用流水线的方式,操作更简单直观,基本遵循打开视频设备、设置格式、处理数据、关闭设备,更多的具体操作通过ioctl函数来实现。
打开视频设备
在Linux中,设备被看做一个文件。使用open函数打开视频设备。 打开设备有两种方式:
1、用非阻塞模式打开
int Fd;
Fd = open("/dev/video2", O_RDWR | O_NONBLOCK, 0);
2用阻塞模式打开:
Fd = open("/dev/video2", O_RDWR, 0);
应用程序能够使用阻塞模式或非阻塞模式打开视频设备,如果使用非阻塞模式调用视频设备,即使尚未捕获到信息,驱动依旧会把缓存(DQBUFF)里的东西返回给应用程序。
设定属性及采集方式
打开视频设备后,可以设置该视频设备的属性,例如裁剪、缩放等。这一步是可选的。在Linux编程中,一般使用ioctl函数来对设备的I/O通道进行管理:
int ioctl (int __fd, unsigned long int __request, .../*args*/) ; 在进行V4L2开发中,常用的命令标志符如下(some are optional): VIDIOC_REQBUFS: 分配内存
VIDIOC_QUERYBUF:把VIDIOC_REQBUFS中分配的数据缓存转换成物理地址 VIDIOC_QUERYCAP:查询驱动功能
VIDIOC_ENUM_FMT:得到视频设备支持的视频格式
VIDIOC_S_FMT: 设置视频设备的频捕获格式
VIDIOC_G_FMT: 得到视频设备的频捕获格式
VIDIOC_TRY_FMT: 视频设备支持的显示格式
VIDIOC_QBUF: 从缓存中读取数据
VIDIOC_DQBUF: 数据重新进入缓存队列
VIDIOC_STREAMON:开始视频获取
VIDIOC_STREAMOFF:结束视频获取
VIDIOC_QUERYSTD:检查当前视频设备支持的标准,例如PAL或NTSC。
在亚洲,一般使用PAL(720X576)制式的摄像头,而欧洲一般使用NTSC(720X480),使用VIDIOC_QUERYSTD来检测:
v4l2_std_id std;
do {
ret = ioctl(fd, VIDIOC_QUERYSTD, &std);
} while (ret == -1 && errno == EAGAIN);
switch (std) {
case V4L2_STD_NTSC:
//„„
case V4L2_STD_PAL:
//„„
}
设置视频捕获格式
当检测完视频设备支持的标准后,还需要设定视频捕获格式,结构如下: struct v4l2_format fmmt;
memset ( & fmmt, 0, sizeof(fmmt) );
fmmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmmt.fmt.pix.width = 720;
fmmt.fmt.pix.height = 576;
fmmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
fmmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
if (ioctl(Fd, VIDIOC_S_FMT, & fmmt) == -1) {
return -1;
}
v4l2_format结构定义:
struct v4l2_format
{
enum v4l2_buf_type type;
union
{
struct v4l2_pix_format pix;
struct v4l2_window win;
struct v4l2_vbi_format vbi;
__u8 raw_data[200];
} fmt;
};
struct v4l2_pix_format
{
__u32 width;
__u32 height;
__u32 pixelformat;
enum v4l2_field field;
__u32 bytesperline;
__u32 sizeimage;
enum v4l2_colorspace colorspace;
__u32 priv;
};
分配内存
然后为从摄像头捕获的图像分配内存:
struct v4l2_requestbuffers req;
if (ioctl(Fd, VIDIOC_REQBUFS, &req) == -1) {
return -1;
}
v4l2_requestbuffers结定义:
struct v4l2_requestbuffers
{
__u32 count;
enum v4l2_buf_type type;
enum v4l2_memory memory;
__u32 reserved[2];
};
得到视频缓存的内存空间
使用VIDIOC_REQBUFS命令,来得到count个缓存,然后通过使用VIDIOC_QUERYBUF命令来得到分配的缓存的地址,再用mmap函数把地址映射为应用程序中的绝对地址,最后把得到的缓存放入缓存队列以便循环利用。
typedef struct VideoBuffer {
void *start;
size_t length;
} VideoBuffer;
VideoBuffer* buffers = calloc( req.count, sizeof(*buffers) ); struct v4l2_buffer buf;
for (numBufs = 0; numBufs
memset( &buf, 0, sizeof(buf) );
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = numBufs;
if (ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) {
return -1;
}
buffers[numBufs].length = buf.length;
// 转换成相对地址
buffers[numBufs].start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE,
MAP_SHARED,fd, buf.m.offset);
if (buffers[numBufs].start == MAP_FAILED) {
return -1;
}
if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) {
return -1;
}
}
视频采集方式
操作系统一般把系统使用的内存划分成用户空间和内核空间,分别由应用程序管理和操作系统管理。应用程序可以直接访问内存的地址,而内核空间存放的是供内核访问的代码和数据,用户不能直接访问。最开始用户不能直接访问v4l2获取的视频数据因为该段数据是属于内核空间,必须进行地址转换。
获取视频有三种方式:内存映射、用户指针模式和read、write方式。 使用read、write方式,内核空间和用户空间不能进行数据的交换,而且浪费大量用户的内存空间,效率低。
内存映射模式:应用程序不能直接使用设备里的物理地址映因此必须通过映射即mmap函数达到这种效果。
用户指针模式:应用程序自己分配内存空间。这一步需要在v4l2_requestbuffers里将memory字段设置成V4L2_MEMORY_USERPTR。 处理采集数据
V4L2提供了数据缓存队列。数据缓存采用先进先出的方式,当应用程序获取缓存数据时,缓存队列将队列头的视频数据送出,并重新采集一张视频数据放入队列末。从队列中读数据与重新放入队列需要用到两个ioctl命令,VIDIOC_DQBUF和VIDIOC_QBUF。
struct v4l2_buffer buff;
memset(&buf,0,sizeof(buff));
buf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory=V4L2_MEMORY_MMAP;
buf.index=0;
//读取缓存
if (ioctl(Fd, VIDIOC_DQBUF, & buff) == -1)
{
return -1;
}
//重新放入缓存队列
if (ioctl(Fd, VIDIOC_QBUF, & buff) == -1) {
return -1;
}
关闭视频设备
使用close函数关闭一个视频设备
close(cameraFd)
如果使用mmap,最后还需要使用munmap方法。
视频格式的转换
由于采集到的视频格式是YUYV 422格式的,因此需要转换成RGB格式或者JPEG格式才能进行输出显示。
YUYV----RGB
#define YCbCrtoR(Y,Cb,Cr) (1000000*Y + 1370705*(Cr-128))/1000000
#define YCbCrtoG(Y,Cb,Cr) (1000000*Y - 337633*(Cb-128) - 698001*(Cr-128))/1000000
#define YCbCrtoB(Y,Cb,Cr) (1000000*Y + 1732446*(Cb-128))/1000000
typedef unsigned long u32;
typedef unsigned short u16;
typedef unsigned char u8;
u32 Conv_YCbCr_Rgb(u8 y0, u8 y1, u8 cb0, u8 cr0)
{
int r0, g0, b0, r1, g1, b1; u16 rgb0, rgb1; u32 rgb; r0 = YCbCrtoR(y0, cb0, cr0);
g0 = YCbCrtoG(y0, cb0, cr0);
b0 = YCbCrtoB(y0, cb0, cr0);
r1 = YCbCrtoR(y1, cb0, cr0);
g1 = YCbCrtoG(y1, cb0, cr0);
b1 = YCbCrtoB(y1, cb0, cr0);
if (r0 > 255) r0 = 255;
if (r0
if (g0 > 255) g0 = 255;
if (g0
if (b0 > 255) b0 = 255;
if (b0
if (r1 > 255) r1 = 255;
if (r1
if (g1 > 255) g1 = 255;
if (g1
if (b1 > 255) b1 = 255;
if (b1
rgb0 = (((u16)r0>>3)>2)>3)>3)>2)>3)
rgb = (rgb1
return(rgb);
}
YUYV----JPEG:
#define OUTPUT_BUF_SIZE 4096
#define CLEAR(x) memset (&(x), 0, sizeof (x))
#define WIDTH 640
#define HEIGHT 480
struct buffer {
void *start;
}; typedef struct {
struct jpeg_destination_mgr pub; JOCTET * buffer; unsigned char *outbuffer; int outbuffer_size; unsigned char *outbuffer_cursor; int *written;
} mjpg_destination_mgr;
typedef mjpg_destination_mgr *mjpg_dest_ptr;
static char * dev_name = "/dev/video0";
static int fd = -1;
struct buffer * buffers = NULL;
static unsigned int n_buffers = 0;
FILE *file_fd;
static unsigned long file_length;
static unsigned char *file_name;
METHODDEF(void) init_destination(j_compress_ptr cinfo) {
mjpg_dest_ptr dest = (mjpg_dest_ptr) cinfo->dest; dest->buffer = (JOCTET *) (*cinfo->mem->alloc_small)((j_common_ptr) cinfo,
}
METHODDEF(boolean) empty_output_buffer(j_compress_ptr cinfo) {
JPOOL_IMAGE, OUTPUT_BUF_SIZE * sizeof(JOCTET)); *(dest->written) = 0; dest->pub.next_output_byte = dest->buffer; dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; mjpg_dest_ptr dest = (mjpg_dest_ptr) cinfo->dest;
} dest->outbuffer_cursor += OUTPUT_BUF_SIZE; *(dest->written) += OUTPUT_BUF_SIZE; dest->pub.next_output_byte = dest->buffer; dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; return TRUE;
METHODDEF(void) term_destination(j_compress_ptr cinfo) {
}
void dest_buffer(j_compress_ptr cinfo, unsigned char *buffer, int size,int *written) {
mjpg_dest_ptr dest; if (cinfo->dest == NULL) { cinfo->dest = (struct jpeg_destination_mgr *) mjpg_dest_ptr dest = (mjpg_dest_ptr) cinfo->dest; size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; memcpy(dest->outbuffer_cursor, dest->buffer, datacount); dest->outbuffer_cursor += datacount; *(dest->written) += datacount; (*cinfo->mem->alloc_small)(
} (j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(mjpg_destination_mgr)); dest = (mjpg_dest_ptr) cinfo->dest; dest->pub.init_destination = init_destination; dest->pub.empty_output_buffer = empty_output_buffer; dest->pub.term_destination = term_destination; dest->outbuffer = buffer; dest->outbuffer_size = size;
} dest->written = written;
摄像头采集的YUYV格式转换为JPEG格式:buf为设备获取的原始数据首地址,buffer为压缩后的数据首地址。size为像素值。quality为压缩质量。
int compress_yuyv_to_jpeg(unsigned char *buf, unsigned char *buffer, int size,int quality) {
struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPROW row_pointer[1]; unsigned char *line_buffer, *yuyv; int z; static int written; line_buffer = calloc(WIDTH * 3, 1); yuyv = buf; //将YUYV格式的图片数据赋给YUYV指针 printf("compress start...\n"); cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); dest_buffer(&cinfo, buffer, size, &written); cinfo.image_width = WIDTH; cinfo.image_height = HEIGHT; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, quality, TRUE); jpeg_start_compress(&cinfo, TRUE); z = 0; while (cinfo.next_scanline
} } } row_pointer[0] = line_buffer; jpeg_write_scanlines(&cinfo, row_pointer, 1); int r, g, b; int y, u, v; if (!z) y = yuyv[0] > 8; g = (y - (88 * u) - (183 * v)) >> 8; b = (y + (454 * u)) >> 8; *(ptr++) = (r > 255) ? 255 : ((r 255) ? 255 : ((g 255) ? 255 : ((b
lcd模块
本论文是基于嵌入式Linux为基础的包括lcd部分。Linux是一款运行速度
快、开源、高效而且免费的操作系统。近年来,基于开源组织的嵌入式Linux系统的操作系统不断升级更新。Linux操作系统是不属于微内核型的操作系统,但是Linux操作系统模块化的结构可以让用户对它进行合理的剪裁,剪除我们不需要的功能以缩减系统的大小,甚至可以做到几千几百k大小。所以综合考虑系统的性能、可兼容性以及系统的运行速度,本论文采用嵌入式Linux2.6.35版本。
在S5PC100的硬件平台上安装经过剪裁后的Linux操作系统后,为了使LCD能正常显示,还需要在系统中安装相应的LCD的驱动程序。缓存(Framebuffer)技术是Linux内核中的一种常用的驱动程序设计的模式,帧缓存为LCD设备提供了控制器的抽象描述。它就是人们常说的显存,应用程序使用系统实现好的接口可以直接访问LCD底层设备,而不需要知道底层具体是如何实现的。本系统利用帧缓冲技术开发LCD驱动程序。LCD设备使用特殊的设备节点,是一个字符设备,其主设备号是29,次设备号为自己需要的帧缓冲个数。其实,帧缓冲设备和Linux中其它的设备一样。
函数接口
首先将帧缓冲设备的属性封装成结构体FB,如下:
typedef struct fb{
int fbfd ; //文件描述符 //屏幕大小 long int screensize ; struct fb_var_screeninfo vinfo; //屏幕信息 struct fb_fix_screeninfo finfo; unshort *fbp ; //mmap后的用户操作指针
} FB;
将屏幕上的点位置信息封装为结构体POINT,如下:
typedef struct point {
unshort location_wide; unshort location_hight; //此点代表的位置的宽 //此点代表的位置的高
}POINT;
FB *screen_init(FB *fb);
//屏幕初始化函数
int show_picture(FB *fb,int wide,int hight,const unchar *Image); // 图片显示函数
int show_temperature(FB *fb,const char *temperature,unshort color); //动态温度显示函数
int show_state(FB *fb,int flage,unshort color); //温度状态显示函数 int screen_close(FB *fb);
实现函数:
static FB *fb_open(const char *PATH,FB *fb);
----->打开设备函数;
static FB *get_fb_msg(FB *fb);
----->得到屏幕信息;
static FB *fb_mmap(FB *fb);
----->将设备映射到用户空间;
static FB *clean_screen(FB *fb,POINT *start,POINT *end,unshort color);
----->清除start到end之间的块儿装屏幕为color颜色;
static int show_word(FB *fb,const unchar *word,POINT *point,unshort color);
----->在给定的点location显示color颜色的字符;
static int drow_horizontal_line(FB *fb,POINT *start,POINT *end,unshort color);
----->在给定的start到end之间画一条横线
static int drow_vertical_line(FB *fb,POINT *start,POINT *end,unshort color);
----->在给定的start到end之间画一条竖线
static unchar *find_word(const char *str);
----->在0~9(包含小数点)之间找字库中对应的数组
static FB *fb_munmap(FB *fb)
----->解除映射
封装给应用层的函数
FB *screen_init(FB *fb):将打开设备到映射以及显示固定文字以及屏幕 //关闭屏幕函数
划线分割这些 准备工作做好;
int show_picture(FB *fb,int wide,int hight,const unchar *Image): 将确定宽高的图片显示在分割的视频显示区域;
int show_temperature(FB *fb,const char *temperature,unshort color): 将保存温度的字符串显示在固定的温度动态显示区域内。每次显示之前先调用函数static FB *clean_screen(FB *fb,POINT *start,POINT
*end,unshort color)来清除屏幕;
int show_state(FB *fb,int flage,unshort color):
将温度的状态显示在固定的状态显示区域内。采用switch语句通过设置标志位来区别三种状态,每次显示之前先清屏;
int screen_close(FB *fb):
先显示结束图片,再解除映射。从而实现关闭。
四、系统软件部分
(一)主程序及大致流程
本项目实现对现场图像实时监控、利用蜂鸣器以及LED报警和发送短信给用户。大致流程如图4.1:
图4.1 系统流程
1、温度监测线程
打开lm75字符设备
得到温度值 -----------> 传送给LCD显示
判断温度是否异常(报警)
关闭设备
图4.2 温度检测流程
2、视频监测线程
打开视频设备
得到图像缓存
转换格式
传送LCD显示
关闭设备
3、报警流程
传送异常信息
报警方式一:(提醒异常)
打开pwm字符设备
报警鸣响
关闭设备
报警方式二:(查看温度高低)
打开led字符设备
报警(过高:高两位灯亮, 过低:第两位灯亮)
关闭设备
图4.4 系统显示效果
(二)短消息程序设计
在本系统中,cortexA8通过串口0向GSM模块发送相应的AT命令来实现短消息的发送和接收。
1、 AT指令介绍
短消息发送命令:AT+CMGC
该命令被用来发送短消息,它不仅可以发送文本形式的短消息的,也可以发送PDU格式的短消息,它还提供了相应的测试指令以验证发送是否成功。 短消息发送指令格式:
AT+CMGS=?
如果GSM模块响应则为OK。
AT+CMGS=[,]
该命令是用来发送基于文本格式的短消息。如成功发送,则响应为:+CMGS:[,];否则响应为:+CMS ERROR:。
该命令格式中,字段为字符串形式的短信接收者的地址,指系统要发送给指定的手机号码短消息,决定定它是那种类型。当的第一个字符是“+”时,的值转换成整数值是“145”,否则的默认值为“129”.完成该条令前面的值输入再按回车符号结束。然后编写短消息的内容,并在末尾添加字符“Ctrl-Z”,“Ctrl-Z”字符的ASCII码值为“26”。如果不发送,则改为字符“ESC”。如果成功发送信息,系统会返回服务中心的时间戳。如果
发送失败,则返回相应的错误信息。
AT+CMGS=
使用命令格式来发送PDU格式的短消息。如果发送成功,则响应为:+CMGS:[,];如果发送失败,则响应为:+CMS ERROR:。
发送该命令时,首先发送命令AT+CMGC=,并末尾添加回车符,当GSM模块返回“>”字符后再编写PDU的具体内容,在类容末尾添加字符“Ctrl-Z”,该字符的ASCII码值为“26”。如果临时不发送,则用字符“ESC”替换“Ctrl-Z”。如果成功发送,返回系统状态信息,具体可参看响应命令格式。如果发送失败,就返回错误信息。发送PDU格式的短消息时,所有的参数均在PDU数据包里。
短消息删除命令:AT+CMGD (删除SIM卡内存的短消息)
该命令主要用于短消息的删除,众所周知不论是手机的存储量还是SIM卡的存储大小有限,如果短息一直累积下去系统会崩溃。因此有必要过一段时间就删除以前的短消息。该指令的格式有如下两种:
AT+CMGD=?
如果响应为OK。该指令是用来对短信删除进行确认的。
AT+CMGR=INDEX
该命令主要用来删除指定位置的短消息。如果成功删除,则返回为OK,否则返回为:+CMS ERROR:。
短消息阅读命令: AT+CMGR
该命令进行短消息阅读,它具体的格式有如下两种:
AT+CMGR=?
响应为OK。该指令用来短消息的确认。
AT+CMGR=INDEX
该命令用于指定位置的短消息的阅读。如果成功,则返回具体的短消息内容,文本模式和PDU模式两者响应的内容不同。如果操作失败,则返回错误指令格式为:+CMS ERROR:。
设置短信中心命令:AT+CSCA
发送短消息是需要设置短信中心,它具体提供三中指令:
AT+CSCA=?
响应为OK。对短信中心设置的确认。
AT+CSCA?
用来获取短信中心的地址。如果成功操作,则响应为+CSCA:OK。响应中的为短信中心的地址,用来表示为地址类型的标示符。 AT+CSCA=,[]
本系统只需用到以上的一些AT命令,AT指令还有很多可以参看AT命令手册。本系统既可以发送PDU短信也可以发送文本格式的短信。
2、PDU编码规则
PDU模式的短信可以分为3种编码:7-bit、8-bit和 UCS2编码。普通的ASCII字符发送用7-bit编码,发送数据消息用8-bit编码,Unicode字符用UCS2编码发送。PDU编码一般由A B C D E F G H I J K L M十三项构成。 A:短信中心地址长度,十六进制格式数据2位。
B:短信中心号码类型,十六进制格式数据2位。
C:短信中心号码,A中的数据决定B+C的长度。
D:短信内容开始的第一个字节,十六进制格式数据2位。
E:信息类型,十六进制格式数据2位。
F:呼叫短信号码长度,十六进制格式数据2位。
G:呼叫短信类型,十六进制格式数据2位,同B的值一样。
H:呼叫短信号码,F中的数据长度决定该字段长度。
I:协议标识,十六进制格式数据2位。
J:数据编码方案,十六进制格式数据2位。
K:有效期,十六进制格式数据2位。
L:用户数据长度,十六进制格式数据2位。
M:用户数据,其长度由L中的数据决定。
由于本设计发送的是中文信息,所以J中设定采用UCS2编码,这里是中英文的Unicode字符。
3、短信模式设置
GSM模块的短信模式有2种。第1种是:TEXT模式;第2种是:PDU模式。PDU模式可以采用unicode编码发送英文、汉字。本系统采用的是PDU模式。设置如下:
AT+CMFG=1回车
4、短信的发送方法
(1)开始打开串口,然后初始化串口。
(2)通过写指令write向串口写AT指令集。
然后通过读指令read从串口读数据,如果读出出错信息error,则从新发送;如果一直返回ok,则发送成功。
(3)用txt模式发送温度信息,用pdu模式发送相应的中文信息。
(4)关闭串口,成功退出。
五、测试及结论
系统测试是为了增加系统的稳定性和调试程序中的BUG,通过对该系统进行测试后找出了需要改进的地方,修改了人脸识别算法以及整个系统的稳定性有了提高,增加了识别率,提高了视频帧的采集及处理速度,界面设计清晰美观。
(一)测试原则
1、根据该系统的功能需求进行测试。
2、测试需要清晰明了的书写测试文档和输出结果。
3、程序员需要根据测试文档对自己的系统进行改进和说明。
4、在进行对整个系统进行综合的测试时,应当提出合理的测试条件和合理的输入条件,支出该系统需要改进的功能等。
5、测试员要注意测试中的群集现象,测试后程序残存的错误数目与该程序中以发现的错误数量成正比,应该对该系统容易出现的问题进行反复的测试及验证。
6、严格的根据测试要求来执行测试计划,排除测试中的随意性,测试要求应该包括:该系统的功能,输入和输出,测试内容,界面的可控性,系统的稳定性等方面。
7、在测试完系统后需要对每一个测试报告进行全面的检测与核对。
8、对测试报告及测试计划进行归档保管,测试具有出错统计和最终的分析报告,这样为了改进系统,维护系统等方面有了很大的帮助性。
(二)测试方案
本系统主要由Lcd模块、GSM模块以及传感器模块组成。系统中的传感器模块集成在cortexA8上。当整个系统上电后。我设置的是开机就启动本系统。
在Lcd屏上就会自动显示摄像头获取的图像以及当前温度值。系统设置好了温度的上下线值。当用户用一些途径改变温度传感器值只要越过了上下线值,这时Led灯会不断闪烁,系统会自动发送短信到设置的手机号码上。当用户收到cortexA8发送的短信时。可根据短信内容回复相应的信息。cortexA8收到用户的短信后会根据短信进行相应的处理,比如:关闭板子后者启动蜂鸣器。
(三)结论
经过测试得到如下结论。本系统借助于GSM网络通信技术和cortexA8的控制功能,实现了对家电的远程监控和控制。系统充分利用GSM网络覆盖范围的无缝化、广阔化和短消息的业务,使用户可以随时随地的了解住宅情况并实现远程控制。同时GSM模块与中心控制单元可以集成在一起,使整个系统的稳定性提高而成本降低。本系统可用于居民住宅,也可以用于仓库、厂房与蔬菜大棚等地方的远程安监控以及及时的对报警信息进行处理。本系统具有成本低、安全简单、易操作等优点。
参 考 文 献
[1]杨利平.基于网络技术的远程智能家居系统[J].仪器仪表学报,2009(10):19-32.
[2]张俊.SMS 短消息传输的远端控制技术及其实现[J].仪器仪表学报,2003:29-31.
[3]万福君.单片微机原理系统设计与开发[M].合肥:中国科技大学出版社,1995:156-169.
[4]谢自美.电子线路设计[M].武汉:华中科技大学出版社,2000:122-128.
[5]樊昌信.通信原理[M].北京:国防工业出版社,2009.5.
[6]藏春华,邵杰,魏小龙,等.综合电子系统设计与实践[M].北京航空航天大学出版社
2009.
[7]裘岚.C语言程序设计实用教程[M].北京:电子工业出版社,2001.
[8]樊天晴.Internet信息终端技术的研究[M].兰州:西北工业大学,2002.
[9]魏小龙.51系列cortexA8接口技术及系统设计实例[M].北京:北京航空航天大学出版
社, 2002.
[10]王琴放.cortexA8原理及应用[M].北京:电子工业出版社:1997:129-136.
[11]徐顺成.实用电子技术与电子产品汇编[M].北京:电子工业出版社,1993.
[12]刘松,赵忠,孙学磊,等.远程家庭智能监控系统设计[M].北京:高等教育出版
社,2009:98-106.
[13]李群芳.单片微型计算机与接口技术[M].北京:电子工业出版社,2005:152-163.
[14]沙占友.集成化智能传感器原理与应用[M].北京:电子工业出版社.2004.
[15]康华光.电子技术基础[M].北京:高等教育出版社,2006:102-109.
天津电子信息职业技术学院
毕业论文
题目 物联网智能家居系统
姓 名
专业班级
指导教师
完成时间
天津电子信息职业技术学院 制
2017.1
摘 要:随着经济的高速增长。建立一个低成本、高效率的智能家居系统已成为当今世界的一个热点话题。目前越来越多的智能家居产品出现在市场上,其中以基于电话网的智能安防系统居多。目前在我国,使用家庭电话的用户越来越少,而且电话线路受地域的影响严重容易损坏,所以这类产品局限性很大。随着电信GSM网络覆盖范围的无缝化、广阔化以及手机的日益普及为基于GSM网络的智能家居系统提供了巨大的应用空间。
本文设计了一种基于GSM网络的智能家居系统。本系统采用cortexA8为系统控制核心,对家庭中出现的意外情况使用各种传感器进行采集,然后通过GSM模块把采集到的信息发送给管理人员,管理员根据收到的信息发送相关指令给GSM模块来控制现场执行机构,完成意外情况的排除。
关键词:智能家居 GSM 传感器 远程控制
目录
一、 绪论 --------------------------------------------------------- 1
(一) 智能家居概述 -------------------------------------------- 1
(二) 智能家居网络构成 ---------------------------------------- 2
1、家居网络控制平台 ---------------------------------------- 2
2、智能家居子系统 ------------------------------------------ 2
3、智能家居网络的信号传输介质 ------------------------------ 3
4、远程控制技术概括 ---------------------------------------- 4
5、智能家居控制系统的国内外发展现状 ------------------------ 5
二、系统需求分析及方案 -------------------------------------------- 6
(一)应用程序功能需求分析 ------------------------------------- 6
(二)开发环境需求分析 ----------------------------------------- 6
1、 硬件环境 ----------------------------------------------- 6
2、 软件环境 ----------------------------------------------- 7
三、硬件模块及其驱动设计实现 -------------------------------------- 7
(一) 主控模块 ------------------------------------------------ 7
(二) 通信模块 ----------------------------------------------- 7
1、 TC35模块简介 ------------------------------------------- 7
2、 TC35模块与cortexA8连接方式 ---------------------------- 7
3、传感器模块 ---------------------------------------------- 8
四、系统软件部分 ------------------------------------------------- 36
(一)主程序及大致流程 ---------------------------------------- 36
1、温度监测线程 ------------------------------------------- 37
2、视频监测线程 ------------------------------------------- 38
3、报警流程 ----------------------------------------------- 39
(二)短消息程序设计 ------------------------------------------ 40
1、 AT指令介绍 -------------------------------------------- 40
2、PDU编码规则 -------------------------------------------- 42
3、短信模式设置 ------------------------------------------- 42
4、短信的发送方法 ----------------------------------------- 43
五、测试及结论 --------------------------------------------------- 43
(一)测试原则 ------------------------------------------------ 43
(二)测试方案 ------------------------------------------------ 43
(三)结论 ---------------------------------------------------- 44 参 考 文 献 ------------------------------------------------------ 45
一、 绪论
21世纪是信息化的时代,物联网新技术推动了人类文明的进步。随着人们生活水平的提高以及科技的高速发展,智能化家居已成为一种必然趋势而深入千家万户。智能化家居是利用电力自动化、计算机、网络通信、信息、结构化布线、无线等技术将多种设备应用和综合功能组成一个强大的完善的系统。它以住房为平台,同时兼备网络家电、家电设备自动化、建筑、通信、远程医疗、家庭办公、娱乐等功能,集结构、服务、系统、管理为一体的舒适、节能、安全、便利、高效、娱乐、环保的居住环境。
本文介绍的智能化家居控制系统可以使得人们通过手机在任何时候、任意地点对家中的任意电器(例如:热水器、空调、电饭煲、灯光等)进行远程控制。你可以在下班途中,预先将家中的空调打开、电饭煲煮好香喷喷的米饭、让热水器提前烧好热水,而这一切的实现都仅仅是靠一条短信完成。
本系统采用cortexA8作为主控器件,远程控制是基于GSM网络短消息通信方式,AT指令作为系统控制命令,cortexA8通过对收到的信息进行解码来识别控制信号,用户只需向TC35模块发送相应指令即可实现远程控制操作。温度传感器完成现场信息的采集,cortexA8对数据进行及时的处理,实现实时测控;短消息发送部分采用基于GSM模块TC35和IT公司的电平转换芯片MAX232等器件构成的移动终端的硬件电路,完成短消息收发功能。
(一) 智能家居概述
进入21世纪,科学技术与生产力加速了社会的发展创造能力,随之而来的也是人类对于物质水平的大力需求,而居住的环境要求也成为了人们关注的领域,所以“智能化”这一概念也促使科技工作者们将其引入智能家居民应用方面的小区住宅以及小区建筑技术之中。由于计算机控制系统发展迅速,以及电子信息行业的发展成长快速,也大力促进了智能家居控制系统的产生。因为固定电话和互联网技术基本上是传统智能家居控制系统的技术核心,所以安装固定电话以及互联网成为了达到家庭用户传统智能家居控制系统的产生的根本硬件技术、以及硬件要求。但是随着电子技术、智能通信技术以及网络技术发展日新月异的今天,基于GSM网络通讯体统的低成本无限制智能家居控制系统成为广大居民以及中国居民享受新一代智能家居控制系统的变革捷径。
智能家居系统成为一种新兴的综合技术学科。智能家居系统也可被定义为
一个控制过程,或者控制系统,利用现在被大多数科技人员已掌握的计算机技术、网络布线技术、网络通信系统将其糅合,使之成为融合在家居控制中的多个子系统,并使其智能的结合在一起。
目前相比较其他时分多址技术手段而言,更加完美、成熟、应用更广泛的一种普及率很高的系统是GSM(Global System for Mobile communication)系统。在我国,已建成的基本覆盖全国的GSM数字蜂窝移动技术信息网,早已成为我国公众移动生活密不可分的一种技术之一。在GSM短信服务的基础上,智能家居控制系统是在移动网络通讯技术的短信应用功能的技术运用。
由于GSM网络通讯系统在全国范围实现了联网以及漫游能力,所以它的网络功能很强大,用户无需另外搭建网络,因此,在GSM网络覆盖率达到全国范围的情况下,为客户省下了昂贵的网络搭建费用以及维护网络费用。同时,它对用户数量的限制也十分少,也为客户克服了一般智能家居控制系统中系统成本高、维护艰难、并且网络覆盖范围小以及用户组数量少的缺点。相比传统网络智能家居控制系统在网络通信覆盖率上具有较大的优势,加之GSM本身就具有数据的输送功能,这也促成了GSM应用在广大生活中得到迅速普及。基于GSM的无线通讯智能系统还具有双线传送数据的功能、性能稳定。为客户在远程操控以及用户控制设备提供了强大技术平台。
远程操控系统应用广泛,遍及中国经济生活发展的各大领域。而且目前人们正在使用中的操控系统从成本、性能、稳定性、便捷性以及维护的难易方面基本都不能使人们最大程度的满意。所以,GSM网络通信技术的提出大大的提升了智能家居控制系统的完善程度。
(二) 智能家居网络构成
1、家居网络控制平台
智能家居主控制平台是智能家居控制系统的“心脏”部分,等效的可以说是智能家居的核心。对方可以通过手机短信的方式接受用户命令并实时操作,或者对对用户手机发送控制电器运转情况,对家庭总线和各个网络子系统实施连接,完成智能家居控制系统平台的链接构成。
2、智能家居子系统
智能家居系统的连接一般均为家电网络中的耗电类型的家电电器。例如冰箱、空调、电磁炉、热水器、电饭煲、电灯等家用电器。这些消耗电类型的家
庭电器可以在现场立即布线互联构成智能家居系统,与主控家居智能平台相连接,再进行现场网络综合布线连接智能家居子系统,就可以由用户利用协议中的操作指令短信操作家庭中电器设备了。
3、智能家居网络的信号传输介质
智能家居网络通讯形式多彩多样,可以采用不同的传输介质传输网络通讯信号,大体上有电力线、电话线、双绞线、无线方式。
(1) 电力线
基于电力线为传输介质的通信网络可以说是最方便的,因为现在家庭基本都已铺设供电源的电源线而且家中的电源线已经延伸到家庭生活的每个角落。而且,现在大部分家用电器设备都离不开电源。所以利用家中的电力线完成智能家居控制系统网络方案方便而且经济便宜。在国际上,首个实现家庭电器智能化的方案便是通过电力线作为信息传输载体的而达成的。
(2) 电话线
利用电话线作为网络信息传输载体起步虽然相较于电力线稍微晚一些,但是因为它具有布局简单、使用方便、安全性能好和易于大规模推广等优点,而且近期电话线的传输速率也完成了大幅度提升,所以它的应用和发展非常快,在美国已有成熟的产品。其中包括:3COM、Advanced Micro—Devices、AT&T、Compaq、Hewlett.Packard、Intel、IBM和Lucent Technologies等发起成立了“电话线家居网络协会”,至今己有100多个成员。
(3) 双绞线/同轴电缆
目前最通用的传输介质是用双绞线/同轴电缆。可是在基于双绞线/同轴电缆实际操作中最大的困难是需要另外铺设2/4根专用的传输线。但是它拥有通信可靠性和总线接口相对简单等优点,其仍然可以受到广泛用户的大批量应用。
(4) 无线方式
无线方式通过射频载波或者红外线等形式传输用户信息,“蓝牙技术”是最近发展最火热的无线通信方式。音频和视频信号、计算机网络信号、控制信号均可以利用蓝牙技术传输家庭用户信号。而且用无线方式传输信息时无需架设任何线路且实现极其方便灵活,非常适合在家庭网络中应用。
由于无线方式简单方便,易于架设,所以本论文便是使用的GSM无线技术平台操作的智能家居平台系统。
4、远程控制技术概括
本论文研究立于一个对于家居电器进行远程控制,以便于实现家居智能化的系统。远程控制指的是远端的家居控制者通过通信系统对现场的家居电器系统进行控制,其目的在于解除地域和环境对控制的限制,实现高集中的远程控制,最终实现生产资料和社会资源与通讯资源的优化配置。现代远程控制技术是计算机技术、通信技术、网络技术的集合,也是信息技术和控制技术的结合。
从用户角度来讲,需要的是一种方便、安全、可靠的一种传输方式。可以利用公共数据网或者通过架设专线来实现有线传输,然而在大多数情况下,传输距离、架线环境等条件限制了有线传输[2]。无线传输也有很多途径,如架设微波线路、(超)短波电台等都是通过自建的无线发射接收系统。然而无线传输架设成本高、频率资源的限制、容易受到地形地貌的影响、系统的架设和维护工作繁重,在业务量小、用户数量大、位置分散等应用场合中也受到很大限制。目前,经过三代发展的移动通信,移动通信体制中的时分多址技术中最完善、最成熟、应用最广的一种移动通信系统就是GSM系统[2]。在数据采集、远距离监控、GPS定位、缴费通知、无线报警等领域GMS都有着广泛的应用。在全国范围内GSM网络实现了联网和漫游,用户无需另外组网,GMS具有很强的网络能力,网络覆盖范围广阔,用户不必再花费节昂贵的建网费用和维护费用[2]。比传统的集群系统在无线网络覆盖上具有无法比拟的优势,加上GSM的SMS本身具备的数据传送功能,都使得这些应用得到迅速的普及[2]。GSM短信息系统性能稳定还可进行双向数据传输,为监控设备和远程数据传送通信提供了一个可靠、安全的支持平台。
短消息发送一般采用其专用控制信道(DCCH)来发送,短信息的服务端可以实时的了解到对方是否接收到短信息,一旦信息传送失败,短信中心实时得知被叫用户没有回复信息,网络管理端则会继续发送消息,以保证被叫方能收到短信息。所以,在GSM网络的一些主要的电信业务当中,此类短消息业务的信息传递是实时安全的[2]。每个短消息的信息量都是140个八位组(7比特编码,160个字符)不会超过140个字节,绝对可以满足单方面监测用户指标的信息量。综上所述,智能家居控制系统选用GSM的短消息控制方式,来实现智能家居设备的远程控制是可行的。
5、智能家居控制系统的国内外发展现状
目前,我国每年竣工的建筑面积达到20亿平米,智能家居/建筑的产值至少在1-2万亿元以上。
智能家居的发展分为三个阶段:
首先是家庭电子化(Home Electronics)阶段,这个时期主要是面向单个的电器,家庭电器之间并没有形成网络,亦没有大的联系。
其次是住宅自动化(Home Automation)阶段,这个时期是面向功能的阶段,一部分的家庭电器之间形成了简单的网络,主要是为了实现某个特定单一的功能,例如单一的自动抄表功能。
最后是家居智能化(欧洲称为Smart Home,美国称为 Wise House)阶段,这个时期是面向系统设计的阶段,系统通过家庭分布总线把住宅内各种与信息相关的通信设备、家用电器、报警装置并到网络节点中进行集中的监控、管理,保持家电与环境的协调,提供生活、工作、学习以及娱乐的各种优质服务,营造一种温馨舒适的家庭氛围。
智能家居控制系统提供高效、舒适的家居环境,确保住户的生命财产安全;集中或远程监控家居环境的温度、湿度以及风速等,空气中成分也可检验,为空气质量的提高提供依据;电视机、CD等娱乐设施也不再需要人们近距离调节;周围环境以及太阳光的强弱变化都可以合理利用,使能耗降低,资源合理利用,保护环境;提供现代化的通信、信息服务[12]。
在智能家居系统研发中,美国和欧洲一些发达国家一直处于领先地位。近年来,一大批国外知名企业先后挤身于智能家居的研发中尤其以美国微软公司及摩托罗拉公司等为首[12]。摩托罗拉公司开发的“居所之门”、IBM公司开发的“家庭主任”、微软公司开发的“梦幻之家”等均已日趋成熟[12]。在亚洲,日本韩国新等一些经济发达国家的主要企业也进军智能化家居系统的开发,对家居市场更是跃跃欲试。
经过哥本哈根会议,我国更加明确了节能减排,绿色建筑的目标,这就使住宅智能化凸显出了其合理规划,最大限度的节约能源的优势。如果我国大力推广绿色建筑,仅在铺设智能化系统上所需的新设备的生产上就有2000亿到3000亿人民币的新市场。而中国“智能家居网络”必在“智能化住宅”的框架下形成一个新型IT产业,而这一切必将对未来几十年我国房地产的健康有效发
展起着深远的影响。
由于智能家居系统还缺乏统一明确的国际标准,许多公司开发出的产品都是基于自己组的网络和信息交换协议,很多产品是针对特定的组网环境开发的,部分核心技术没有对外公布,技术复杂,直接导致了使用范围的局限性。再者,缺乏对应的第三方产品,各个接入设备之间不能兼容、互操作性差、不利于产品的扩充,因而进一步局限了产品的发展。再加上,有的系统成本过高,严重影响了产品的普及。因此设计一个符合国家国情和规范的集远程控制和本地控制为一体的智能家居控制系统是非常具有现实意义的,且势在必行。
作为智能家居的核心系统的智能家居的控制系统,它的设计功能的完善必将推动住宅智能化的发展。而系统功能的集成化、用户使用的傻瓜化以及市场的平民化将是智能家居控制器的发展趋势,系统也将逐步迈向绿色化。最终,我想全人类的梦想是智能家居控制系统将囊括所有的家事杂物,让我们真正的享受舒适温馨的家庭生活。
二、系统需求分析及方案
物联网智能家居要将各成体系、互不相连的子系统协调起来,就必须有一个兼容性强的中央家居处理平台,接受并处理控制设施发出的信息,然后传送信号给你希望控制的家电或者其他家居子系统。
(一)应用程序功能需求分析
本设计采用模块化设计,整个系统由通信模块、视频采集模块、传感器模块、Lcd模块组成。cortexA8通过对传感器模块传送来的信息进行判断,如果信息异常,则利用蜂鸣器以及LED实现报警,并通过GSM模块向用户发送报警信息。同时用户也可以根据需要,发送短信给GSM模块来控制相应的家电。实现对现场图像实时监控及工作位置实时控制。
(二)开发环境需求分析
1、 硬件环境
(1) 硬件配置原则
具有可靠性,可用性和安全性,在满足软件需求的条件下,具有完善的技术支持,能够满足个人学习和设计需要。
(2) 运行本软件所需的硬件资源
CPU: 800M及以上;内存容量: 内存达128M以上。
本系统采用cortexA8为中央处理平台。
2、 软件环境
(1) 系统软件配置规则
能够在指定的运行环境下,满足该软件的可靠性、安全性和可用性的要求。
(2) 系统软件的配置方案
配置有持续工作能力、高稳定性、高度可集成的开放式标准的操作系统,如Windows NT 、Windows2000、UNIX,Linux等。熟悉C++高级程序设计语言。
本系统采用Linux为操作系统。
三、硬件模块及其驱动设计实现
(一) 主控模块
本系统采用cortexA8为控制核心,cortexA8不断监测有没有异常信息,当发现异常信息时,则进入相应中断,利用cortexA8通过UART串口向GSM模块发送一系列AT指令并启动GSM模块发送报警短信给用户。再根据用户发送回来的指令打开相应的继电器来控制家用电器,完成现场控制和监测任务。
(二) 通信模块
1、 TC35模块简介
TC35是西门子公司推出的一种完整的无线GSM模块,主要由GSM基带处理器、GSM射频模块、供电模块(ASIC)、闪存、ZIF连接器、天线接口、SIM卡支架七部分组成。它可以快速、安全可靠地实现系统方案中的数据传输、短消息服务(Short Message Service)。模块的工作电压为3.3~4.8V。该模块有AT指令集接口,支持文本和PDU模式的短消息第三组的二类传真等。此外,TC35还拥有多方通话、电话簿功能、漫游检测等功能。TC35具有TALK、IDLE、省电模式三种常用工作模式。通过它的40管脚的ZIF连接器实现指令、数据、语音信号、控制信号的双向传输以及电源连接。TC35的核心是基带处理器,主要处理GSM终端内的语音、数据信号,蜂窝射频设备中所有的模拟和数字功能它也拥有。可支持EFR、FR和语音编码而不需要额外硬件电路。
2、 TC35模块与cortexA8连接方式
TC35模块主要通过串口与cortexA8进行连接,从而cortexA8实现对TC35模块的控制。考虑到系统设计接口的简单性并且与cortexA8的UART进行连接,所以只采用TC35的串口提供了的两线(TXD、RXD)控制线连接。系统采用软件
对TC35模块通信模块进行控制非常灵活,过多硬件信号的检测也很好地避免了。对于TC35的其它管脚在不使用的时候,如果该管脚为输出时,一般将该管脚悬空;如果该管脚为输入管脚,则需要将该管脚通过10Ω的电阻上拉。另外需要将IGT管脚上拉因为IGT管脚是控制TC35模块工作的管脚。并且cortexA8与该管脚进行连接,因此我们可以利用cortexA8来控制TC35模块的工作模式。由于TC35模块功能健全,TC35模块的电源管脚是并连在一起的,因此这里不需要做任何的射频处理和信号处理。此外,IGT管脚是TC35模快的启动脚,与cortexA8的ALE管脚相连接。系统加电后为使TC35i进入工作状态,必须在ALE管脚加一个大于100ms的低脉冲,电平下降持续时间不可超过1ms。以下为TC35模块的接口设计。
3、传感器模块
linux2.6内核的设备驱动模型中关心总线、设备和驱动这三个实体,总线将设备和驱动绑定。SOC系统中集成的独立的外设控制器、挂接在soc内存空间的外设不依附于PCI、USB、I2C、SPI等。基于这个背景linux发明了一种虚拟的总线,称为platform总线,相应的设备platform_device,而驱动称为platform_driver。
(1)
led
图3.1 led电路
采用platform框架 自动获取设备号,生成设备节点。
led驱动:
struct file_operations fops = {
}; .read = led_read, .ioctl = led_ioctl, .release = led_release, .open = led_open, .write = led_write,
static int led_probe(struct platform_device *devices)
{
struct resource *r; int ret; dev_t dev = MKDEV(led_major, led_minor); if(led_major) { } else { } if(ret) return ret; ret = alloc_chrdev_region(&dev, led_minor, count, devname); led_major = MAJOR(dev); ret = register_chrdev_region(dev, count, devname); cdev_init(&cdev, &fops); ret=cdev_add(&cdev, dev, 1); if(ret) goto out_unreg_chrdev; atomic_set(&num, 0); myclass = class_create(THIS_MODULE, devname);
goto out_cdevdel; device_create(myclass, NULL, dev, NULL, "%s""%d", devname, led_minor);
r = platform_get_resource(devices, IORESOURCE_MEM, 1); if (r == NULL) { } GPG3_DAT=r->start; return 0; goto out_class_destroy; r = platform_get_resource(devices, IORESOURCE_MEM, 0); if (r == NULL) { } GPG3_CON=r->start; goto out_class_destroy;
out_class_destroy:
device_destroy(myclass, dev); class_destroy(myclass);
out_cdevdel:
cdev_del(&cdev);
out_unreg_chrdev:
}
int led_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
unregister_chrdev_region(dev, count); return -EINVAL;
int tmp; if(cmd==CMDINIT) { } else { } return 0; if(atomic_sub_and_test(1,&num)) { } atomic_inc(&num); return 0; gpg3con = ioremap(GPG3_CON, 4); if(NULL == gpg3con) return -ENOMEM; gpg3dat = ioremap(GPG3_DAT, 4); if(NULL == gpg3dat) return -ENOMEM; tmp=ioread32(gpg3con); tmp=tmp&(~0xffff); iowrite32(0x1111|tmp, gpg3con); tmp=ioread32(gpg3dat); tmp=tmp&(~0xf); iowrite32(0x0|tmp, gpg3dat); m=cmd & 0xf; tmp=ioread32(gpg3dat); tmp=tmp&(~0xf); iowrite32(m, gpg3dat);
led应用程序设计
void led_init(void);
函数功能:打开led设备并
int led_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
函数功能:LED报警 输入参数:cmd 参数表示那个灯亮
void led_exit(void);
函数功能:关闭led设备
(2) 蜂鸣器
图3.2 pwm电路图
采用platform框架 自动获取设备号,生成设备节点。由于这个蜂鸣器是无源的,所以要想使其产生声音必须给他提供一个有一定频率的高低电平。所以这里我们采用S5PC100的PWM定时器来使蜂鸣器发出声音。
static int pwm_probe(struct platform_device *devices)
{
int ret; dev_t dev = MKDEV(pwm_major, pwm_minor); if(pwm_major) { } else { } if(ret) return ret; ret = alloc_chrdev_region(&dev, pwm_minor, count, devname); pwm_major = MAJOR(dev); ret = register_chrdev_region(dev, count, devname); cdev_init(&cdev, &fops); ret=cdev_add(&cdev, dev, 1); if(ret) goto out_unreg_chrdev; atomic_set(&num, 0); myclass = class_create(THIS_MODULE, devname); if (IS_ERR(myclass)) goto out_cdevdel; device_create(myclass, NULL, dev, NULL, "%s""%d", devname, pwm_minor);
r = platform_get_resource(devices, IORESOURCE_MEM, 0); if (r == NULL) { } GPD_CON1=r->start; goto out_class_destroy;
r = platform_get_resource(devices, IORESOURCE_MEM, 1); if (r == NULL) {
goto out_class_destroy;
}
TCFG0=r->start;
r = platform_get_resource(devices, IORESOURCE_MEM, 2); if (r == NULL) {
goto out_class_destroy;
}
TCFG1=r->start;
r = platform_get_resource(devices, IORESOURCE_MEM, 3); if (r == NULL) {
goto out_class_destroy;
}
TCNTB1=r->start;
r = platform_get_resource(devices, IORESOURCE_MEM, 4); if (r == NULL) {
goto out_class_destroy;
}
TCMPB1=r->start;
r = platform_get_resource(devices, IORESOURCE_MEM, 5); if (r == NULL) {
goto out_class_destroy;
}
TCON=r->start;
return 0;
out_class_destroy:
device_destroy(myclass, dev);
class_destroy(myclass);
out_cdevdel:
cdev_del(&cdev);
out_unreg_chrdev:
}
int pwm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
unregister_chrdev_region(dev, count); return -EINVAL; int tmp; if(cmd==CMDINIT) { if(atomic_sub_and_test(1,&num)) { gpdcon1 = ioremap(GPD_CON1, 4); if(NULL == gpdcon1) return -ENOMEM; tcfg0 = ioremap(TCFG0, 4); if(NULL == tcfg0) return -ENOMEM; tcfg1 = ioremap(TCFG1, 4); if(NULL == tcfg1) return -ENOMEM; tcntb1 = ioremap(TCNTB1, 4); if(NULL == tcntb1) return -ENOMEM; tcmpb1 = ioremap(TCMPB1, 4); if(NULL == tcmpb1) return -ENOMEM;
} } gtcon = ioremap(TCON, 4); if(NULL == gtcon) return -ENOMEM; tmp=ioread32(gpdcon1); tmp=tmp&(~0xf
} } iowrite32(tmp, gtcon); else if(cmd==CMDSTOP) { } return 0; tmp=ioread32(gtcon); tmp=tmp&(~(0x0f
蜂鸣器应用程序设计:
int beep_init(void);
函数功能:打开蜂鸣器设备文件
void beep_exit(void);
函数功能:关闭蜂鸣器设备文件
void beep_on(int num);
函数功能:在出现火灾时蜂鸣器报警 输入参数:int num 表示报警的次数
void beep_off(void);
函数功能:停止蜂鸣器响
(3)lm75温度传感器
I2C驱动三种方式:用户层驱动、sysfs接口驱动、字符设备接口驱动(项目采用方案)。
图3.3 lm75电路图
驱动程序设计:
static struct file_operations lm75_fops = {
};
static int lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
data = kzalloc(sizeof(struct lm75_data), GFP_KERNEL); if (!data) return -ENOMEM; int status; u8 set_mask, clr_mask; int new; my_client=client; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) .owner .read .open = THIS_MODULE, = lm75_read, = lm75_open, .release = lm75_release, return -EIO;
i2c_set_clientdata(client, data); mutex_init(&data->update_lock); set_mask = 0; clr_mask = (1 orig_conf = status; new = status & ~clr_mask; new |= set_mask; if (status != new) lm75_write_value(client, LM75_REG_CONF, new); dev_dbg(&client->dev, "Can't read config? %d\n", status); goto exit_free; dev_dbg(&client->dev, "Config %02x\n", new); devn = MKDEV(lm75_major, lm75_minor); if(lm75_major) { } else { } if(status) return status; status = alloc_chrdev_region(&devn, lm75_minor, count, devname); lm75_major = MAJOR(devn); status = register_chrdev_region(devn, count, devname); cdev_init(&cdev, &lm75_fops);
if(status) goto out_unreg_chrdev; myclass = class_create(THIS_MODULE, devname); if (IS_ERR(myclass)) goto out_cdevdel; device_create(myclass, NULL, devn, NULL, "%s""%d", devname, lm75_minor);
goto out;
out_cdevdel:
cdev_del(&cdev);
out_unreg_chrdev:
unregister_chrdev_region(devn, count);
exit_free:
kfree(data);
out:
}
static int lm75_read_value(struct i2c_client *client, u8 reg) {
}
static int lm75_write_value(struct i2c_client *client, u8 reg, u16 return status; int value; if (reg == LM75_REG_CONF) return i2c_smbus_read_byte_data(client, reg); value = i2c_smbus_read_word_data(client, reg); return (value
value)
{
}
static int __init sensors_lm75_init(void)
{
}
static void __exit sensors_lm75_exit(void)
{
}
由于lm75读出的是TEMP寄存器(16位)的值但是lm75TEMP寄存器是高9位有效,精度是0.5。在驱动中不宜使用浮点数运算,所以读出的值在应用层转换。
read (fd,buf,sizeof(buf));
函数功能:从buf中读取温度值
fd = open ("/dev/lm750",O_RDWR);
read (fd,buf,sizeof(buf));
m=atoi(buf);
n=m&0xff80;
if(n&0x8000)
{
n=n>>7;
if (reg == LM75_REG_CONF) return i2c_smbus_write_byte_data(client, reg, value); else return i2c_smbus_write_word_data(client, reg, swab16(value)); return i2c_add_driver(&lm75_driver); i2c_del_driver(&lm75_driver);
n=n-1;
n=~n;
n=n&0xfe;
n=-n;
}
else
{
n=n>>7;
}
tmp=n*0.5;
(4)视屏模块
图3.4 V4L2流程
V4L2采用流水线的方式,操作更简单直观,基本遵循打开视频设备、设置格式、处理数据、关闭设备,更多的具体操作通过ioctl函数来实现。
打开视频设备
在Linux中,设备被看做一个文件。使用open函数打开视频设备。 打开设备有两种方式:
1、用非阻塞模式打开
int Fd;
Fd = open("/dev/video2", O_RDWR | O_NONBLOCK, 0);
2用阻塞模式打开:
Fd = open("/dev/video2", O_RDWR, 0);
应用程序能够使用阻塞模式或非阻塞模式打开视频设备,如果使用非阻塞模式调用视频设备,即使尚未捕获到信息,驱动依旧会把缓存(DQBUFF)里的东西返回给应用程序。
设定属性及采集方式
打开视频设备后,可以设置该视频设备的属性,例如裁剪、缩放等。这一步是可选的。在Linux编程中,一般使用ioctl函数来对设备的I/O通道进行管理:
int ioctl (int __fd, unsigned long int __request, .../*args*/) ; 在进行V4L2开发中,常用的命令标志符如下(some are optional): VIDIOC_REQBUFS: 分配内存
VIDIOC_QUERYBUF:把VIDIOC_REQBUFS中分配的数据缓存转换成物理地址 VIDIOC_QUERYCAP:查询驱动功能
VIDIOC_ENUM_FMT:得到视频设备支持的视频格式
VIDIOC_S_FMT: 设置视频设备的频捕获格式
VIDIOC_G_FMT: 得到视频设备的频捕获格式
VIDIOC_TRY_FMT: 视频设备支持的显示格式
VIDIOC_QBUF: 从缓存中读取数据
VIDIOC_DQBUF: 数据重新进入缓存队列
VIDIOC_STREAMON:开始视频获取
VIDIOC_STREAMOFF:结束视频获取
VIDIOC_QUERYSTD:检查当前视频设备支持的标准,例如PAL或NTSC。
在亚洲,一般使用PAL(720X576)制式的摄像头,而欧洲一般使用NTSC(720X480),使用VIDIOC_QUERYSTD来检测:
v4l2_std_id std;
do {
ret = ioctl(fd, VIDIOC_QUERYSTD, &std);
} while (ret == -1 && errno == EAGAIN);
switch (std) {
case V4L2_STD_NTSC:
//„„
case V4L2_STD_PAL:
//„„
}
设置视频捕获格式
当检测完视频设备支持的标准后,还需要设定视频捕获格式,结构如下: struct v4l2_format fmmt;
memset ( & fmmt, 0, sizeof(fmmt) );
fmmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmmt.fmt.pix.width = 720;
fmmt.fmt.pix.height = 576;
fmmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
fmmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
if (ioctl(Fd, VIDIOC_S_FMT, & fmmt) == -1) {
return -1;
}
v4l2_format结构定义:
struct v4l2_format
{
enum v4l2_buf_type type;
union
{
struct v4l2_pix_format pix;
struct v4l2_window win;
struct v4l2_vbi_format vbi;
__u8 raw_data[200];
} fmt;
};
struct v4l2_pix_format
{
__u32 width;
__u32 height;
__u32 pixelformat;
enum v4l2_field field;
__u32 bytesperline;
__u32 sizeimage;
enum v4l2_colorspace colorspace;
__u32 priv;
};
分配内存
然后为从摄像头捕获的图像分配内存:
struct v4l2_requestbuffers req;
if (ioctl(Fd, VIDIOC_REQBUFS, &req) == -1) {
return -1;
}
v4l2_requestbuffers结定义:
struct v4l2_requestbuffers
{
__u32 count;
enum v4l2_buf_type type;
enum v4l2_memory memory;
__u32 reserved[2];
};
得到视频缓存的内存空间
使用VIDIOC_REQBUFS命令,来得到count个缓存,然后通过使用VIDIOC_QUERYBUF命令来得到分配的缓存的地址,再用mmap函数把地址映射为应用程序中的绝对地址,最后把得到的缓存放入缓存队列以便循环利用。
typedef struct VideoBuffer {
void *start;
size_t length;
} VideoBuffer;
VideoBuffer* buffers = calloc( req.count, sizeof(*buffers) ); struct v4l2_buffer buf;
for (numBufs = 0; numBufs
memset( &buf, 0, sizeof(buf) );
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = numBufs;
if (ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) {
return -1;
}
buffers[numBufs].length = buf.length;
// 转换成相对地址
buffers[numBufs].start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE,
MAP_SHARED,fd, buf.m.offset);
if (buffers[numBufs].start == MAP_FAILED) {
return -1;
}
if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) {
return -1;
}
}
视频采集方式
操作系统一般把系统使用的内存划分成用户空间和内核空间,分别由应用程序管理和操作系统管理。应用程序可以直接访问内存的地址,而内核空间存放的是供内核访问的代码和数据,用户不能直接访问。最开始用户不能直接访问v4l2获取的视频数据因为该段数据是属于内核空间,必须进行地址转换。
获取视频有三种方式:内存映射、用户指针模式和read、write方式。 使用read、write方式,内核空间和用户空间不能进行数据的交换,而且浪费大量用户的内存空间,效率低。
内存映射模式:应用程序不能直接使用设备里的物理地址映因此必须通过映射即mmap函数达到这种效果。
用户指针模式:应用程序自己分配内存空间。这一步需要在v4l2_requestbuffers里将memory字段设置成V4L2_MEMORY_USERPTR。 处理采集数据
V4L2提供了数据缓存队列。数据缓存采用先进先出的方式,当应用程序获取缓存数据时,缓存队列将队列头的视频数据送出,并重新采集一张视频数据放入队列末。从队列中读数据与重新放入队列需要用到两个ioctl命令,VIDIOC_DQBUF和VIDIOC_QBUF。
struct v4l2_buffer buff;
memset(&buf,0,sizeof(buff));
buf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory=V4L2_MEMORY_MMAP;
buf.index=0;
//读取缓存
if (ioctl(Fd, VIDIOC_DQBUF, & buff) == -1)
{
return -1;
}
//重新放入缓存队列
if (ioctl(Fd, VIDIOC_QBUF, & buff) == -1) {
return -1;
}
关闭视频设备
使用close函数关闭一个视频设备
close(cameraFd)
如果使用mmap,最后还需要使用munmap方法。
视频格式的转换
由于采集到的视频格式是YUYV 422格式的,因此需要转换成RGB格式或者JPEG格式才能进行输出显示。
YUYV----RGB
#define YCbCrtoR(Y,Cb,Cr) (1000000*Y + 1370705*(Cr-128))/1000000
#define YCbCrtoG(Y,Cb,Cr) (1000000*Y - 337633*(Cb-128) - 698001*(Cr-128))/1000000
#define YCbCrtoB(Y,Cb,Cr) (1000000*Y + 1732446*(Cb-128))/1000000
typedef unsigned long u32;
typedef unsigned short u16;
typedef unsigned char u8;
u32 Conv_YCbCr_Rgb(u8 y0, u8 y1, u8 cb0, u8 cr0)
{
int r0, g0, b0, r1, g1, b1; u16 rgb0, rgb1; u32 rgb; r0 = YCbCrtoR(y0, cb0, cr0);
g0 = YCbCrtoG(y0, cb0, cr0);
b0 = YCbCrtoB(y0, cb0, cr0);
r1 = YCbCrtoR(y1, cb0, cr0);
g1 = YCbCrtoG(y1, cb0, cr0);
b1 = YCbCrtoB(y1, cb0, cr0);
if (r0 > 255) r0 = 255;
if (r0
if (g0 > 255) g0 = 255;
if (g0
if (b0 > 255) b0 = 255;
if (b0
if (r1 > 255) r1 = 255;
if (r1
if (g1 > 255) g1 = 255;
if (g1
if (b1 > 255) b1 = 255;
if (b1
rgb0 = (((u16)r0>>3)>2)>3)>3)>2)>3)
rgb = (rgb1
return(rgb);
}
YUYV----JPEG:
#define OUTPUT_BUF_SIZE 4096
#define CLEAR(x) memset (&(x), 0, sizeof (x))
#define WIDTH 640
#define HEIGHT 480
struct buffer {
void *start;
}; typedef struct {
struct jpeg_destination_mgr pub; JOCTET * buffer; unsigned char *outbuffer; int outbuffer_size; unsigned char *outbuffer_cursor; int *written;
} mjpg_destination_mgr;
typedef mjpg_destination_mgr *mjpg_dest_ptr;
static char * dev_name = "/dev/video0";
static int fd = -1;
struct buffer * buffers = NULL;
static unsigned int n_buffers = 0;
FILE *file_fd;
static unsigned long file_length;
static unsigned char *file_name;
METHODDEF(void) init_destination(j_compress_ptr cinfo) {
mjpg_dest_ptr dest = (mjpg_dest_ptr) cinfo->dest; dest->buffer = (JOCTET *) (*cinfo->mem->alloc_small)((j_common_ptr) cinfo,
}
METHODDEF(boolean) empty_output_buffer(j_compress_ptr cinfo) {
JPOOL_IMAGE, OUTPUT_BUF_SIZE * sizeof(JOCTET)); *(dest->written) = 0; dest->pub.next_output_byte = dest->buffer; dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; mjpg_dest_ptr dest = (mjpg_dest_ptr) cinfo->dest;
} dest->outbuffer_cursor += OUTPUT_BUF_SIZE; *(dest->written) += OUTPUT_BUF_SIZE; dest->pub.next_output_byte = dest->buffer; dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; return TRUE;
METHODDEF(void) term_destination(j_compress_ptr cinfo) {
}
void dest_buffer(j_compress_ptr cinfo, unsigned char *buffer, int size,int *written) {
mjpg_dest_ptr dest; if (cinfo->dest == NULL) { cinfo->dest = (struct jpeg_destination_mgr *) mjpg_dest_ptr dest = (mjpg_dest_ptr) cinfo->dest; size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; memcpy(dest->outbuffer_cursor, dest->buffer, datacount); dest->outbuffer_cursor += datacount; *(dest->written) += datacount; (*cinfo->mem->alloc_small)(
} (j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(mjpg_destination_mgr)); dest = (mjpg_dest_ptr) cinfo->dest; dest->pub.init_destination = init_destination; dest->pub.empty_output_buffer = empty_output_buffer; dest->pub.term_destination = term_destination; dest->outbuffer = buffer; dest->outbuffer_size = size;
} dest->written = written;
摄像头采集的YUYV格式转换为JPEG格式:buf为设备获取的原始数据首地址,buffer为压缩后的数据首地址。size为像素值。quality为压缩质量。
int compress_yuyv_to_jpeg(unsigned char *buf, unsigned char *buffer, int size,int quality) {
struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPROW row_pointer[1]; unsigned char *line_buffer, *yuyv; int z; static int written; line_buffer = calloc(WIDTH * 3, 1); yuyv = buf; //将YUYV格式的图片数据赋给YUYV指针 printf("compress start...\n"); cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); dest_buffer(&cinfo, buffer, size, &written); cinfo.image_width = WIDTH; cinfo.image_height = HEIGHT; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, quality, TRUE); jpeg_start_compress(&cinfo, TRUE); z = 0; while (cinfo.next_scanline
} } } row_pointer[0] = line_buffer; jpeg_write_scanlines(&cinfo, row_pointer, 1); int r, g, b; int y, u, v; if (!z) y = yuyv[0] > 8; g = (y - (88 * u) - (183 * v)) >> 8; b = (y + (454 * u)) >> 8; *(ptr++) = (r > 255) ? 255 : ((r 255) ? 255 : ((g 255) ? 255 : ((b
lcd模块
本论文是基于嵌入式Linux为基础的包括lcd部分。Linux是一款运行速度
快、开源、高效而且免费的操作系统。近年来,基于开源组织的嵌入式Linux系统的操作系统不断升级更新。Linux操作系统是不属于微内核型的操作系统,但是Linux操作系统模块化的结构可以让用户对它进行合理的剪裁,剪除我们不需要的功能以缩减系统的大小,甚至可以做到几千几百k大小。所以综合考虑系统的性能、可兼容性以及系统的运行速度,本论文采用嵌入式Linux2.6.35版本。
在S5PC100的硬件平台上安装经过剪裁后的Linux操作系统后,为了使LCD能正常显示,还需要在系统中安装相应的LCD的驱动程序。缓存(Framebuffer)技术是Linux内核中的一种常用的驱动程序设计的模式,帧缓存为LCD设备提供了控制器的抽象描述。它就是人们常说的显存,应用程序使用系统实现好的接口可以直接访问LCD底层设备,而不需要知道底层具体是如何实现的。本系统利用帧缓冲技术开发LCD驱动程序。LCD设备使用特殊的设备节点,是一个字符设备,其主设备号是29,次设备号为自己需要的帧缓冲个数。其实,帧缓冲设备和Linux中其它的设备一样。
函数接口
首先将帧缓冲设备的属性封装成结构体FB,如下:
typedef struct fb{
int fbfd ; //文件描述符 //屏幕大小 long int screensize ; struct fb_var_screeninfo vinfo; //屏幕信息 struct fb_fix_screeninfo finfo; unshort *fbp ; //mmap后的用户操作指针
} FB;
将屏幕上的点位置信息封装为结构体POINT,如下:
typedef struct point {
unshort location_wide; unshort location_hight; //此点代表的位置的宽 //此点代表的位置的高
}POINT;
FB *screen_init(FB *fb);
//屏幕初始化函数
int show_picture(FB *fb,int wide,int hight,const unchar *Image); // 图片显示函数
int show_temperature(FB *fb,const char *temperature,unshort color); //动态温度显示函数
int show_state(FB *fb,int flage,unshort color); //温度状态显示函数 int screen_close(FB *fb);
实现函数:
static FB *fb_open(const char *PATH,FB *fb);
----->打开设备函数;
static FB *get_fb_msg(FB *fb);
----->得到屏幕信息;
static FB *fb_mmap(FB *fb);
----->将设备映射到用户空间;
static FB *clean_screen(FB *fb,POINT *start,POINT *end,unshort color);
----->清除start到end之间的块儿装屏幕为color颜色;
static int show_word(FB *fb,const unchar *word,POINT *point,unshort color);
----->在给定的点location显示color颜色的字符;
static int drow_horizontal_line(FB *fb,POINT *start,POINT *end,unshort color);
----->在给定的start到end之间画一条横线
static int drow_vertical_line(FB *fb,POINT *start,POINT *end,unshort color);
----->在给定的start到end之间画一条竖线
static unchar *find_word(const char *str);
----->在0~9(包含小数点)之间找字库中对应的数组
static FB *fb_munmap(FB *fb)
----->解除映射
封装给应用层的函数
FB *screen_init(FB *fb):将打开设备到映射以及显示固定文字以及屏幕 //关闭屏幕函数
划线分割这些 准备工作做好;
int show_picture(FB *fb,int wide,int hight,const unchar *Image): 将确定宽高的图片显示在分割的视频显示区域;
int show_temperature(FB *fb,const char *temperature,unshort color): 将保存温度的字符串显示在固定的温度动态显示区域内。每次显示之前先调用函数static FB *clean_screen(FB *fb,POINT *start,POINT
*end,unshort color)来清除屏幕;
int show_state(FB *fb,int flage,unshort color):
将温度的状态显示在固定的状态显示区域内。采用switch语句通过设置标志位来区别三种状态,每次显示之前先清屏;
int screen_close(FB *fb):
先显示结束图片,再解除映射。从而实现关闭。
四、系统软件部分
(一)主程序及大致流程
本项目实现对现场图像实时监控、利用蜂鸣器以及LED报警和发送短信给用户。大致流程如图4.1:
图4.1 系统流程
1、温度监测线程
打开lm75字符设备
得到温度值 -----------> 传送给LCD显示
判断温度是否异常(报警)
关闭设备
图4.2 温度检测流程
2、视频监测线程
打开视频设备
得到图像缓存
转换格式
传送LCD显示
关闭设备
3、报警流程
传送异常信息
报警方式一:(提醒异常)
打开pwm字符设备
报警鸣响
关闭设备
报警方式二:(查看温度高低)
打开led字符设备
报警(过高:高两位灯亮, 过低:第两位灯亮)
关闭设备
图4.4 系统显示效果
(二)短消息程序设计
在本系统中,cortexA8通过串口0向GSM模块发送相应的AT命令来实现短消息的发送和接收。
1、 AT指令介绍
短消息发送命令:AT+CMGC
该命令被用来发送短消息,它不仅可以发送文本形式的短消息的,也可以发送PDU格式的短消息,它还提供了相应的测试指令以验证发送是否成功。 短消息发送指令格式:
AT+CMGS=?
如果GSM模块响应则为OK。
AT+CMGS=[,]
该命令是用来发送基于文本格式的短消息。如成功发送,则响应为:+CMGS:[,];否则响应为:+CMS ERROR:。
该命令格式中,字段为字符串形式的短信接收者的地址,指系统要发送给指定的手机号码短消息,决定定它是那种类型。当的第一个字符是“+”时,的值转换成整数值是“145”,否则的默认值为“129”.完成该条令前面的值输入再按回车符号结束。然后编写短消息的内容,并在末尾添加字符“Ctrl-Z”,“Ctrl-Z”字符的ASCII码值为“26”。如果不发送,则改为字符“ESC”。如果成功发送信息,系统会返回服务中心的时间戳。如果
发送失败,则返回相应的错误信息。
AT+CMGS=
使用命令格式来发送PDU格式的短消息。如果发送成功,则响应为:+CMGS:[,];如果发送失败,则响应为:+CMS ERROR:。
发送该命令时,首先发送命令AT+CMGC=,并末尾添加回车符,当GSM模块返回“>”字符后再编写PDU的具体内容,在类容末尾添加字符“Ctrl-Z”,该字符的ASCII码值为“26”。如果临时不发送,则用字符“ESC”替换“Ctrl-Z”。如果成功发送,返回系统状态信息,具体可参看响应命令格式。如果发送失败,就返回错误信息。发送PDU格式的短消息时,所有的参数均在PDU数据包里。
短消息删除命令:AT+CMGD (删除SIM卡内存的短消息)
该命令主要用于短消息的删除,众所周知不论是手机的存储量还是SIM卡的存储大小有限,如果短息一直累积下去系统会崩溃。因此有必要过一段时间就删除以前的短消息。该指令的格式有如下两种:
AT+CMGD=?
如果响应为OK。该指令是用来对短信删除进行确认的。
AT+CMGR=INDEX
该命令主要用来删除指定位置的短消息。如果成功删除,则返回为OK,否则返回为:+CMS ERROR:。
短消息阅读命令: AT+CMGR
该命令进行短消息阅读,它具体的格式有如下两种:
AT+CMGR=?
响应为OK。该指令用来短消息的确认。
AT+CMGR=INDEX
该命令用于指定位置的短消息的阅读。如果成功,则返回具体的短消息内容,文本模式和PDU模式两者响应的内容不同。如果操作失败,则返回错误指令格式为:+CMS ERROR:。
设置短信中心命令:AT+CSCA
发送短消息是需要设置短信中心,它具体提供三中指令:
AT+CSCA=?
响应为OK。对短信中心设置的确认。
AT+CSCA?
用来获取短信中心的地址。如果成功操作,则响应为+CSCA:OK。响应中的为短信中心的地址,用来表示为地址类型的标示符。 AT+CSCA=,[]
本系统只需用到以上的一些AT命令,AT指令还有很多可以参看AT命令手册。本系统既可以发送PDU短信也可以发送文本格式的短信。
2、PDU编码规则
PDU模式的短信可以分为3种编码:7-bit、8-bit和 UCS2编码。普通的ASCII字符发送用7-bit编码,发送数据消息用8-bit编码,Unicode字符用UCS2编码发送。PDU编码一般由A B C D E F G H I J K L M十三项构成。 A:短信中心地址长度,十六进制格式数据2位。
B:短信中心号码类型,十六进制格式数据2位。
C:短信中心号码,A中的数据决定B+C的长度。
D:短信内容开始的第一个字节,十六进制格式数据2位。
E:信息类型,十六进制格式数据2位。
F:呼叫短信号码长度,十六进制格式数据2位。
G:呼叫短信类型,十六进制格式数据2位,同B的值一样。
H:呼叫短信号码,F中的数据长度决定该字段长度。
I:协议标识,十六进制格式数据2位。
J:数据编码方案,十六进制格式数据2位。
K:有效期,十六进制格式数据2位。
L:用户数据长度,十六进制格式数据2位。
M:用户数据,其长度由L中的数据决定。
由于本设计发送的是中文信息,所以J中设定采用UCS2编码,这里是中英文的Unicode字符。
3、短信模式设置
GSM模块的短信模式有2种。第1种是:TEXT模式;第2种是:PDU模式。PDU模式可以采用unicode编码发送英文、汉字。本系统采用的是PDU模式。设置如下:
AT+CMFG=1回车
4、短信的发送方法
(1)开始打开串口,然后初始化串口。
(2)通过写指令write向串口写AT指令集。
然后通过读指令read从串口读数据,如果读出出错信息error,则从新发送;如果一直返回ok,则发送成功。
(3)用txt模式发送温度信息,用pdu模式发送相应的中文信息。
(4)关闭串口,成功退出。
五、测试及结论
系统测试是为了增加系统的稳定性和调试程序中的BUG,通过对该系统进行测试后找出了需要改进的地方,修改了人脸识别算法以及整个系统的稳定性有了提高,增加了识别率,提高了视频帧的采集及处理速度,界面设计清晰美观。
(一)测试原则
1、根据该系统的功能需求进行测试。
2、测试需要清晰明了的书写测试文档和输出结果。
3、程序员需要根据测试文档对自己的系统进行改进和说明。
4、在进行对整个系统进行综合的测试时,应当提出合理的测试条件和合理的输入条件,支出该系统需要改进的功能等。
5、测试员要注意测试中的群集现象,测试后程序残存的错误数目与该程序中以发现的错误数量成正比,应该对该系统容易出现的问题进行反复的测试及验证。
6、严格的根据测试要求来执行测试计划,排除测试中的随意性,测试要求应该包括:该系统的功能,输入和输出,测试内容,界面的可控性,系统的稳定性等方面。
7、在测试完系统后需要对每一个测试报告进行全面的检测与核对。
8、对测试报告及测试计划进行归档保管,测试具有出错统计和最终的分析报告,这样为了改进系统,维护系统等方面有了很大的帮助性。
(二)测试方案
本系统主要由Lcd模块、GSM模块以及传感器模块组成。系统中的传感器模块集成在cortexA8上。当整个系统上电后。我设置的是开机就启动本系统。
在Lcd屏上就会自动显示摄像头获取的图像以及当前温度值。系统设置好了温度的上下线值。当用户用一些途径改变温度传感器值只要越过了上下线值,这时Led灯会不断闪烁,系统会自动发送短信到设置的手机号码上。当用户收到cortexA8发送的短信时。可根据短信内容回复相应的信息。cortexA8收到用户的短信后会根据短信进行相应的处理,比如:关闭板子后者启动蜂鸣器。
(三)结论
经过测试得到如下结论。本系统借助于GSM网络通信技术和cortexA8的控制功能,实现了对家电的远程监控和控制。系统充分利用GSM网络覆盖范围的无缝化、广阔化和短消息的业务,使用户可以随时随地的了解住宅情况并实现远程控制。同时GSM模块与中心控制单元可以集成在一起,使整个系统的稳定性提高而成本降低。本系统可用于居民住宅,也可以用于仓库、厂房与蔬菜大棚等地方的远程安监控以及及时的对报警信息进行处理。本系统具有成本低、安全简单、易操作等优点。
参 考 文 献
[1]杨利平.基于网络技术的远程智能家居系统[J].仪器仪表学报,2009(10):19-32.
[2]张俊.SMS 短消息传输的远端控制技术及其实现[J].仪器仪表学报,2003:29-31.
[3]万福君.单片微机原理系统设计与开发[M].合肥:中国科技大学出版社,1995:156-169.
[4]谢自美.电子线路设计[M].武汉:华中科技大学出版社,2000:122-128.
[5]樊昌信.通信原理[M].北京:国防工业出版社,2009.5.
[6]藏春华,邵杰,魏小龙,等.综合电子系统设计与实践[M].北京航空航天大学出版社
2009.
[7]裘岚.C语言程序设计实用教程[M].北京:电子工业出版社,2001.
[8]樊天晴.Internet信息终端技术的研究[M].兰州:西北工业大学,2002.
[9]魏小龙.51系列cortexA8接口技术及系统设计实例[M].北京:北京航空航天大学出版
社, 2002.
[10]王琴放.cortexA8原理及应用[M].北京:电子工业出版社:1997:129-136.
[11]徐顺成.实用电子技术与电子产品汇编[M].北京:电子工业出版社,1993.
[12]刘松,赵忠,孙学磊,等.远程家庭智能监控系统设计[M].北京:高等教育出版
社,2009:98-106.
[13]李群芳.单片微型计算机与接口技术[M].北京:电子工业出版社,2005:152-163.
[14]沙占友.集成化智能传感器原理与应用[M].北京:电子工业出版社.2004.
[15]康华光.电子技术基础[M].北京:高等教育出版社,2006:102-109.