自己架设服务器内网穿透之二:相关产品介绍
上次《自己架设服务器内网穿透之一:问题缘起》讲到为了实现自建服务器,需要解决“内网IP”不能由外网访问的问题。对于非专业人士,使用第三方软件(或硬件)是最便捷的方式,下面我们就对此做个简单的探讨。
一、第三方软件(或硬件)的技术大体分为两种类型:
1、虚拟专用网络(VPN)
虚拟专用网络VPN技术的存在已经很久了,它并不是为了解决内网IP的问题而设计的(当初主要是为了解决网络安全的问题),用这套技术,可以在公网上虚拟地建立自己的“专网”,使互联网上遥远的两个局域网互联,终端之间可以用“内网IP”互访。发现了吧?这个东东里有我们想要的功能。具体的做法就是让服务器和客户机共同加入一个虚拟专网,这样大家就像处在一个本地的局域网中了,就可以用该“局域网”中的内网IP互联了。
基于这种技术,产生了一系列的第三方产品。它的优点就是直接互联,速度快。没有服务器转发,不受制于服务器带宽的限制,对服务器的压力非常轻,成本很低,这样就有可能做成免费的产品。缺点也很明显,互联前大家都需要加入虚拟专网,所以不仅服务器端要安装相关的软件,客户机上也要安装VPN软件。而且,现在政策上对VPN的管控越来越严了。
2、反向 SSH 隧道
SSH也是一个旨在解决网络安全性的一个协议,本文也不深入探讨,只要知道它也有我们想要的东西就行了。一般地,内网的电脑是可以自由的访问到外网的,而外网访问不了内网的电脑,所以才有了这篇文章。SSH协议有一个功能可以被我们利用,先是由内网电脑访问到外网一台有外网IP的服务器,并与它建立安全地联接,这样它们之间就存在了一条安全的“隧道”,在一段时间内,服务器被允许通过这个隧道访问到内网的客户机。
你看,是不是有了我们想要的东西?虽然有两个限制:一是得先由内网访问外网的服务器,二是隧道只是在一段时间内有效。但是我们可以用软件来完成这两项工作,在内网电脑安装一个软件,让它一开机就访问外网服务器并建立隧道,并且每隔一段时间就联接一下以免隧道被关闭,这样我们就有了一条从外网访问内网的通道了。以后,其它人想访问内网电脑时,就直接访问外网这台服务器就可以了,因为从这里可以经隧道到达内网电脑,而外网这台服务器是有外网IP的。
当这一切设置好了以后,你告诉想访问内网电脑的用户这个外网服务器的IP就可以了,他们就可以顺利地访问到内网电脑了,中间发生了什么用户并不知道,这就是SSH隧道最大的优点,它只需要在服务器端配置好相关软件就行了,客户端(用户端)不需要做任何的设置。而最大的缺点是,所有的访问都需要经过外网服务器的中转,需要占用它的带宽、CPU时间,对外网服务器压力很大,成本较高。所以,这种方式的穿透产品不太可能大量地免费。
二、市面上常见的穿透产品简介
其实这类产品挺多的,以下仅限于我的见识,简单说几个我知道的,相关意见仅供参考。
1、花生壳
这一家公司做得很专业,历史也悠久,产品线很全面,基本上相关的需求都有解决方案。缺点:贵。
我们最关注的产品就是“花生壳”,它应该属于SSH 隧道类产品,用户端不需要做任何设置,他们提供一个XXX.oray.com之类的域名,使用很方便。只需要在内网电脑上安装花生壳客户端软件,做好相应的设置就可以了。他们还有一个硬件“花生棒”,就插在内网电脑的网线上就行了,不用做任何设置,因为参数都写在这个硬件中了。这类硬件其实就是一个单片机,把相关的程序写进去了,与软件的功能是一样的,就是不用安装、不用设置,傻瓜化,使用方便。
提供一个免费版,1M带宽,每月1G流量,没有使用时间的限制,但是我记得之彰好像需要去“抢”,现在是申请开通。个人玩家可以试一下,商业用户还是老老实实用一个付费版,推荐每年898元的商业版。
2、蒲公英
与花生壳是同一家公司,采用的是VPN技术另一款产品。前面说过,这种方式就是把大家组到一个虚拟局域网中,不需要服务器转发,速度快。缺点:服务器电脑、用户端都需要安装专用软件。
提供一个免费版,声称不限速,但实际受到DDNS转发的速度限制、免费版客户端数量、设备数量上限3个,用户量小于3个,且用户终端方便安装软件的,推荐使用这个。它也提供了相关硬件产品,插在内网电脑所在的局域网中,做好相关设置就可以了,但用户终端还是需要安装软件的。企业版客户端成员98元/年,路由器成员228元/年。
3、零遁建站宝
像是一家新公司,今年我才知道他们。这款建站宝(也叫零遁内网穿透盒)应该是基于SSH技术的产品(可以对应“花生壳”)。它们只有硬件产品,插在内网电脑所在的局域网中,在他们提供的后台上设置好就可以了,用户端不用安装软件,也可以提供一个类似花生壳的动态域名。我还专门买了一个回来测试:
硬件299元,基础版免费帐号,声称2M带宽,2个端口映射,不限流量,不限终端数,实际测试上传速度(向服务器传一个大文件)大约就是2M。对比花生壳,最大的亮点就是“不限流量”,很多用过花生壳的客户经常会因为这个被迫升级更贵的花生壳。个人觉得值得推荐,若觉得这个免费版不够用,付费版也比花生壳便宜一些。
但最重要的担心是,这是一家新公司,这是一款基于服务器转发的产品,这种不限流量的政策能持续多久?别哪天突然中止服务,或者突然加了限制,那就不划算了。
4、零遁NAS伴侣
与上面是同一家公司,采购VPN技术的另一款产品,应该是他们公司的主打产品(可以对应“蒲公英”)。只有硬件产品,基于VPN技术,不限速度、不限设备数。有两种工作模式:1、路由器模式为虚拟局域网,可以实现虚拟网段下所有设备互访;2、映射模式为映射虚拟局域网内某个设备的某个端口,仅能单向访问。也买了一个回来测试:
硬件299元,很小的一个盒子,安装也很方便,而且没有后期费用,官方宣称帐号完全免费,只收硬件一次性费。在复杂网络环境下实测功能正常,上传速度最高达到5M,比上面的建站宝强多了,反正,做测试的黎工对它大加赞赏。说缺点:用户端需要安装软件,而且目前仅支持PC端和安卓端,没有苹果端。前面的“蒲公英”也存在同样的问题。
最后总结一下:
两家公司,各有两种产品,分别基于VPN和SSH。一家大、贵、限制多;一家新、便宜、限制少。我个人倾向于SSH类产品,因为用户端不用装软件,使用起来很自然,黎工倾向于VPN,因为不限流量、速度快,大家可以根据自己的实际情况和喜好来选择。
(以上意见仅代表个人观点,仅供参考)
基于红外通信的单片机综合编程控制技术实现遥控密码锁功能
一、设计的目的及意义
1.1、设计的现状及背景
在日常的生活和工作中, 住宅与部门的安全防范、单位的文件档案、财务报表以及一些个人资料的保存多以加锁的办法来解决。若使用传统的机械式钥匙开锁,人们常需携带多把钥匙, 使用极不方便, 且钥匙丢失后安全性即大打折扣。随着科学技术的不断发展,人们对日常生活中的安全保险器件的要求越来越高。为满足人们对锁的使用要求,增加其安全性,用密码代替钥匙的密码锁应运而生。密码锁具有安全性高、成本低、功耗低、易操作等优点。
在安全技术防范领域,具有防盗报警功能的电子密码锁逐渐代替传统的机械式密码锁,克服了机械式密码锁密码量少、安全性能差的缺点,使密码锁无论在技术上还是在性能上都大大提高一步。随着大规模集成电路技术的发展,特别是单片机的问世,出现了带微处理器的智能密码锁,它除具有电子密码锁的功能外,还引入了智能化管理、专家分析系统等功能,从而使密码锁具有很高的安全性、可靠性,应用日益广泛。
随着人们对安全的重视和科技的发展,许多电子智能锁(指纹识别、IC卡辨认)已在国内外相继面世。但是这些产品的特点是针对特定的指纹和有效卡,只能适用于保密要求的箱、柜、门等。而且指纹识识别器若在公共场所使用存在容易机械损坏,IC卡还存在容易丢失、损坏等特点。加上其成本较高,一定程度上限制了这类产品的普及和推广。鉴于目前的技术水平与市场的接收程度,电子密码锁是这类电子防盗产品的主流。红外遥控是单工的红外通信方式,本设计的红外遥控采用以通信方式为基础的红外遥控,而且本设计也使用了红外通信技术,故着重分析红外通信的基本原理。
红外通信是利用红外技术实现两点间的近距离保密通信和信息转发。它一般由红外发射和接收系统两部分组成。发射系统对一个红外辐射源进行调制后发射红外信号,而接收系统用光学装置和红外探测器进行接收,就构成红外通信系统。但是接触式密码锁系统都相应的存在着不同的缺点。例如:接触式密码锁系统成本较低,体积小,卡片本身无须电源,但使用不太方便,而且有接触磨损。相比之下,红外遥控密码锁系统的成本与接触式密码锁系统相当,而且可以进行近距离遥控,使用十分方便。而且它已经与 PC 机的数据库相结合,可以组成一套酒店房间的门禁管理系统。 由于红外遥控具有许多优点, 例如红外线发射装置采用红外发光二极管遥控发射器易于小型化且价格低廉; 采用数字信号编码和二次调制方式,不仅可以实现多路信息的控制,增加遥控功能,提高信号传输的抗干扰性,减少误动作,而且功率消耗低;红外线不会向室外泄露,不会产生信号串扰;反应速度快、传输效率高、工作稳定可靠等。工业设备中,在高压、辐射、有毒气体、粉尘等环境下,采用红外线遥控不仅完全可靠而且能有效地隔离电气干扰。所以红外线遥控是目前使用最广泛的一种通信和遥控手段。
1.2、设计的目的
在科技高速发展的今天,非接触式控制越来越受大家欢迎,利用红外遥控,方便又安全。另外,红外线不会产生信号干扰,反应速度迅速、工作稳定度高等特点。而在工业制造中,在高压、辐射、腐蚀等恶劣环境下,采用红外遥控能够很好地隔离这些干扰。在本次设计中,为了更加方便操作,除了采用矩阵键盘对密码锁进行控制外,还可以用遥控器进行控制,以达到双控的目的。可以加深自己对所学专业的认识,关联知识,增强自己的动手能力,积累实践经验,为以后的工作打好基础。
1.3、设计的意义
随着科技的发展,人们生活的节奏也越来越快,随之人们对方便,快捷的要求也随之不断增高。遥控器的出现,在一定程度上满足了人们这个要求。遥控器是由高产的发明家Robert Adler在五十年代发明的[1]。而红外遥控是20世纪70年代才开始发展起来的一种远程控制技术,其原理是利用红外线来传递控制信号,实现对控制对象的远距离控制,具体来讲,就是有发射器发出红外线指令信号,有接收器接收下来并对信号进行处理,最后实现对控制对象的各种功能的远程控制。
红外遥控具有独立性、物理特性与可见光相似性、无穿透障碍物的能力及较强的隐蔽性等特点。随着红外遥控技术的开发和迅速发展,很多电器都应用了红外遥控,在日常的生活和工作中, 住宅与部门的安全防范、单位的文件档案、财务报表以及一些个人资料的保存多以加锁的办法来解决。若使用传统的机械式钥匙开锁,人们常需携带多把钥匙, 使用极不方便, 且钥匙丢失后安全性即大打折扣。随着科学技术的不断发展,人们对日常生活中的安全保险器件的要求越来越高。为满足人们对锁的使用要求,增加其安全性,用密码代替钥匙的密码锁应运而生。密码锁具有安全性高、成本低、功耗低、易操作等优点。 在安全技术防范领域,具有防盗报警功能的电子密码锁逐渐代替传统的机械式密码锁,克服了机械式密码锁密码量少、安全性能差的缺点,使密码锁无论在技术上还是在性能上都大大提高一步。随着大规模集成电路技术的发展,特别是单片机的问世,出现了带微处理器的智能密码锁,它除具有电子密码锁的功能外,还引入了智能化管理、专家分析系统等功能,从而使密码锁具有很高的安全性、可靠性,应用日益广泛。
二、主要器件介绍
系统主要有STC89C52RC单片机最小系统和LCD1602液晶显示、数据存储芯片24C02、红外发射接收模块等组成。
2.1、主控器件
本设计是STC89C52RC单片机为控制核心,矩阵键盘输入,红外遥控输入基于红外通信的单片机控制技术综合实现所有功能。系统框图如下图:
单片机是STC公司最新推出的一种新型51内核的单片机。片内含有Flash程序存储器、SRAM、UART、SPI、PWM等模块。封装图如下图:
2.1.1、主要特性
1. 增强型8051单片机,6时钟/机器周期和12时钟/机器周期可以任意选择,指令代码完全兼容传统8051.
2. 工作电压:5.5V~3.3V(5V单片机)/3.8V~2.0V(3V单片机)
3. 工作频率范围:0~40MHz,相当于普通8051的0~80MHz,实际工作频率可达48MHz
4. 用户应用程序空间为8K字节 5. 片上集成512字节RAM
6. 通用I/O口(32个),复位后为:P1/P2/P3/P4是准双向口/弱上拉,
P0口是漏极开路输出,作为总线扩展用时,不用加上拉电阻,作为I/O口用时,需加上拉电阻。
7. ISP(在系统可编程)/IAP(在应用可编程),无需专用编程器,无需专用仿真器,可通过串口(RxD/P3.0,TxD/P3.1)直接下载用户程序,数秒即可完成一片
8. 具有EEPROM功能
9. 具有看门狗功能
10. 共3个16位定时器/计数器。即定时器T0、T1、T2
11. 外部中断4路,下降沿中断或低电平触发电路,Power Down模式可由外部中断低电平触发中断方式唤醒
12. 通用异步串行口(UART),还可用定时器软件实现多个UART
13. 工作温度范围:-40~+85℃(工业级)/0~75℃(商业级)
2.1.2、引脚功能
VCC(40引脚):电源电压
VSS(20引脚):接地
P0端口(P0.0~P0.7,39~32引脚):P0口是一个漏极开路的8位双向I/O口。作为输出端口,每个引脚能驱动8个TTL负载,对端口P0写入“1”时,可以作为高阻抗输入。在访问外部程序和数据存储器时,P0口也可以提供低8位地址和8位数据的复用总线。此时,P0口内部上拉电阻有效。在Flash ROM编程时,P0端口接收指令字节;而在校验程序时,则输出指令字节。验证时要求外接上拉电阻。
P1端口(P1.0~P1.7,1~8引脚):P1口是一个带内部上拉电阻的8位双向I/O口。P1的输出缓冲器可驱动(吸收或者输出电流方式)4个TTL输入。对端口写入1时,通过内部的上拉电阻把端口拉到高电位,这是可用作输入口。P1口作输入口使用时,因为有内部上拉电阻,那些被外部拉低的引脚会输出一个电流。
P2端口(P2.0~P2.7,21~28引脚):P2口是一个带内部上拉电阻的8位双向I/O端口。P2的输出缓冲器可以驱动(吸收或输出电流方式)4个TTL输入。对端口写入1时,通过内部的上拉电阻把端口拉到高电平,这时可用作输入口。P2作为输入口使用时,因为有内部的上拉电阻,那些被外部信号拉低的引脚会输出一个电流
P3口引脚复用功能 引脚号 复用功能
P3.0 RXD(串行输入口)
P3.1 TXD(串行输出口)
P3.2 (外部中断0)
P3.3 (外部中断1)
P3.4 T0(定时器0的外部输入)
P3.5 T1(定时器1的外部输入)
P3.6 (外部数据存储器写选通)
P3.7 (外部数据存储器读选通)
RST(9引脚):复位输入。当输入连续两个机器周期以上高电平时为有效,用来完成单片机单片机的复位初始化操作。看门狗计时完成后,RST引脚输出96个晶振周期的高电平。特殊寄存器AUXR(地址8EH)上的DISRTO位可以使此功能无效。DISRTO默认状态下,复位高电平有效。
ALE/(30引脚):地址锁存控制信号(ALE)是访问外部程序存储器时,锁存低8位地址的输出脉冲。在Flash编程时,此引脚()也用作编程输入脉冲。 在一般情况下,ALE以晶振六分之一的固定频率输出脉冲,可用来作为外部定时器或时钟使用。然而,特别强调,在每次访问外部数据存储器时,ALE脉冲将会跳过。如果需要,通过将地址位8EH的SFR的第0位置“1”,ALE操作将无效。这一位置“1”,ALE仅在执行MOVX或MOV指令时有效。否则,ALE将被微弱拉高。这个ALE使能标志位(地址位8EH的SFR的第0位)的设置对微控制器处于外部执行模式下无效。
VPP(31引脚):访问外部程序存储器控制信号。为使能从0000H到FFFFH的外部程序存储器读取指令,必须接GND。注意加密方式1时,将内部锁定位RESET。为了执行内部程序指令,应该接VCC。在Flash编程期间,也接收12伏VPP电压。
XTAL1(19引脚):振荡器反相放大器和内部时钟发生电路的输入端。
XTAL2(18引脚):振荡器反相放大器的输入端。
2.1.3、串口通信
一条信息的各位数据被逐位顺序传送的通信方式成为串行通信。根据信息的传送方向,串行通信可以可以进一步划分为单工、半双工和全双工 3 种。信息只能单方向传送为单工;信息能双向传送但不能同时双向传送为半双工;信息能够同时双向传送则成为全双工。 8051 系列单片机有一个全双工串行口, 全双工的串行通信只需要一根输出线和输入线。
串行通信又有异步通信和同步通信这两种方式。异步通信用起始位“0”表示字符的开始,然后从低位到高位逐位传送数据,最后用停止位“1”表示字符结束。一个字符又称作一帧信息,一帧信息包括 1 位起始位、8 位数据位、1 位停止位,若数据位增加到第 9 位, 在 8051 系列单片机中, 第九位数据可以用作奇偶校验位, 也可以用作地址/数据帧标志。
8051 系列单片机串行 I/O 接口的工作原理就是: 当要发送数据时, 单片机自动将 SBUF 内的 8 位并行数据转换为一定格式的串行数据, 从 TXD 引脚按规定的波特率来输出; 当要接收数据时, 要监视 RXD 引脚,一旦出现起始位“0” ,按规定的波特率将外围设备送来的一定格式的串行数据转换成 8 位并行数据,等待用户读取 SBUF 寄存器,若不及时读取,SBUF 中的数据有可能被刷新。8051 系列单片机上有通用异步接收/发送器用于串行通信,发送时数据由 TXD 引脚输出,接收时数据从 RXD 引脚输入。有两个缓冲器(Serial Buffer) ,一个作发送缓冲器,另外一个作为接收缓冲器。UART 是可编程的全双工的串行口。
SBUF是可以直接寻址的专用寄存器。物理上,它对应着两个寄存器,即一个发送寄存器一个接收寄存器,CPU写SBUF就是修改发送寄存器;读SBUF就是读接收寄存器。接收器是双缓冲的,以避免在接收下一帧数据之前,CPU未能及时的响应接收器的中断,没有把上一帧的数据读走而产生两帧数据重叠的问题。对于发送器,为了保持最大的传输速率,一般不需要双缓冲,因为发送时CPU是主动的,不会产生重叠问题。
SCON是一个逐位定义的8位寄存器,用于控制串行通信的方式选择、接收和发送,指示串口的状态,SCON即可以字节寻址也可以位寻址,字节地址98H,地址位为98H~9FH。它的各个位定义如下:
SM2在工作方式2和3中是多机通信的使能位。在工作方式0中,SM2必须为0。在工作方式1中,若SM2=1且没有接收到有效的停止位,则接收中断标志位RI不会被激活。在工作方式2和3中若SM2=1且接收到的第9位数据(RB8)为0,则接收中断标志RB8不会被激活,若接收到的第9位数据(RB8)为1,则RI置位。此功能可用于多处理机通信。
REN为允许串行接收位,由软件置位或清除。置位时允许串行接收,清除时禁止串行接收。
TB8是工作方式2和3要发送的第9位数据。在许多通信协议中该位是奇偶位,可以按需要由软件置位或清除。在多处理机通信中,该位用于表示是地址帧还是数据帧。
RB8是工作方式2和3中接收到的第9位数据(例如是奇偶位或者地址/数据标识位),在工作方式1中若SM2=0,则RB8是已接收的停止位。在工作方式0中RB8不使用。
TI 为发送中断标志位,由硬件置位,软件清除。工作方式0中在发送第8位末尾由硬件置位;在其他工作方式时,在发送停止位开始时由硬件置位。TI=1时,申请中断。CPU响应中断后,发送下一帧数据。在任何工作方式中都必须由软件清除TI。
RI为接收中断标志位,由硬件置位,软件清除。工作方式0中在接收第8位末尾由硬件置位;在其他工作方式时,在接收停止位的中间由硬件置位。RI=1时,申请中断,要求CPU取走数据。但在工作方式1中,SM2=1且未接收到有效的停止位时,不会对RI置位。
在任何工作方式中都必须由软件清除RI。
系统复位时,SCON的所有位都被清除。
(1) 工作方式0
SM0=0且SM1=0时,串口选择工作方式0,实质这是一种同步移位寄存器模式。其数据传输的波特率固定为Fosc/12,数据由RXD引脚输入或输出,同步时钟由TXD引脚输出。接收/发送的是8位数据,传输是低位在前,帧格式如下:
…….. D0 D1 D2 D3 D4 D5 D6 D7 …….
(2)工作方式1
当SM0=0且SM1=1时,串口选择工作方式1,其数据传输的波特率由定时/计数器T1、T2的溢出速率决定,可通过程序设定。当T2CON寄存器中的RCLK和TCLK置位时,用T2作为发送和接收波特率发生器,而RCLK=TCLK=0时,用T1作为波特率发生器,两者还可以交叉使用,即发送和接收采用不同的波特率。数据由TXD引脚发送,由RXD引脚接收。发送或接收一帧的数据为10位,即1位起始位(0)、8位数据位(低位在先)和1位停止位(1)。帧格式如下:
起始位0 D0 D1 D2 D3 D4 D5 D6 D7 停止位1
类似于工作方式0,当执行任一条SBUF指令时,就启动串行数据的发送。在执行写入SBUF的指令时,也将“1”写入发送移位寄存器的第9位,并通知发送控制器有发送请求。实际上,发送过程始于内部的16分频计数器下次满度翻转(全“1”变全“0”)后的那几个机器周期的开始。所以,每位的发送过程与16分频计数器同步,而不是与“写SBUF”同步。
(3)方式 2 和方式 3
这两种方式都是 11 位异步接收/发送方式。他们的操作过程都是完全一样
的,所不同的是波特率而已。方式 3 波特率同方式 1(定时器 1 作为波特率时钟发生器) 。
方式 2 和方式 3 的发送起始于任何一条 SBUF 数据装载指令。当第 9 位数据(TB8)输出之后,TI 将被置位(TI=1) 。
方式 2 和方式 3 的接收数据前提条件也是 REN 被编程为 1。 在第 9 位数据接收到后, 如果下列条件同时满足,即 RI=0 且 SM2=0 或者接收到的第 9 位为 1,则将已接受的数据装入 SBUF 缓冲器和 RB8,并将RI 置位(RI=1)否则接收数据无效。
8051 串行口的不同寻常的特征是包括第 9 位方式。它允许把在串行口通信增加的第 9 位用于标志特殊字节的接收。用这种方式,一个单片机可以和大量的其他单片机对话而不打扰不寻址的单片机,这种多机通信方式必须工作在严格的主从方式,由软件进行分析。
2.2 、LCD1602的原理
2.2.1 LCD1602的概述
液晶显示的原理是利用液晶的物理特性,通过电压对其显示区域进行控制,有电就有显示。LCD1602是有32个5x7点阵组成的行字符型显示屏。其操作方法如下:读写时序操作
读状态RS=L,R/W=H,E=H输出D0—D7
写指令RS=L,R/W=L,D0—D7指令码,E=高脉冲
读数据RS=H,R/W=H,E=H输出D0—D7数据
写数据RS=H,R/W=L,D0—D7数据,E=高脉冲
2.2.2LCD1602的操作时序
写操作时序图
2.2.3 LCD1602的基本命令
1、RAM地址映射图
2、指令码
1602液晶模块内部的控制器共有11条控制指令,如表10-14所示:
指令1:清显示,指令码01H,光标复位到地址00H位置。指令2:光标复位,光标返回到地址00H。
指令3:光标和显示模式设置I/D:光标移动方向,高电平右移,低电平左移S:屏幕上所有文字是否左移或者右移。高电平表示有效,低电平则无效。
指令4:显示开关控制。D:控制整体显示的开与关,高电平表示开显示,低电平表示关显示C:控制光标的开与关,高电平表示有光标,低电平表示无光标B:控制光标是否闪烁,高电平闪烁,低电平不闪烁。
指令5:光标或显示移位S/C:高电平时移动显示的文字,低电平时移动光标。
指令6:功能设置命令DL:高电平时为4位总线,低电平时为8位总线N:低电平时为单行显示,高电平时双行显示F:低电平时显示5x7的点阵字符,高电平时显示5x10的点阵字符。指令7:字符发生器RAM地址设置。
指令8:DDRAM地址设置。
指令9:读忙信号和光标地址BF:为忙标志位,高电平表示忙,此时模块不能接收命令或者数据,如果为低电平表示不忙。
指令10:写数据。
指令11:读数据。
2.3、红外一体化接收头
2.3.1红外一体化接收头的概述
红外遥控信号是一连串的二进制脉冲码。为了使其在无线传输过程中免受其他红外信号的干扰,通常都是先将其调制在特定的载波频率上,然后再经红外发射二极管发射出去,而红外线接收装置则要滤除其他杂波,只接收该特定频率的信号并将其还原成二进制脉冲码,也就是解调.
目前,对于这种进行了调制的红外遥控信号,通常是采用一体化红外线接收头进行调解.一体化红外线接收头将低噪音放大器,限幅器,带通滤波器,解调器,,以及整形驱动电路等集成在一起.一体化红外线接收头体积小,灵敏度高,外接元件少,抗干扰能力强,使用十分方便。
红外信号收发系统的典型电路如图1所示,红外接收电路通常被厂家集成在一个元件中,成为一体化红外接收头。 内部电路包括红外监测二极管,放大器,限幅器,带通滤波器,积分电路,比较器等。红外监测二极管监测到红外信号,然后把信号送到放大器和限幅器,限幅器把脉冲幅度控制在一定的水平,而不论红外发射器和接收器的距离远近。交流 信号进入带通滤波器,带通滤波器可以通过30khz到60khz的负载波,通过解调电路和积分电路进入比较器,比较器输出 高低电平,还原出发射端的信号波形。注意输出的高低电平和发射端是反相的,这样的目的是为了提高接收的灵敏度。
红外接收头的种类很多,引脚定义也不相同,一般都有三个引脚,包括供电脚,接地和信号输出脚。根据发射端调制 载波的不同应选用相应解调频率的接收头。
红外接收头内部放大器的增益很大,很容易引起干扰,因此在接收头的供电脚上须加上滤波电容,一般在22uf以上。 有的厂家建议在供电脚和电源之间接入330欧电阻,进一步降低电源干扰。
2.3.2红外一体化接收头的应用
红外遥控是以调制的方式发射数据,就是把数据和一定频率的载波进行“与”操作,这样既可以提高发射效率又可以降低电源 功耗。
调制载波频率一般在30khz到60khz之间,大多数使用的是38kHz,占空比1/3的方波,如图2所示,这是由发射端所使用的 455kHz晶振决定的。在发射端要对晶振进行整数分频,分频系数一般取12,所以455kHz÷12≈37.9 kHz≈38kHz。
单片机可以准备接收下面的数据。地址码由8位二进制组成,共256种.图中地址码重发了一次。主要是加强发射机的可靠性.如果两次地址码不相同.则说明本帧数据有错.应丢弃。不同的设备可以拥有不同的地址码.因此。同种编码的发射机只要设置地址码不同,也不会相互干扰。在同一个发射机中.所有按键发出的地址码都是相同的。数据码为8位,可编码256种状态,代表实际所按下的键。数据反码是数据码的各位求反,通过比较数据码与数据反码.可判断接收到的数据是否正确。如果数据码与数据反码之间的关系不满足相反的关系.则本次遥控接收有误.数据应丢弃。在同一个发射机上,所有按键的数据码均不相同。
数据格式包括了引导码、用户码、数据码和数据码反码,编码总占32位。数据反码是数据码反相后的编码,编码时可用于对数据的纠错。注意:第二段的用户码也可以在遥控应用电路中被设置成第一段用户码的反码。
用户码或数据码中的每一个位可以是位‘1’,也可以是位‘0’。区分‘0’和‘1’是利用脉冲的时间间隔来区分,这种编码方式称为脉冲位置调制方式,英文简写PPM。
以接收TC9012遥控器编码为例,解码方法如下:
设外部中断为下降沿中断,定时器0(或者1)为16位计时器.初始值均为0
(2)第一次进入遥控中断后,开始计时。
(3)从第二次进入遥控中断起,先停止计时。并将计时值保存后,再重新计时。如果计时值等于前导码的时间,设立前导码标志。准备接收下面的一帧遥控数据,如果计时值不等于前导码的时间,但前面已接收到前导码,则判断是遥控数据的0还是1。
(4)继续接收下面的地址码、数据码、数据反码。
(5)当接收到32位数据时,说明一帧数据接收完毕。此时可停止定时器的计时,并判断本次接收是否有效.如果两次地址码相同且等于本系统的地址,数据码与数据反码之和等于0FFH,则接收的本帧数据码有效。否则丢弃本次接收到的数据。
(6)接收完毕,初始化本次接收的数据,准备下一次遥控接收。
三、程序设计
红外遥控锁系统主要由单片机通过红外通信控制,当其完成红外信号,读取数据,,其数据的传输根据协议的内容,发生错误时,有单片机发出警报,超出一定次数就把键盘锁死报警。红外遥控锁系统程序需要完成以下的功能:
1、矩阵键盘,可以设置密码开锁及密码重置;
3、遥控器输入密码开锁及密码重置;
5、密码输入输入信息或密码输入错误报警及键盘锁死;
6、用1602液晶显示功能状态。
矩阵键盘设置程序流程图如下:
四、过程分享
PCB图
原理图
程序代码:
//(智能存钱管) //晶振12Mkz
//功能:该系统具有存钱取钱功能,存钱时需要输入密码 密码为000000
//密码可修改 万能密码为:131420 改密码可初始化密码为:000000 密码与存钱数有掉电保存功能
#include<reg52.h> //头文件
#include<intrins.h>
#define uchar unsigned char //宏定义
#define uint unsigned int
#define LCD1602_dat P0
uchar irbyte[4];
uchar irtime,irflag,bitnum,irdateok;
uchar irdate[33];
sbit LCD1602_rs=P1^0;
sbit LCD1602_rw=P1^1;
sbit LCD1602_e=P1^2;
sbit led=P2^0;
sbit beep=P2^7;
sbit Scl=P3^5;//24C02串行时钟
sbit Sda=P3^4;//24C02串行数据
uchar ptem,mm[6],mm_n1[6],mm_n2[6],n,j;
uchar step,ms,time,cw;
uchar zt[2];
bit cq,beep1,beep2;
void mDelay(uint t) //延时
{
uchar i;
while(t--)
{
for(i=0;i<125;i++)
{;}
}
}
void Nop(void) //空操作
{
_nop_();
_nop_();
_nop_();
_nop_();
}
/*起始条件*/
void Start(void)
{
Sda=1;
Scl=1;
Nop();
Sda=0;
Nop();
}
/*停止条件*/
void Stop(void)
{
Sda=0;
Scl=1;
Nop();
Sda=1;
Nop();
}
/*应答位*/
void Ack(void)
{
Sda=0;
Nop();
Scl=1;
Nop();
Scl=0;
}
/*反向应答位*/
void NoAck(void)
{
Sda=1;
Nop();
Scl=1;
Nop();
Scl=0;
}
/*发送数据子程序,Data为要求发送的数据*/
void Send(uchar Data)
{
uchar BitCounter=8;
uchar temp;
do
{
temp=Data;
Scl=0;
Nop();
if((temp&0x80)==0x80)
Sda=1;
else
Sda=0;
Scl=1;
temp=Data<<1;
Data=temp;
BitCounter--;
}
while(BitCounter);
Scl=0;
}
/*读一字节的数据,并返回该字节值*/
uchar Read(void)
{
uchar temp=0;
uchar temp1=0;
uchar BitCounter=8;
Sda=1;
do{
Scl=0;
Nop();
Scl=1;
Nop();
if(Sda)
temp=temp|0x01;
else
temp=temp&0xfe;
if(BitCounter-1)
{
temp1=temp<<1;
temp=temp1;
}
BitCounter--;
}
while(BitCounter);
return(temp);
}
void WrToROM(uchar Data[],uchar Address,uchar Num)
{
uchar i;
uchar *PData;
PData=Data;
for(i=0;i<Num;i++)
{
Start();
Send(0xa0);
Ack();
Send(Address+i);
Ack();
Send(*(PData+i));
Ack();
Stop();
mDelay(20);
}
}
void RdFromROM(uchar Data[],uchar Address,uchar Num)
{
uchar i;
uchar *PData;
PData=Data;
for(i=0;i<Num;i++)
{
Start();
Send(0xa0);
Ack();
Send(Address+i);
Ack();
Start();
Send(0xa1);
Ack();
*(PData+i)=Read();
Scl=0;
NoAck();
Stop();
}
}
void delay(uint T) //延时函数
{
while(T--);
}
void qing() // 清楚数据
{
uint i;
for(i=0;i<33;i++)
{
irdate[i]=0;
}
}
void deal_with() //解码处理部分
{
uchar i,j,k,temp;
k=1;
for(j=0;j<4;j++)
{
for(i=0;i<8;i++)
{
temp=temp>>1;
if(irdate[k]>7)
{
temp=temp|0x80;
}
k++;
}
irbyte[j]=temp;
}
}
void LCD1602_write(uchar order,dat) //1602 一个字节 处理
{
LCD1602_e=0;
LCD1602_rs=order;
LCD1602_dat=dat;
LCD1602_rw=0;
LCD1602_e=1;
delay(1);
LCD1602_e=0;
}
void LCD1602_writebyte(uchar *prointer) //1602 字符串 处理
{
while(*prointer!='\0')
{
LCD1602_write(1,*prointer);
prointer++;
}
}
void LCD1602_cls() //1602 初始化
{
LCD1602_write(0,0x01); //1602 清屏 指令
delay(1500);
LCD1602_write(0,0x38); // 功能设置 8位、5*7点阵
delay(1500);
LCD1602_write(0,0x0c); //设置 光标 不显示开关、不显示光标、字符不闪烁
LCD1602_write(0,0x06);
LCD1602_write(0,0xd0);
delay(1500);
}
uchar key_fs() //矩阵按键返回按码
{
uchar fs=255;
P1=0x0f;
if(P1!=0x0f)
{
delay(800);
P1=0x0f;
if(P1!=0x0f)
{
ptem=P1;
P1=0xf0;
ptem=ptem|P1;
switch (ptem)
{
case 0xe7:
fs=1;
break;
case 0xd7:
fs=2;
break;
case 0xb7:
fs=3;
break;
case 0x77:
fs=10;
break;
case 0xeb:
fs=4;
break;
case 0xdb:
fs=5;
break;
case 0xbb:
fs=6;
break;
case 0x7b:
fs=11;
break;
case 0xed:
fs=7;
break;
case 0xdd:
fs=8;
break;
case 0xbd:
fs=9;
break;
case 0x7d:
fs=12;
break;
case 0xee:
fs=13;
break;
case 0xde:
fs=0;
break;
case 0xbe:
fs=14;
break;
case 0x7e:
fs=15;
break;
}
P1=0x0f;
while(P1!=0x0f)
{
P1=0x0f;
}
}
}
return(fs);
}
void show() //显示程序
{
LCD1602_write(0,0x80);
LCD1602_writebyte("===Coded Lock===");
}
unsigned char coding_1(unsigned char m)
{
unsigned char k;
switch(m)
{
case (0x0c): k=1;break;
case (0x18): k=2;break;
case (0x5e): k=3;break;
case (0x08): k=4;break;
case (0x1c): k=5;break;
case (0x5a): k=6;break;
case (0x42): k=7;break;
case (0x52): k=8;break;
case (0x4a): k=9;break;
case (0x09): k=13;break;
case (0x16): k=0;break;
case (0x19): k=14;break;
case (0x0d): k=15;break;
case (0x07): k=12;break;
}
return(k);
}
void key() //按键键码处理程序
{
uchar fz=255,i;
if(irbyte[2]!=0)
{
fz=coding_1(irbyte[2]);
do
{
qing();
deal_with();
}while(irbyte[2]!=0);
}else
{
fz=key_fs();
}
if(fz!=255)
{
beep2=1;beep=0;
delay(10000);
beep2=0;beep=1;
}
if(step==0)
{
if(fz<10&&cq==0&&n<6)
{
if(n==0)
{
LCD1602_write(0,0xc0);
LCD1602_writebyte(" ");
LCD1602_write(0,0xc0);
LCD1602_writebyte("Pass:");
}
mm_n1[n]=fz;
n++;
LCD1602_write(0,0xc5);
for(i=0;i<n;i++)
{
LCD1602_writebyte("*");
}
}
}else if(step==1|step==2)
{
if(fz<10&&n<6)
{
mm_n1[n]=fz;
n++;
LCD1602_write(0,0xc9);
for(i=0;i<n;i++)
{
LCD1602_writebyte("*");
}
}
}else if(step==3)
{
if(fz<10&&n<6)
{
mm_n2[n]=fz;
n++;
LCD1602_write(0,0xc6);
for(i=0;i<n;i++)
{
LCD1602_writebyte("*");
}
}
}
switch(fz)
{
case 11:
break;
case 12:
if(n!=0)
{
n--;
if(step==0)
{
mm_n1[n+1]=0xff;
LCD1602_write(0,0xc5);
for(i=0;i<n;i++)
{
LCD1602_writebyte("*");
}
for(i=0;i<6-n;i++)
{
LCD1602_writebyte(" ");
}
}else if(step==1|step==2)
{
mm_n1[n+1]=0xff;
LCD1602_write(0,0xc9);
for(i=0;i<n;i++)
{
LCD1602_writebyte("*");
}
for(i=0;i<6-n;i++)
{
LCD1602_writebyte(" ");
}
}else if(step==3)
{
mm_n2[n+1]=0xff;
LCD1602_write(0,0xc6);
for(i=0;i<n;i++)
{
LCD1602_writebyte("*");
}
for(i=0;i<6-n;i++)
{
LCD1602_writebyte(" ");
}
}
}
break;
case 13:
LCD1602_write(0,0xc0);
LCD1602_writebyte(" ");
LCD1602_write(0,0xc0);
LCD1602_writebyte("Password");
step=0;
cq=0;
n=0;
led=0;
zt[0]='N';
zt[1]='O';
WrToROM(zt,10,2);
break;
case 14:
if(step==0)
{
if(n==6)
{
n=0;
for(i=0;i<6;i++)
{
if(mm[i]!=mm_n1[i])
{
break;
}
}
if(i==6)
{
LCD1602_write(0,0xc0);
LCD1602_writebyte(" ");
LCD1602_write(0,0xc5);
LCD1602_writebyte("Open");
led=1;
zt[0]='O';
zt[1]='K';
WrToROM(zt,10,2);
cq=1;
cw=0;
}else if(mm_n1[0]==1&&mm_n1[1]==3&&mm_n1[2]==1&&mm_n1[3]==4&&mm_n1[4]==2&&mm_n1[5]==0)
{
LCD1602_write(0,0xc0);
LCD1602_writebyte(" ");
LCD1602_write(0,0xc3);
LCD1602_writebyte("Pass init");
for(j=0;j<6;j++)
{
mm[j]=0;
}
cw=0;
WrToROM(mm,0,6);
}else
{
LCD1602_write(0,0xc0);
LCD1602_writebyte(" ");
LCD1602_write(0,0xc5);
LCD1602_writebyte("Error");
time=3;
cw++;
if(cw>2)
{
LCD1602_write(0,0xc0);
LCD1602_writebyte(" ");
LCD1602_write(0,0xc2);
LCD1602_writebyte("Locked state");
while(1)
{
beep1=1;
cw=3;
time=5;
}
}
}
}else
{
n=0;
LCD1602_write(0,0xc0);
LCD1602_writebyte(" ");
LCD1602_write(0,0xc5);
LCD1602_writebyte("Error");
time=3;
cw++;
if(cw>2)
{
LCD1602_write(0,0xc0);
LCD1602_writebyte(" ");
LCD1602_write(0,0xc2);
LCD1602_writebyte("Locked state");
while(1)
{
beep1=1;
cw=3;
time=5;
}
}
}
}else if(step==1)
{
if(n==6)
{
n=0;
for(i=0;i<6;i++)
{
if(mm[i]!=mm_n1[i])
{
break;
}
}
if(i==6)
{
LCD1602_write(0,0xc0);
LCD1602_writebyte(" ");
LCD1602_write(0,0xc0);
LCD1602_writebyte("New pass:");
step=2;
}else
{
step=0;
LCD1602_write(0,0xc0);
LCD1602_writebyte(" ");
LCD1602_write(0,0xc5);
LCD1602_writebyte("Error");
}
}else
{
step=0;
n=0;
LCD1602_write(0,0xc0);
LCD1602_writebyte(" ");
LCD1602_write(0,0xc5);
LCD1602_writebyte("Error");
}
}else if(step==2)
{
if(n==6)
{
n=0;
LCD1602_write(0,0xc0);
LCD1602_writebyte(" ");
LCD1602_write(0,0xc0);
LCD1602_writebyte("Again:");
step=3;
}else
{
step=0;
n=0;
LCD1602_write(0,0xc0);
LCD1602_writebyte(" ");
LCD1602_write(0,0xc5);
LCD1602_writebyte("Error");
}
}else
{
step=0;
if(n==6)
{
n=0;
for(i=0;i<6;i++)
{
if(mm_n1[i]!=mm_n2[i])
{
break;
}
}
if(i==6)
{
LCD1602_write(0,0xc0);
LCD1602_writebyte(" ");
LCD1602_write(0,0xc4);
LCD1602_writebyte("Pass OK");
for(i=0;i<6;i++)
{
mm[i]=mm_n1[i];
}
WrToROM(mm,0,6);
}else
{
LCD1602_write(0,0xc0);
LCD1602_writebyte(" ");
LCD1602_write(0,0xc5);
LCD1602_writebyte("Error");
}
}else
{
n=0;
LCD1602_write(0,0xc0);
LCD1602_writebyte(" ");
LCD1602_write(0,0xc5);
LCD1602_writebyte("Error");
}
}
break;
case 15:
step=1;
n=0;
LCD1602_write(0,0xc0);
LCD1602_writebyte(" ");
LCD1602_write(0,0xc0);
LCD1602_writebyte("Old pass:");
break;
}
}
void main() //主程序
{
TMOD=0x12;
TH0=0;
TL0=0;
TH1=0x3c;
TL1=0xb0;
EA=1;
ET0=1;
ET1=1;
TR0=1;
TR1=1;
EX0=1;
IT0=1;
LCD1602_cls();
RdFromROM(zt,10,2);
if(zt[0]=='O'&&zt[1]=='K')
{
led=1;
}else
{
led=0;
}
show();
LCD1602_write(0,0xc0);
LCD1602_writebyte("Password");
RdFromROM(mm,0,6);
while(1)
{
if(irdateok==1) //解码完成处理
{
irdateok=0;
deal_with();
}
key();
}
}
void time3_interrupt()interrupt 3
{
TH1=0x3c;
TL1=0xb0;
ms++;
if(ms%3==0)
{
if(beep2==0)
{
if(beep1==1)
{
beep=!beep;
}else
{
beep=1;
}
}
}
if(ms>19)
{
ms=0;
if(time!=0)
{
time--;
beep1=1;
}
else beep1=0;
}
}
//==================================定时器0中断函数,用于数码管扫描显示====================================
void time0_interrupt()interrupt 1
{
irtime++;
}
void int0() interrupt 0 //遥控器解码
{
if(irflag==1)
{
if(irtime>32)
{
bitnum=0;
}
irdate[bitnum]=irtime;
irtime=0;
bitnum++;
if(bitnum==33)
{
bitnum=0;
irdateok=1;
}
}
else
{
irflag=1;
irtime=0;
}
}
相关问答
哪位知道光谱仪分析X‐RAY 能否 穿透 5um 厚的 Ni 镀层?在线等[回答]光谱仪分析X射线是一种电磁波,波长比紫外线还要短,为0.001‐10nm左右。X射线照射到物质上面以后,从物质上主要可以观测到以下三种X射线。荧光X射线...
超声波液位计和雷达液位计的区别有哪些?超声波液位计这种仪表利用了声波在不同介质传播时的衰减、穿透能力、声阻抗的不同性质,在被测的介质的界面产生反射与折射的原理而工作的。雷达液位计,是基...
电脑显示屏有哪些分类?m×16,间隔为1??m。根据所用DMD的片数,DLP投影机可分为:单片机、两片机、三片机。DLP投影机清晰度高、画面均匀,色彩锐利,三片机亮度可达2000流明以上,它...其工...