admin 管理员组文章数量: 1086019
2024年12月24日发(作者:墨茶色是什么颜色)
智能家居学习手册
广州粤嵌通信科技股份有限公司
作者
日期
版本
粤嵌教仪
2013-11
beta
第一章智能家居
--------------------------------------------------------------------------------3
1.1
智能家居的需求
----------------------------------------------------------------------3
1.2
系统功能
-------------------------------------------------------------------------------3
1.1.1
中央控制系统
-----------------------------------------------------------------4
1.1.2
智能家居的功能
--------------------------------------------------------------4
1.1.3
功能界面
-----------------------------------------------------------------------5
1.3
开发流程
-------------------------------------------------------------------------------5
第二章图形界面编程
--------------------------------------------------------------------------5
2.1QT
界面设计
---------------------------------------------------------------------------5
2.1.1
建立工程
-----------------------------------------------------------------------5
2.1.2
界面编程
-----------------------------------------------------------------------7
2.1.2
编译运行
---------------------------------------------------------------------12
2.2
设计多界面
---------------------------------------------------------------------------13
2.2.1
创建多界面类
---------------------------------------------------------------13
2.2.2
界面编程
---------------------------------------------------------------------14
2.4
加载驱动
------------------------------------------------------------------------------18
2.4.1
上位机操作
-------------------------------------------------------------------18
2.4.2
开发板操作
-------------------------------------------------------------------22
2.5
界面调用驱动
------------------------------------------------------------------------22
第三章空调模块
------------------------------------------------------------------------------24
3.1
图形界面设计
-------------------------------------------------------------------24
3.1.1
建立工作目录
---------------------------------------------------------------24
3.1.2
建立
QT
工程
----------------------------------------------------------------24
3.2
界面调用驱动
-------------------------------------------------------------------25
3.3
界面调用驱动
-------------------------------------------------------------------27
3.3.1
上位机操作
-------------------------------------------------------------------27
3.3.2
开发板操作
-------------------------------------------------------------------30
第四章温湿度模块
---------------------------------------------------------------------------31
4.1
图形界面设计
------------------------------------------------------------------------31
4.1.1
建立工作目录
----------------------------------------------------------------31
4.1.2
界面设计
---------------------------------------------------------------------31
4.2
界面调用驱动
------------------------------------------------------------------------34
4.3
加载驱动
------------------------------------------------------------------------------35
4.3.1
上位机操作
-------------------------------------------------------------------35
4.3.2
开发板操作
-------------------------------------------------------------------41
第五章
RFID
模块
-----------------------------------------------------------------------------42
5.1
图形界面设计
------------------------------------------------------------------------42
5.1.1
创建工程目录
----------------------------------------------------------------42
5.1.2
创建工程
----------------------------------------------------------------------42
5.1.3
界面设计
---------------------------------------------------------------------43
5.2
源码实现
------------------------------------------------------------------------------45
第六章报警模块
------------------------------------------------------------------------------50
6.1
创建工程
------------------------------------------------------------------------------51
6.1.1
创建工程目录
----------------------------------------------------------------51
6.1.2
创建工程
----------------------------------------------------------------------51
6.2
界面设计
------------------------------------------------------------------------------52
6.3
源码实现
------------------------------------------------------------------------------54
6.4
驱动实现
------------------------------------------------------------------------------59
第七章
GPRS
模块
-----------------------------------------------------------------------------65
7.1.1
创建工程目录
----------------------------------------------------------------65
7.1.2
创建工程
----------------------------------------------------------------------65
7.1.3
源码实现
----------------------------------------------------------------------66
第一章智能家居
伴随着数字化和网络化的进程,智能化的浪潮席卷了世界的每一个角落,成
为一种势不可挡的历史化大趋势。这一切的最终目的为人们提供一个以人为本的
舒适、便捷、高效安全的生活环境。
如何建立一个高效率、高性能、低成本的智能家居系统是我们项目的主题。
1.1智能家居的需求
智能家居系统的使用者,他们追求舒适的生活环境,所有的系统一定要稳定、
所有的软件界面操作起来一定要友好。
智能家居系统有一个稳定可靠的中央控制系统,稳定的无线网络,通过这个
无线网络可以控制多个智能模块。像一键触控的智能灯光模块、智能空调模块、
智能窗帘模块、智能通讯模块;自动监控的智能温湿度模块、报警模块、RFID
模块等。
1.2系统功能
智能家居根据用户的需求,如下图所示:中央控制系统通过无线网络,控制
了智能灯光模块、智能温湿度模块、智能空调模块、智能窗帘模块、智能通讯模
块、智能报警模块等多个功能模块。
1.1.1中央控制系统
智能家居,需要一个使用
GEC2440
或者
GEC210
的开发板来设计一个中央
控制系统,通过它来实现对室内电器的监控与控制。
这个中央控制系统,使用Linux作为系统内核、QT作为用户界面、TCP/IP
协议来通信、GPIO口来控制门口电机、温度传感器、窗台电机、烟雾传感器、
灯、光传感器等功能模块。示意图如下所示:
1.1.2
智能家居的功能
智能家居的要实现的功能:智能门禁、智能温湿度监控、智能灯光调节、智
能空调、智能窗帘、RFID模块、智能GPRS通讯、智能报警。
智能门禁:轻轻一点触摸屏上的按键,就可以驱动继电器开门。
智能温湿度监控:从LCD屏幕上,我们可以看到读取的温度和湿度。
智能灯光调节:进去灯光模块,轻轻一点触摸屏上的按键,就可以控制房间
或者大厅的灯光。
智能空调:除了可以通过轻轻一点触摸屏上的按键实现空调的开关控制,也
能和温湿度监控系统结合起来,在室内温度高于预设的温度时,自动开启。
智能窗帘:除了可以通过轻轻一点触摸屏上的按键实现窗帘的开关控制,也
能根据光感电阻的变化,在室内光线高于预设值时,自动关闭。
RFID模块:刷卡识别是不是房主。
智能GPRS通讯:可以实现通话和短信通知的功能,当房间的红外监控模块
发现异常的事情发生时,会通过GPRS模块,将异常发送到房主的手机上。
智能报警:当发现火警或者异常的事情发生,报警器会发出警告,同时通过
GPRS
模块,通知房主,房间发生异常。
1.1.3功能界面
所有的功能模块,都需要通过友好的界面来控制,那么,我们就要为客户设
计一个容易操作的友好界面。
功能界面共分为:主界面、功能主界面、门禁界面、窗帘界面、空调界面、
GPRS设置界面、报警界面。
1.3开发流程
简易的智能家居开发分为三个环节:构建家居的Linux系统、设计功能模块
的驱动、设计图形界面。
构建智能家居的Linux系统的开发流程是:移植uboot--->移植Linux内核
--->移植Linux根文件系统--->移植Linux驱动,具体的操作步骤请查看:Linux
系统移植手册。
设计功能模块驱动:了解硬件--->设计Linux驱动--->加载驱动。具体的
设计步骤请查看光盘目录中参考资料里所对应功能模块的源码和手册。
设计图形界面:编写Qt界面--->移植qte到开发板--->界面调用驱动
--->再次移植qte到开发板。具体的步骤请查看本手册以下内容。
第二章图形界面编程
智能家居都是由多个界面切换而成的,所以首先我们要学会在pc机上面编
写qt的界面,从单个界面到多个界面之间的却换,再到驱动调用和文件编译,
接下来请跟着我们的文档提示,一步步地操作。
我们先从最简单的灯光模块开始。
2.1QT界面设计
2.1.1
建立工程
1.建立工作目录
mkdir/home/example/SmartHome
2.打开ubuntu上已经装好的QtCreator软件,如下图所示。如果还没装QtCreator
并且搭建好开发环境,请参考文档《GEC210开发环境搭建.doc》。
3.
开始创建工程,并且将工程文件放在第一步创建的路径下。如下如所示:
并且按默认,选择下一步。
2.1.2界面编程
1、正式开始界面编程。首先我们要知道的是210开发板配套的屏幕大小是7寸,
其分辨率是800*480,因此我们要使主界面和屏幕往前匹配。于是,点击界面文
件,如下如:
来到界面控制窗口,看到丰富的控件种类。但是我们要先调整界面大小吧,如下
图:
2.
、添加
Qt
资源文件。为了使界面更加的绚丽和增强交互性,我们必要性加入
点资源文件,比如说图片。在工程右键,请看下图:
在此之后,要对资源文件命名。添加完成后会出现下图文件。
在双击此文件开始添加图片资源。首先要添加前缀,再是添加文件。
再次是添加文件,并且选择自己想选择的图片,推荐把图片统一放在当前工程目
录下。
3
、添加控件和资源。首先添加背景图片,双击进去界面文件,右键改变样式表。
Ps:格式:Qwidget#类名{background-image:url(:/图片.jpg):}
接着,添加控制按键。比如:门,灯,空调,窗帘,安防,摄像头监测,
GPRS
。
拖放完空间后,并按照自己的喜好修改控件大小和控件名以及位置。同样可以拖
进其他的
6
个控件。在控件上右键,改变样式表,如下图:
选择控件的图片,一般情况下,当控件显示图片情况下,为了界面更加绚丽,应
当取消控件的静态文字显示,于是,双击控件,删除文字。其他控件改变图片方
法一样。完成上述工作之后,请看下图:
在编译运行之前,应该加上一行代码,使界面和屏幕更加匹配。目的是去掉窗口
的标题栏:
2.1.2编译运行
提示:此步骤的前提是要安装交叉编译链和交叉环境,如果还没安装,请参考文
档《
GEC210
开发环境搭建
.doc
》。务必也要搭建好
NFS
环境。
进到工程所在路径。
qmake-v
如果出现下图所示,证明环境安装成功
接着,
qmake//
生成
Makefile
make
编译完成后,用
file
命令查看可执行文件
FileSmartHome
看到上图出现的“
ARM
”,证明已经成功了,那么试着到开发板上运行吧,可以
通过tftp,nfs(推荐nfs)或者其他方法移植到ARM板上。
2.2设计多界面
2.2.1创建多界面类
Qt
编程里,一般来说一个界面肯定是独立的一个类,如果要创建多界面工程,
必须创建多个类。在菜单栏上点击新建文件,如下图:
接着输入创建的类名,这里以
door
为类名。
2.2.2界面编程
如2.1.2一样,对界面文件进行编辑的话,会出现控件继承父窗口的图片,
因为界面是一个QWidget,因此,先拖入一个QFrame并调整和QWidget一样大
小:
接着在Frame上改变样式表QFrame#frame{border-image:
url(:/images/door/d_);},拖放控件,更改命名,调整大小,添加图片资源,
以及改变样式表对此界面装饰。可根据自己的喜好,完成此步骤有下图:
到这里我们已经创建好和做好界面设计,但是我们并没有在源码中实现调用此界
面。在这步骤我们要实现的是:当我们点击最左边的门控制按钮的时候,会跳转
到我们刚刚实现的
UI
界面那里。打开
2.1
中创建的界面文件
,在
门控制按钮
pushButton_door
右键,选择转到槽
,
如下图:
并选择
click()
信号,也就是当控件发送
click()
信号的时候,会自动去执行此槽函
数,槽函数的命名机制是根据控件的命令和信号的类型。如下图:
现在就可以在这个函数实现想实现的操作。而我们就是为了实现界面跳转。思路
是:当主界面的
pushButton_door
触发
click()
的时候,会显示
door
控制界面,同
时主界面隐藏。而当在
door
控制界面的返回按钮
pushButton_back
触发
click()
的
时候,发送一个信号给主界面,主界面收到这个信号就删除
door
对象,显示主
界面。
首先在
door.h
上定义发给
SmartHome
的信号:
然后去到
的返回键右键转到槽并且选择
click()
信号:
接着,在
SmartHome.h
添加头文件
door.h,
并且声明
door
的对象和显示主界面的
槽函数:
并且实现
pushButton_door
的
click()
的函数体以及
ShowSmartHome
的函数体:
记住,和主界面一样,这个界面也要设置全屏模式,那么就可以保存编译了,大
家看看效果吧。
2.4
加载驱动
2.4.1上位机操作
建立工作目录
#mkdir/home/driver
#cd/home/driver
vimrelay.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#defineDEVICE_NAME"relay"
staticintrelay_gpios[]={
S5PV210_GPH3(3),
};
#defineRELAY_NUM
//驱动模块节点名字
ARRAY_SIZE(relay_gpios)
staticlonggec210_relay_ioctl(structfile*filp,unsignedintcmd,
unsignedlongarg)
{
switch(cmd){
case0:
if(arg>RELAY_NUM){
return-EINVAL;
}
gpio_set_value(relay_gpios[arg],cmd);
break;
case1:
if(arg>RELAY_NUM){
return-EINVAL;
}
gpio_set_value(relay_gpios[arg],cmd);
//printk(DEVICE_NAME":%d%dn",arg,cmd);
break;
default:
return-EINVAL;
}
return0;
}
staticstructfile_operationsgec210_relay_dev_fops={
.owner
};
staticstructmiscdevicegec210_relay_dev={
.minor
.name
.fops
};
staticint__initgec210_relay_dev_init(void){
intret;
inti;
for(i=0;i ret=gpio_request(relay_gpios[i],"RELAY"); if(ret){ printk("%s:requestGPIO%dforRELAYfailed,ret=%dn",DEVICE_NAME, relay_gpios[i],ret); returnret; } s3c_gpio_cfgpin(relay_gpios[i],S3C_GPIO_OUTPUT); gpio_set_value(relay_gpios[i],1); } =MISC_DYNAMIC_MINOR, =DEVICE_NAME, =&gec210_relay_dev_fops, =THIS_MODULE, .unlocked_ioctl=gec210_relay_ioctl, ret=misc_register(&gec210_relay_dev); printk(DEVICE_NAME"tinitializedn"); returnret; } staticvoid__exitgec210_relay_dev_exit(void){ inti; for(i=0;i gpio_free(relay_gpios[i]); } misc_deregister(&gec210_relay_dev); } module_init(gec210_relay_dev_init); module_exit(gec210_relay_dev_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("GecLab."); #vimMakefile 修改红色部分 CONFIG_HOUSELED?=m ifneq($(KERNELRELEASE),) #relay-objs:=relay.o// 编译的模块的命名 obj-$(CONFIG_HOUSELED)+=relay.o else PWD:=$(shellpwd) KERN_VER=$(shelluname-r) #KERN_DIR=/lib/modules/$(KERN_VER)/build #YOURCROSSCOMPILEKERNELDIR KERN_DIR=/home/kernel/linux-2.6.35.7-gec-v3.0// 注意这里,我的 linux 源 代码是在 /home/kernel 下,这里的源码必须是已经编译过的源码 modules: $(MAKE)-C$(KERN_DIR)M=$(PWD)modules endif clean: rm-rf*.o*~*.cmd*.ko*.mod.c*.tmp_versions 进行编译 #make 得到 .ko 文件,这个文件就是内核模块。 测试程序也是在 /home/driver/ 创建 vimrelay_test.c #defineRELAY_DEVICE_FILENAME"/dev/relay" #defineRELAY_ON0 #defineRELAY_OFF1 intmain(void) { intval=0; intfd; fd=open(RELAY_DEVICE_FILENAME,O_RDWR); while(val!=3) { printf("pleaseselectnumbertorunprogramn"); printf("1:RELAYonn2:RELAYoffn"); scanf("%d",&val); if(val==1) { ioctl(fd,RELAY_ON,0); printf("RELAY_ONn"); } elseif(val==2) { ioctl(fd,RELAY_OFF,0); printf("RELAY_OFFn"); } } close(fd); return0; } 目录下,进行交叉编译 #arm-linux-gcc-orelay_testrelay_test.c 2.4.2 开发板操作 把内核模块和编译好的测试程序relay_test通过nfs挂载到开发板(这 部分在文档《GEC210开发环境搭建.doc》里面有介绍) 把开发板和智能家居底板连好线 在开发板终端上测试 # #chmod777relay_test 加载内核模块 # 改驱动模块是已经自动创建该设备节点了,这时候我们可以测试驱动了 #./relay_test 有以下打印信息 可以看到,输入1为打开继电器,2为关闭继电器。在此过程可以听到继电器的 声音。 2.5界面调用驱动 在开始这章的实验前,要先认真照着上面两章:图形界面界面开发和 linux 驱动开发的步骤,完成图形界面和 Linux 驱动代码的编写。那么接下来看源码实 现:修改 , 提示:红色代码为修改代码 #include"door.h" #include"ui_door.h" #include #include #include #include #include #include #include #include constintRELAY_ON=0; constintRELAY_OFF=1; constchar*RELAY_DEV="/dev/relay"; door::door(QWidget*parent): QWidget(parent), ui(newUi::door) { ui->setupUi(this); setWindowFlags(Qt::FramelessWindowHint); fd=open(RELAY_DEV,O_RDWR); if(fd<0) qDebug()<<"Relaydevopenfail!"; // 设置全屏,去标题栏 } 上面为构造函数,打开设备,那么下面就是控制了,来到控制按钮 pushButton_door 的槽函数: voiddoor::on_pushButton_door_clicked() { staticboolon_off_flag=false; if(!on_off_flag) { on_off_flag=true; ioctl(fd,RELAY_ON,0); ui->pushButton_door->setStyleSheet(QString::fromUtf8("border-image: url(:/images/door/d_);")); } else { on_off_flag=false; ioctl(fd,RELAY_OFF,0); ui->pushButton_door->setStyleSheet(QString::fromUtf8("border-image: url(:/images/door/d_);")); } } 同时 voiddoor::on_pushButton_back_clicked() { ::close(fd); emitsig_GoBack_SmartHome(); } 到这里,就可以编译运行了,看看效果吧 ! 第三章空调模块 有了前一章的基础,那么我们可以开始智能家居空调模块的设计工作,设计 空调模块的方法与灯光模块相似,也是从编写单个界面开始,加载驱动,调用驱 动,编译文件,完成空调模块的设计。 3.1图形界面设计 3.1.1建立工作目录 mkdir/home/example/AirCondition cd/home/example/AirCondition 3.1.2 建立 QT 工程 和之前建立工程一样,并将工程路径设在/home/example/AirCondition 然后双击进去 .ui 界面文件进行界面设计。这个步骤包括:大小调整,添加资 源文件,添加图片,拖放控件,设置背景图片等等,可参考前面第二章。先是资 源文件: 接着是对 .ui 文件右键改变样式表设置背景等的设计。完成设计之后: 3.2 3.2 界面调用驱动 首先增加头文件 在 中增加相对应的头文件 #include #include constintMOTOR_ON=1; constintMOTOR_OFF=0; AirCondition::AirCondition(QWidget*parent): QMainWindow(parent), ui(newUi::AirCondition) { ui->setupUi(this); Getmotorflag=false; setWindowFlags(Qt::FramelessWindowHint);// 去标题栏 motorfd=open("/dev/dc_motor",O_RDWR);// 直流电击 if(motorfd<0) { qDebug(""); } } 控制空调的按键 pushButton_onoff 的槽函数:如下 voidAirCondition::on_pushButton_onoff_clicked() { if(Getmotorflag) { ioctl(motorfd,MOTOR_OFF,0); ui->pushButton_onoff->setIcon(QIcon(":/images/air_")); ui->pushButton_air->setIcon(QIcon(":/images/air_")); Getmotorflag=false; } else { ioctl(motorfd,MOTOR_ON,0); ui->pushButton_onoff->setIcon(QIcon(":/images/air_")); ui->pushButton_air->setIcon(QIcon(":/images/air_")); Getmotorflag=true; } } AirCondition::~AirCondition() { ::close(motorfd); deleteui; } 那么到这里就基本实现了对空调的控制,但是自动控制模块我们还没有实现。那 么就先来测试一下吧!编译传送到 210 开发板上。 3 3.3.3界面调用驱动 3.3.1上位机操作 vimmoto.c 开始编程驱动模块 #include #include #include #include #include #include #include #include #include #include #include #include #include #defineDEVICE_NAME"dc_motor" staticintmotor_gpios[]={ S5PV210_GPH3(1), S5PV210_GPH2(3), }; #defineMOTOR_NUMARRAY_SIZE(motor_gpios) staticvoidmotor_init(void) { gpio_set_value(motor_gpios[0],0); gpio_set_value(motor_gpios[1],0); //s3c_gpio_setpull(S5PV210_GPH3(1),0); //s3c_gpio_setpull(S5PV210_GPH2(2),0); } staticvoidmotor_foreward(void) { gpio_set_value(motor_gpios[0],1); gpio_set_value(motor_gpios[1],0); } staticvoidmotor_rollback(void) { gpio_set_value(motor_gpios[1],1); gpio_set_value(motor_gpios[0],0); } staticintgec210_motor_open(structinode*inode,structfile*filp) { printk(DEVICE_NAME":openn"); motor_init(); return0; } staticlonggec210_motor_ioctl(structfile*filp,unsignedintcmd, unsignedlongarg) { switch(cmd){ case0: if(arg>MOTOR_NUM){ return-EINVAL; } motor_init(); printk("MotorStop.n"); break; case1: if(arg>MOTOR_NUM){ return-EINVAL; } motor_rollback(); printk("MotorRollback.n"); break; case4: if(arg>MOTOR_NUM){ return-EINVAL; } motor_foreward(); printk("MotorForeward.n"); break; default: return-EINVAL; } return0; } staticstructfile_operationsgec210_motor_dev_fops={ .owner=THIS_MODULE, .unlocked_ioctl=gec210_motor_ioctl, }; staticstructmiscdevicegec210_motor_dev={ .minor=MISC_DYNAMIC_MINOR, .name=DEVICE_NAME, .fops=&gec210_motor_dev_fops, }; staticint__initgec210_motor_dev_init(void){ intret; inti; for(i=0;i ret=gpio_request(motor_gpios[i],"MOTOR"); if(ret){ printk("%s:requestGPIO%dforMOTORfailed,ret=%dn", DEVICE_NAME, motor_gpios[i],ret); returnret; } s3c_gpio_cfgpin(motor_gpios[i],S3C_GPIO_OUTPUT); gpio_set_value(motor_gpios[i],0); } gpio_set_value(motor_gpios[0],0); gpio_set_value(motor_gpios[1],0); ret=misc_register(&gec210_motor_dev); printk(DEVICE_NAME"tinitializedn"); returnret; } staticvoid__exitgec210_motor_dev_exit(void){ inti; for(i=0;i gpio_free(motor_gpios[i]); } misc_deregister(&gec210_motor_dev); } module_init(gec210_motor_dev_init); module_exit(gec210_motor_dev_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("GecLab."); 3.3.2开发板操作 #vimMakefile 修改红色部分 CONFIG_HOUSELED?=m ifneq($(KERNELRELEASE),) #dc_motor-objs:=dc_motor.o//编译的模块的命名 obj-$(CONFIG_HOUSELED)+=dc_motor.o else PWD:=$(shellpwd) KERN_VER=$(shelluname-r) #KERN_DIR=/lib/modules/$(KERN_VER)/build #YOURCROSSCOMPILEKERNELDIR KERN_DIR=/home/kernel/linux-2.6.35.7-gec-v3.0// 注意这里,我的 linux 源 代码是在 /home/kernel 下,这里的源码必须是已经编译过的源码 modules: $(MAKE)-C$(KERN_DIR)M=$(PWD)modules endif clean: rm-rf*.o*~*.cmd*.ko*.mod.c*.tmp_versions 进行编译 #make 如前面内容 2.4.1 操作一样,编译出 .ko 文件。并传送到 210 板上,执行命令: 就可以成功生成节点了!那么现在就执行刚刚完成的可执行程序吧: 这个时候触摸屏幕控制直流点击吧。 第四章温湿度模块 智能家居的开始界面的右下方有一个显示温湿度的表,大家一定很好奇这个 温湿度的表是如何做出来,这一章就来满足大家的好奇心,认真完成这一章的学 习,你将编写出属于自己的温湿度模块。 4.1图形界面设计 4.1.1建立工作目录 mkdir/home/example/humidity cd/home/example/humidity 4.1.2 界面设计 首先创建工程 添加资源文件 添加前缀,添加文件: 然后针对界面文件设计,完成效果图: 4.2界面调用驱动 增加头文件 在中增加相对应的头文件 #include #include 在构造函数中, Humidity::Humidity(QWidget*parent): QMainWindow(parent), ui(newUi::Humidity) { ui->setupUi(this); setWindowFlags(Qt::FramelessWindowHint);// 去标题栏 hdfd=::open("/dev/humidity",0);// 温湿度 if(hdfd<0) qDebug(""); showtimer=newQTimer; connect(showtimer,SIGNAL(timeout()),this,SLOT(showhumidity())); showtimer->start(2000); } 接着是显示的函数,这里是一个定时器槽函数,读取温湿度并且显示出来: voidHumidity::showhumidity() { QStringhumidity; QStringtemp; if(read(hdfd,&temperature,sizeof(temperature))==0) { humidiyz=(temperature&0xff000000)>>24;// 湿度整数 humidiyx=(temperature&0x00ff0000)>>16;// 湿度小数 tempz=(temperature&0x0000ff00)>>8;// 温度整数 tempx=(temperature&0x000000ff);// 温度小数 qDebug("humidiyz=%dtempz=%d",humidiyz,tempz); humidity=QString("%1.%2").arg(humidiyz).arg(humidiyx); temp=QString("%1.%2").arg(tempz).arg(tempx); ui->lineEdit_humidity->setText(humidity+"%"); ui->lineEdit_temp->setText(temp+"'C"); } } Humidity::~Humidity() { ::close(hdfd); deleteui; } 4.3加载驱动 4.3.1上位机操作 vimhumidity.c 开始编程温湿度驱动模块 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #defineDEVICE_NAME"humidity" //XEINT24/KP_ROW0/GPH3_0 unsignedlongreceive_value; unsignedlongreceive_jy; intdata_in(void) { s3c_gpio_cfgpin(S5PV210_GPH3(0),S3C_GPIO_INPUT); returngpio_get_value(S5PV210_GPH3(0)); } voiddata_out(intdata) { s3c_gpio_cfgpin(S5PV210_GPH3(0),S3C_GPIO_OUTPUT); gpio_set_value(S5PV210_GPH3(0),data); } voidread_data(void) { unsignedintflag=0; unsignedintu32i=0; data_out(0); mdelay(20); data_out(1); udelay(40); if(data_in()==0) { while((data_in()==0)&&((flag++)<50000)); flag=0; receive_value=0; receive_jy=0; while(data_in()!=0); for(u32i=0x80000000;u32i>0;u32i>>=1) { flag=0; while((data_in()==0)&&((flag++)<50000)); flag=0; while((data_in()!=0)&&((flag)<500)) { udelay(10); flag++; } if(flag>5) { printk("flag1=%dn",flag); receive_value|=u32i; } } //printk("flag0=%dn",flag); for(u32i=0x80;u32i>0;u32i>>=1) { flag=0; while((data_in()==0)&&((flag++)<50000)); flag=0; while((data_in()!=0)&&((flag)<500)) { udelay(10); flag++; } if(flag>5) { receive_jy|=u32i; } } } } // voidhumidity_read_data(void) { unsignedintflag=0; unsignedintu32i=0; receive_value=0; receive_jy=0; data_out(0); mdelay(20); data_out(1); udelay(40); if(data_in()==0) { flag=0; while(data_in()==0)// 响应 80us 的低电平 { udelay(10); flag++; if(flag>10) return;// 超过 100us ,器件还是没有响应,认为其出现问题 ,退出 } //printk("80uslowflag=%dn",flag); flag=0; while(data_in()==1)// 响应 80us 的高电平 { udelay(10); flag++; if(flag>10) return;// 超过 100us ,器件还是没有响应,认为其出现问题 ,退出 } //printk("80ushighflag=%dn",flag); flag=0; for(u32i=0x80000000;u32i>0;u32i>>=1) { flag=0; while(data_in()==0)// 响应 50us 的低电平 , 开始接收 数据 { udelay(10); flag++; if(flag>10) break; } flag=0; while(data_in()==1) 70us { udelay(10); flag++; if(flag>10) break; // 响应高电平,持续高电平时间最多不超过 } if(flag>5)// 低电平持续时间为 26us-28us 为数据 0 高电平持续时间 为 70us 为数据 1 { receive_value|=u32i; } } #if1 //printk("flag0=%dn",flag); for(u32i=0x80;u32i>0;u32i>>=1) { flag=0; while(data_in()==0)// 响应 50us 的低电平 , 开始接收 { udelay(10); flag++; if(flag>10) break; } flag=0; while(data_in()==1) 70us { udelay(10); flag++; if(flag>10) break; } if(flag>5)// 低电平持续时间为 26us-28us 为数据 0 高电平持续时间 为 70us 为数据 1 { receive_jy|=u32i; } } #endif } } // 响应高电平,持续高电平时间最多不超过 数据 staticssize_tgec210_humidiy_read(structfile*file,char__user*buf,size_tsize, loff_t*off) { unsignedchartempz=0; unsignedchartempx=0; unsignedcharhumidityz=0; unsignedcharhumidityx=0; unsignedcharecc,jy; humidity_read_data(); humidityz=(receive_value&0xff000000)>>24; humidityx=(receive_value&0x00ff0000)>>16; tempz=(receive_value&0x0000ff00)>>8; tempx=(receive_value&0x000000ff); jy=receive_jy&0xff; ecc=humidityz+humidityx+tempz+tempx; printk("=============ecc=%xjy=%xn",ecc,jy); if(ecc!=jy) return-EAGAIN; copy_to_user(buf,&receive_value,sizeof(receive_value)); return0; // } staticintgec210_humidiy_open(structinode*inode,structfile*file) { printk("openinkerneln"); return0; } staticvoidgec210_humidiy_release(structinode*inode,structfile*file) { printk(""); } staticstructfile_operationsgec210_humidity_dev_fops={ .owner=THIS_MODULE, .open=gec210_humidiy_open, .read=gec210_humidiy_read, .release=gec210_humidiy_release }; staticstructmiscdevicegec210_humidity_dev={ .minor=MISC_DYNAMIC_MINOR, .name .fops }; =DEVICE_NAME, =&gec210_humidity_dev_fops, staticint__initgec210_humidity_dev_init(void){ intret; ret=gpio_request(S5PV210_GPH3(0),"humidity"); if(ret){ printk("%s:requestGPIO%dforhumidityfailed,ret=%dn", DEVICE_NAME, S5PV210_GPH3(0),ret); returnret; } s3c_gpio_cfgpin(S5PV210_GPH3(0),1); gpio_set_value(S5PV210_GPH3(0),1); ret=misc_register(&gec210_humidity_dev); printk(DEVICE_NAME"tinitializedn"); returnret; } staticvoid__exitgec210_humidity_dev_exit(void) { gpio_free(S5PV210_GPH3(0)); misc_deregister(&gec210_humidity_dev); } module_init(gec210_humidity_dev_init); module_exit(gec210_humidity_dev_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("GecLab."); 4.3.2开发板操作 编译生成 , 并且在开发板执行命令 查看/dev/目录是不是有humidity节点,如果有则是加载成功了。然后运行已经 完成的Qt可执行程序,程序启动后会自动采集温湿度并且显示的。 第五章 RFID 模块 智能家居在操作所有界面之前,必须要进行刷卡,对刷卡进行检验工作的是 RFID 模块,这一章让我们来学习如何设计 RFID 模块的界面。 5.1图形界面设计 5.1.1 创建工程目录 mkdir/home/example/RFID cd/home/example/RFID 5.1.2创建工程 5.1.3 界面设计 添加前缀和添加文件: 调整主界面大小为800*480: 修改主界面样式表: 拖拉控件并调整大小: 同时我们要加入一个 lineEdit 来显示 RFID 模块监测到的卡 ID. 5.2源码实现 修改 添加头文件: #include #include #include #include #include #include #include #include #include #include #include #include 下面涉及到几个读卡 ID 的 API /* 设置窗口参数 :9600 速率 */ voidRfid::init_ttyS(intfd) { // 声明设置串口的结构体 structtermiostermios_new; // 先清空该结构体 bzero(&termios_new,sizeof(termios_new)); //cfmakeraw() 设置终端属性,就是设置 termios 结构中的各个参数。 cfmakeraw(&termios_new); // 设置波特率 //termios_new.c_cflag=(B9600); cfsetispeed(&termios_new,B9600); cfsetospeed(&termios_new,B9600); //CLOCAL 和 CREAD 分别用于本地连接和接受使能,因此,首先要通过位 掩码的方式激活这两个选项。 termios_new.c_cflag|=CLOCAL|CREAD; // 通过掩码设置数据位为 8 位 termios_new.c_cflag&=~CSIZE; termios_new.c_cflag|=CS8; // 设置无奇偶校验 termios_new.c_cflag&=~PARENB; // 一位停止位 termios_new.c_cflag&=~CSTOPB; tcflush(fd,TCIFLUSH); // 可设置接收字符和等待时间,无特殊要求可以将其设置为 0 termios_new.c_cc[VTIME]=10; termios_new.c_cc[VMIN]=1; // 用于清空输入 / 输出缓冲区 tcflush(fd,TCIFLUSH); // 完成配置后,可以使用以下函数激活串口设置 if(tcsetattr(fd,TCSANOW,&termios_new)) printf("Settingtheserial1failed!n"); } /* 计算校验和 */ unsignedcharRfid::CalBCCS(unsignedchar*buf,intn) { inti; unsignedcharbcc=0; for(i=0;i { bcc^=*(buf+i); } return(~bcc); } /* 请求天线范围内的卡 */ intRfid::PiccRequestS(intfd) { unsignedcharWBuf[128],RBuf[128]; intret; fd_setrdfd; memset(WBuf,0,128); memset(RBuf,1,128); WBuf[0]=0x07;// 帧长 =7Byte WBuf[1]=0x02;// 包号 =0, 命令类型 =0x01 WBuf[2]=0x41;// 命令 ='C' WBuf[3]=0x01;// 信息长度 =0 WBuf[4]=0x52;// 请求模式 :ALL=0x52 WBuf[5]=CalBCCS(WBuf,WBuf[0]-2);// 校验和 WBuf[6]=0x03;// 结束标志 FD_ZERO(&rdfd); FD_SET(fd,&rdfd); write(fd,WBuf,7);; ret=select(fd+1,&rdfd,NULL,NULL,&timeout); switch(ret) { case-1: perror("selecterrorn"); break; case0: printf("Requesttimedout.n"); break; default: ret=read(fd,RBuf,8); if(ret<0) { //printf("ret=%d,%mn",ret,errno);q break; } if(RBuf[2]==0x00)// 应答帧状态部分为 0 则请求成功 { return0; } break; } return-1; } /* 防碰撞,获取范围内最大 ID*/ intRfid::PiccAnticollS(intfd) { unsignedcharWBuf[128],RBuf[128]; intret; fd_setrdfd;; memset(WBuf,0,128); memset(RBuf,0,128); WBuf[0]=0x08;// 帧长 =8Byte WBuf[1]=0x02;// 包号 =0, 命令类型 =0x01 WBuf[2]=0x42;// 命令 ='B' WBuf[3]=0x02;// 信息长度 =2 WBuf[4]=0x93;// 防碰撞 0x93-- 一级防碰撞 WBuf[5]=0x00;// 位计数 0 WBuf[6]=CalBCCS(WBuf,WBuf[0]-2);// 校验和 WBuf[7]=0x03;// 结束标志 FD_ZERO(&rdfd); FD_SET(fd,&rdfd); write(fd,WBuf,8); ret=select(fd+1,&rdfd,NULL,NULL,&timeout); switch(ret) { case-1: perror("selecterrorn"); break; case0: perror("Timeout:"); break; default: ret=read(fd,RBuf,10); if(ret<0) { //printf("ret=%d,%mn",ret,errno); break; } if(RBuf[2]==0x00)// 应答帧状态部分为 0 则获取 ID 成功 { cardidS=(RBuf[4]<<24)|(RBuf[5]<<16)|(RBuf[6]<<8)|RBuf[7]; return0; } } return-1; } QStringRfid::readCardID() { /*intret,i;*/ intfd; fd=open(DEV_RFID,O_RDWR|O_NOCTTY|O_NONBLOCK); if(fd<0) { fprintf(stderr,"open/dev/ttySAC1fail!n"); return"error"; } /* 初始化串口 */ init_ttyS(fd); _sec=1; _usec=0; /* 请求天线范围的卡 */ if(PiccRequestS(fd)) { printf("Therequestfailed!n"); ::close(fd); return"error"; } /* 进行防碰撞,获取天线范围内最大的 ID*/ if(PiccAnticollS(fd)) { printf("Couldn'tgetcard-id!n"); ::close(fd); return"error"; } printf("cardID=%xn",cardidS); ::close(fd); returnQString::number(cardidS,16); } 因此我们直接在 pushbutton_card 的槽函数直接去获得 ID 号,再显示于 lineedit 上; voidRfid::on_pushButton_card_clicked() { QStringcardid; sleep(2); cardid=readCardID(); ui->lineEdit->setText(cardid); } 到这里可以编译运行 提示:这个 RFID 模块用到的是串口 1 。开发板必须和智能家居板通过杜邦线连 接串口 1. 第六章报警模块 智能家居报警模块有两种分类, 1 是当烟雾浓度超过警戒值的火警报警, 2 是当 有红外监测到有人情况的防盗报警。这个模块涉及到的驱动有三个,烟雾传感器, 红外传感器和蜂鸣器,蜂鸣器是一个执行器,也就是需要提醒用户的时候鸣叫。 那么下面就开始: 6.1创建工程 6.1.1创建工程目录 mkdir/home/example/alarm cd/home/example/alarm 6.1.2 创建工程 6.2界面设计 添加前缀和添加文件: 和之前的几个模块来比较,这里不同的地方在于这里需要用到两个界面类,因为 在控制报警这里是一个类,另一个是报警进行时弹出的一个窗口。 首先我们先对着控制界面进行设计,这里就不详细讲,不明之处请参考前面界面 设计: 下面继续新建一个类 mdialog: 进去 文件后进行一系列的设计,可自行设计,这里用到的界面大小是, 设计完之后是这样的: 6.3源码实现 #ifndefALARM_H #defineALARM_H #include #include #include #include"mdialog.h" namespaceUi{ classAlarm; } classAlarm:publicQMainWindow { Q_OBJECT public: explicitAlarm(QWidget*parent=0); ~Alarm(); privateslots: voidon_pushButton_alarm_clicked();// 开关控制按钮 voidtimeroutslot();// 定时器槽函数,轮巡红外和烟雾到 状态 voidsetonhere(int);// 弹出窗口发过来到信号 public: voidshow_alarm_dialog(QStringmode);// 判断是烟雾还是红外 voidalarmMonitor();// 实时读取状态到函数 voidInitAllDev();// 打开所有用到的设备 private: Ui::Alarm*ui; boolonoff; boolAlarmFlag;// 报警功能开关标志 QTimer*ONtimer; mdialog*show_dialog;// 弹出窗口 }; #endif//ALARM_H 源码 #include"alarm.h" #include"ui_alarm.h" #include #include intgasfd; inthwfd; intbeepfd; Alarm::Alarm(QWidget*parent): QMainWindow(parent), ui(newUi::Alarm) { ui->setupUi(this); setWindowFlags(Qt::FramelessWindowHint); AlarmFlag=false; onoff=true; ONtimer=newQTimer; connect(ONtimer,SIGNAL(timeout()),this,SLOT(timeroutslot())); InitAllDev(); ONtimer->start(1000); show_dialog=NULL; } Alarm::~Alarm() { ::close(gasfd); ::close(hwfd); ::close(beepfd); deleteui; } voidAlarm::on_pushButton_alarm_clicked() { if(onoff) { AlarmFlag=true; ui->pushButton_alarm->setIcon(QIcon(":/images/alarm_")); } else { AlarmFlag=false; ui->pushButton_alarm->setIcon(QIcon(":/images/alarm_")); } onoff=!onoff; } voidAlarm::InitAllDev() { if((gasfd=open("/dev/gas",O_RDWR))<0) { qDebug(""); return; } if((hwfd=open("/dev/infrared",O_RDWR))<0) { qDebug(":"); return; // 烟雾 // 红外 } if((beepfd=open("/dev/pwm",O_RDWR))<0) // 蜂鸣器 { qDebug(""); return; } } voidAlarm::timeroutslot() { if(!AlarmFlag) alarmMonitor(); } voidAlarm::alarmMonitor() { inthwbye,hwbuf; intgasbye,gasbuf; gasbye=read(gasfd,&gasbuf,sizeof(gasbuf)); qDebug()<<"gas="< if(gasbuf==16) { qDebug(""); ioctl(beepfd,1,1000);// 控制蜂鸣器 /* 显示是否暂时取消警报对话框 */ if(show_dialog==NULL) { QStringtmp="fire"; show_alarm_dialog(tmp);// 显示火警警告窗体 } } hwbye=read(hwfd,&hwbuf,sizeof(hwbuf)); qDebug()<<"hwbye="< if(hwbuf==0)// 报警处理 ( 控制蜂鸣器,发送短信 ) { ioctl(beepfd,1,1000); /* 显示是否暂时取消警报对话框 */ if(show_dialog==NULL) { QStringtmp="hw"; show_alarm_dialog(tmp);// 显示红外警告窗体 } } } /************************************************** ************* 显示和关闭警报窗口 ********************* **************************************************/ voidAlarm::show_alarm_dialog(QStringmode) { show_dialog=newmdialog(this); connect(show_dialog,SIGNAL(sig_toalarm(int)),this,SLOT(setonhere(int))); if(mode=="fire") { show_dialog->setStyleSheet("#frame{border-image: url(:/images/fireAlarm_dialog_)}"); } else { show_dialog->setStyleSheet("#frame{border-image: url(:/images/infrared_dialog_)}"); } show_dialog->setGeometry(QRect(200,100,400,300)); show_dialog->show(); } voidAlarm::setonhere(intindex) { switch(index) { case2: onoff=false; AlarmFlag=true; ui->pushButton_alarm->setIcon(QIcon(":/images/alarm_")); break; } show_dialog=NULL; } 源码 #include"mdialog.h" #include"ui_mdialog.h" #include #include externintbeepfd; mdialog::mdialog(QWidget*parent): QWidget(parent), ui(newUi::mdialog) { ui->setupUi(this); setWindowFlags(Qt::FramelessWindowHint); } mdialog::~mdialog() { deleteui; } voidmdialog::on_pushButton_stop_clicked() { ioctl(beepfd,0); emitsig_toalarm(1); parentWidget()->show(); deletethis; } voidmdialog::on_pushButton_off_clicked() { ioctl(beepfd,0); emitsig_toalarm(2); parentWidget()->show(); deletethis; } 6.4驱动实现 烟雾传感器源码 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #defineDEVICE_NAME"gas" //XEINT16/KP_COL0/GPH2_0 staticintinterrup=1; staticintirq; staticirqreturn_tirq_handler(intirq,void*dev_id) { printk(""); interrup=16; returnIRQ_HANDLED; } staticintgas_open(structinode*inode,structfile*file) { return0; } staticssize_tgas_read(structfile*file,char__user*buf, size_tconstcount,loff_t*offset) { unsignedlongerr; if(copy_to_user((void*)buf,&interrup,min(sizeof(interrup),count))) { printk("copy_"); } //printk("err=%ldn",err); interrup=1; returnerr?-EFAULT:min(sizeof(interrup),count); } staticstructfile_operationsgec210_gas_dev_fops={ .owner=THIS_MODULE, .read=gas_read, .open=gas_open, }; staticstructmiscdevicegec210_gas_dev={ .minor=MISC_DYNAMIC_MINOR, .name=DEVICE_NAME, .fops=&gec210_gas_dev_fops, }; staticint__initgec210_gas_dev_init(void){ intret; interr=0; s3c_gpio_cfgpin(S5PV210_GPH2(0),S3C_GPIO_SFN(0XF)); gpio_set_value(S5PV210_GPH2(0),1); s3c_gpio_setpull(S5PV210_GPH2(0),S3C_GPIO_PULL_NONE); irq=gpio_to_irq(S5PV210_GPH2(0)); err=request_irq(irq,irq_handler,IRQ_TYPE_EDGE_BOTH,DEVICE_NAME, NULL); if(err){ printk("requestirq%dfailedforinfrared,%dn",irq,err); return-1; } ret=misc_register(&gec210_gas_dev); printk(DEVICE_NAME"tinitializedn"); returnret; } staticvoid__exitgec210_gas_dev_exit(void){ free_irq(irq,NULL); misc_deregister(&gec210_gas_dev); } module_init(gec210_gas_dev_init); module_exit(gec210_gas_dev_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("GecLab."); 红外传感器: #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #defineDEVICE_NAME"infrared" //XEINT0/GPH0_0 volatileintinterrup=1; staticintirq; staticirqreturn_tirq_handler(intirq,void*dev_id) { printk(""); interrup=0; printk("iqr=%dn",irq); returnIRQ_HANDLED; } staticintinfrared_open(structinode*inode,structfile*file) { return0; } staticssize_tinfrared_read(structfile*file,char__user*buf, size_tconstcount,loff_t*offset) { unsignedlongerr; err=copy_to_user((void*)buf,&interrup,sizeof(interrup)); //printk("err=%ldn",err); if(err) { printk("copyfromuserfailn"); return-EFAULT; } interrup=1; returnerr?-EFAULT:min(sizeof(interrup),count); } staticstructfile_operationsgec210_infrared_dev_fops={ .owner=THIS_MODULE, .read=infrared_read, .open=infrared_open, }; staticstructmiscdevicegec210_infrared_dev={ .minor=MISC_DYNAMIC_MINOR, .name=DEVICE_NAME, .fops=&gec210_infrared_dev_fops, }; staticint__initgec210_infrared_dev_init(void){ intret; interr=0; s3c_gpio_cfgpin(S5PV210_GPH0(0),S3C_GPIO_SFN(0XF)); gpio_set_value(S5PV210_GPH0(0),0); s3c_gpio_setpull(S5PV210_GPH0(0),S3C_GPIO_PULL_NONE); set_irq_type(IRQ_EINT0,IRQ_TYPE_EDGE_FALLING); err=request_irq(IRQ_EINT0,irq_handler,IRQ_TYPE_EDGE_FALLING, DEVICE_NAME,NULL);//EINT0 注册 if(err) { printk("requestirq%dfailedforinfrared,%dn",irq,err); return-EBUSY; } //irq=gpio_to_irq(S5PV210_GPH0(0)); /*err=request_irq(irq,irq_handler,IRQ_TYPE_EDGE_BOTH,DEVICE_NAME, NULL); if(err){ printk("requestirq%dfailedforinfrared,%dn",irq,err); return-1; }*/ ret=misc_register(&gec210_infrared_dev); printk(DEVICE_NAME"tinitializedn"); returnret; } staticvoid__exitgec210_infrared_dev_exit(void){ free_irq(IRQ_EINT0,NULL); misc_deregister(&gec210_infrared_dev); } module_init(gec210_infrared_dev_init); module_exit(gec210_infrared_dev_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("GecLab."); 至于蜂鸣器驱动已经编译进去内核,不用我们加载了。按照前面编译驱动的方法, 编译出来的 .ko 文件,在开发板上执行命令 insmod 驱动模块 .ko 则可以自动生成 设备节点,就可以运行我们的 Qt 程序了。 第七章 GPRS 模块 智能家居有一个GPRS模块,我们这一章开始学习如何设计GPRS的界面, 那么现在我们就开始这段旅程吧。 7.1.1创建工程目录 mkdir/home/example/gprs cd/home/example/gprs 7.1.2 创建工程 至于界面设计方面,这里就做讲解,不明之处请参考前面部分文档,可以参考下 面设计做: 这个模块我们设计的方案,一开始进来之后要设置发送报警信息对象,也就是在 软键盘上输入号码之后并且确定。在此之后,我们先测试一下 GPRS 模块,也就 是点击一下 GPRS 那个控件,这操作会像你设置的号码手机发送一条短信息,内 容是: Thisisatestmessage! 7.1.3源码实现 软件盘设计可以用到一个QButtonGroup来管理控件,这样可以多个控件信号链 接到一个槽函数,避免代码过于冗余; QButtonGroup*numbergroup=newQButtonGroup; numbergroup->addButton(ui->pushButton_1,1); numbergroup->addButton(ui->pushButton_2,2); numbergroup->addButton(ui->pushButton_3,3); numbergroup->addButton(ui->pushButton_4,4); numbergroup->addButton(ui->pushButton_5,5); numbergroup->addButton(ui->pushButton_6,6); numbergroup->addButton(ui->pushButton_7,7); numbergroup->addButton(ui->pushButton_8,8); numbergroup->addButton(ui->pushButton_9,9); numbergroup->addButton(ui->pushButton_0,0); numbergroup->addButton(ui->pushButton_c,10); connect(numbergroup,SIGNAL(buttonClicked(int)),this,SLOT(AllButtonSlot(int))); voidgprs::AllButtonSlot(intid) { //槽函数 str=ui->lineEdit->text(); switch(id) { case0: str+="0"; break; case1: str+="1"; break; case2: str+="2"; break; case3: str+="3"; break; case4: str+="4"; break; case5: str+="5"; break; case6: str+="6"; break; case7: str+="7"; break; case8: str+="8"; break; case9: str+="9"; break; case10: str=(()-1); break; default: break; } ui->lineEdit->setText(str); } 当然这里最重要的部分代码是对 GPRS 模块的操作,智能家居实验板里用到的 GPRS 模块是通过串口 2 通信,因此注意要用杜邦线连接 J10 和开发板的串口 2 。 因此首先要初始化串口: voidinit_ttys2(intfd) { structtermiostermios_new; bzero(&termios_new,sizeof(termios_new)); cfmakeraw(&termios_new); termios_new.c_cflag=(B9600); termios_new.c_cflag|=CLOCAL|CREAD; termios_new.c_cflag&=~CSIZE; termios_new.c_cflag|=CS8; termios_new.c_cflag&=~PARENB; termios_new.c_cflag&=~CSTOPB; tcflush(fd,TCIFLUSH); termios_new.c_cc[VTIME]=0; termios_new.c_cc[VMIN]=0; tcflush(fd,TCIFLUSH); tcsetattr(fd,TCSANOW,&termios_new); } 因为我们这里用到的仅仅是发送短信息的接口,所以我们封装了一个发短信的接 口: intsendmessage(unsignedchar*num,unsignedchar*messge) { intfd; unsignedcharWBuf[128],RBuf[128]; unsignedcharmessage[140]; char*mes_mode="AT+CMGF=1xd0"; char*mes_sdms="AT+CMGS=""; char*mes_cend=""xd0"; char*mes_end="x1ax0dx0a"; strcpy((char*)message,(char*)messge); fd=open(DEV_PATH,O_RDWR|O_NOCTTY|O_NDELAY); if(-1==fd){ //perror("Can'tOpenSerialPort"); } init_ttys2(fd); memset(WBuf,0,128); memset(RBuf,0,128); write(fd,mes_mode,strlen(mes_mode)); usleep(200000); write(fd,mes_sdms,strlen(mes_sdms)); write(fd,num,strlen((char*)num)); write(fd,mes_cend,strlen(mes_cend)); usleep(200000); write(fd,messge,strlen((char*)messge)); write(fd,mes_end,strlen(mes_end)); printf("phonetestend"); close(fd); return1; } 此处涉及到的 AT 指令,也就是红色字体。需要参考一下 AT 指令资料。当设置 好信息发送对象的号码之后,我们就要点击发送信息的控件 pushButton_test : voidgprs::on_pushButton_test_clicked() { QStringnumber=ui->label->text(); QByteArrayba=n1(); char*numberstr=(); sendmessage((unsignedchar*)numberstr,(unsignedchar*)"Thisisatest message!"); qDebug()<<"sendok"; } 那么到现在我们就实现了发送短信的一个小模块。
版权声明:本文标题:GEC210-智能家居项目教程(PDF 69页) 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://roclinux.cn/p/1735131710a1638914.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论