当前国内传统的电子防盗报警系统方案往往是在用户端通过电子设备检测到盗窃等报警信息,然后通过通讯器经电话线将信号自动传到报警中心来完成报警过程。传统的报警中心往往存在很多局限,例如:报警中心地点和人员需固定,报警通信速度慢,反向查询、控制等操作困难而专业,电话线断线问题难以解决,通信费用、尤其是远程通信费用较高,不利于组建远程网络,通信带宽太小,加载信息量少,音视频信号的技术手段应用困难,很难应用于家庭安防市场等等。
而彩信业务自中国移动从2002年9月正式推出以来,随着彩信网络工程的建立和不断地优化,彩信逐渐进入了高速发展和稳定应用阶段。根据调查, 95.4%的用户将来会使用彩信业务。随着支持彩信终端的普及,彩信市场的发展和不断完善,彩信相关的各种业务及应用将得到空前的发展。
所以人们越来越关注于依托中国移动网络、基于彩信业务来发展现代的电子防盗报警系统,从而能在此系统上发挥其随时随地监控、网络涵盖范围大、查询控制等操作简便且普及、费用低、报警通信速度快、音视频应用简易等众多优势,使其能广泛应用于家庭、办公、工厂、商铺等等各种场所。
基于这种巨大的市场需求,新加坡亿世茂科技中国分公司开发出一套以普通51单片机和TR800的GPRS模块为核心的彩信报警器方案,并已经成功投放市场。
方案介绍
此方案是一种基于GSM和GPRS网络的照片监控方案,采用此方案设计的产品操作极其简易,用户可以随时随地用手机远程遥控,拍摄现场的照片并发送到指定手机或者电子邮箱里。可以外接多达15个无线传感器报警,例如烟感、无线门磁、红外人体感应器、煤气传感器等,实现多种触发方式的报警,并具有图像移动侦测功能,能对移动的物体自动触发报警;不仅如此,采用此方案设计的产品还能够监听报警器所在现场的声音,并可录制成音频文件发送至手机或者邮箱。
方案功能优势
短信遥控拍摄:
通过手机发送短信控制报警器拍照并发送
手机接收照片图像:
彩信手机实时接收报警彩信图片
电子邮件接收图像:
彩信图片可发送到指定的电子邮箱
报警时现场录音:
报警时能自动录下现场声音
电话监听:
手机可监听报警器所在场所的声音
无线传感器:
可外接15个无线传感器报警,例如无线门磁、红外人体感应器、烟感、煤气感等
遥控器遥控
可支持学习8个精致遥控器,使报警器按功能需求来被遥控器遥控
存储和发送多种格式文件
支持存储TXT文本文件、JPEG等9种格式的图片文件、MP3等6种格式的音频文件、MP4等8种格式的视频文件,此类文件均支持彩信发送
移动侦测:
对于移动的物体能自动触发并拍照及发送
多方式报警:
报警器能向指定手机打电话、发短信或发送现场照片
后备锂电池:
在外电源不供电时也能确保继续工作
多人接收报警:
可预设多个接收报警的手机号
手动监控:
手机可发送短信命令报警器启动或关闭监控。
方案应用范围
家居监控试用范围
有婴儿、中小学生子女、老人、病人、残疾人的家庭
住宅小区的业主
需长时间外出,住宅无人照看的家庭
住宅小区物业公司
有远程拍照监控需求的家庭
商业办公场所监控试用范围
仓库
物流
装修
物业
娱乐场所
消防、电力、银行等行业用户
环境特殊需现场监控的公司
远程抄表
批发零售市场的商户
车辆监控试用范围
私家车主
拥有车辆的小企业
带停车场的物业公司
汽车销售商
保险公司
方案核心元器件TR800
新加坡iWOW公司出品的TR800是一款通用的GPRS无线通信模块,除了那些通用的功能以外,和别的模块不同的是,它嵌入了标准的彩信协议,支持完整的彩信中英文编辑,支持各种格式的音视频和文本文件的存储与彩信收发,另外,它还具有锂电充电管理的功能。
方案主处理器
STC89LE516RD+,普通8位单片机,价格便宜。
系统原理框图
系统从逻辑上分为三部分:图像捕获和图像压缩编码部分;主控制器处理图像数据和任务控制;带彩信协议GPRS模块无线部分。系统原理如图1所示。
图1 系统原理框图
图1中图像捕获部分除了示意的camera数据线以外,还有行场同步信号线、I2C数据线和时钟线、复位信号线、power down控制信号线和使能控制线、图像压缩编码部分输出给图像捕获部分的时钟信号线。
Sensor可以是无线门磁、红外人体感应器、烟感、煤气感等,通过315MHz接收模块将触发信号和各自的地址码以及数据码回传给主处理器。
OV7670和VC0528的工作模式、触发动作、数据类别都由主处理器来控制,而IS63LV1024L主要用于缓存JPEG图像数据。
TR800独有的锂电充电管理功能主要由两个脚来实现,一个ADC脚对锂电电压进行探测,另一个模拟输出脚对锂电按照其充电曲线方式进行充电。
系统工作原理步骤
1. 系统上电启动后,TR800模块读取SIM信息发送无线信号寻找GSM网络,进行用户号码账户和身份验证后连接到网络;然后系统发起任务读取手机模块中的信息,确定是否有网络连接,若有网络连接则系统发起任务,等待满足触发自动发送彩信的条件。
2. 主处理器可以通过接收SMS(短信服务)信息、来电信息、各类传感模块返回信息,并对之进行解析,根据解析的结果对应开发者定义的任务去进行动作。当接收到用户的触发后,系统发起任务对图像捕获、编码压缩芯片进行命令控制和拍照;拍照后发起任务读取、接收图像捕获、编码压缩芯片回传的图像数据,并在RAM里缓存起来。
3. 当接收到回传的图像数据后,主处理器会发送一条AT命令与TR800建立基于xmodem或者xmodem-1K的通信协议来进行图像数据的传输,然后主处理器再通过AT命令编辑这条彩信,最后TR800会自动按照编辑的命令将图像数据进行MMS封装,封装格式完全符合MMS CLIENT端协议。
4. TR800自动通过PPP协议登陆GPRS网关(GGSN),并使用HTTP代理协议与WAP信息网关建立连接,建立连接后由TR800通过TCP/IP协议把MMS封装的图像数据传送给彩信中心(MMSC),最后MMSC会回传给TR800示意彩信接收成功的数据(同时会发送一条通知给目的手机终端,这条通知里面包含一个网址URL,这个URL网址就是彩信所在的地址,手机终端可以设置为收到通知后就自动连接这个URL网址来收取彩信,也可以设置为手动接受,手机终端连接这个URL网址的过程实际上就是通过WAP来浏览并下载这个URL网页,最后在手机上浏览),而TR800则会从UART口返回一串固定的字符串给主控制器,从而完成了发送彩信的任务。
软件流程图
图2为一个典型应用的软件流程图。
图2 软件流程图
Xmodem传送数据的参考代码
大多数串口软件都不支持xmodem等一类传送数据的协议,但windows自带的超级终端可支持包括xmodem、xmodem-1K在内等多种数据传输协议。以下提供的参考代码是基于STC89LE516RD+处理器的。
xmodem.c
#include <stdio.h>
#include <string.h>
#include "inc\reg516.h"
#include "inc\datatype.h"
#include "inc\xmodem.h"
#include "inc\Uart.h"
#include "inc\interrupt.h"
#include "inc\init.h"
//#include "inc\VIM_COMMON.h"
BYTE tx_EOT(void);
UINT update_CRC(BYTE inData, UINT checksum);
BYTE xmodem_tx(void);
BYTE tx_packet(BYTE packet_number,BYTE xdata *packet_data_buffer, BYTE temp_char);
unsigned char get_packet_data(unsigned char xdata * packet_data_buffer);
code unsigned int crc16_table[256] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
BYTE tx_packet(BYTE packet_number,BYTE xdata * packet_data_buffer, BYTE temp_char )
{
BYTE attempt;
for(attempt = 1; attempt <= MAX_TX_TRY; attempt++)
{
BYTE buffer_index;
unsigned int checksum= 0;
red_led=~red_led;
send_a_byte(SOH); // send start of packet
send_a_byte(packet_number);
send_a_byte(255 - packet_number);
for(buffer_index = 0; buffer_index < PACKET_DATA_BUFFER_LENGTH; buffer_index++)
{
send_a_byte(packet_data_buffer[buffer_index]);
if (temp_char == NAK) checksum += packet_data_buffer[buffer_index];
else checksum = update_CRC(packet_data_buffer[buffer_index], checksum);
}
if (temp_char == ASCII_C) send_a_byte((char)((checksum> > 8) & 0x00ff));
send_a_byte((char)(checksum & 0x00ff)); // send end of packet CRC
temp_char = getchar(); // get receiver response
if (temp_char == CAN) return 0; // reception cancelled
if (temp_char == ACK) return 1; // packet received okay
}
return 0; // attempts exhausted
}
/*
function: 以XMODEM 发送数据
in: user_data 是数据指针
out: 1 sucess
0 faile
使用全局变量? 无
*/
bit send_packet_data(BYTE xdata *User_Data , UINT LEN)
{
struct Message xdata Xmodem_Pack22;
struct Message xdata *xModem;
BYTE i;
unsigned char packet_number = 1;
unsigned char no_more = 0;
unsigned char temp_char = 0;
xModem=&Xmodem_Pack22;
xModem-> User_Data=User_Data;
while((temp_char != ASCII_C) && (temp_char != NAK))
{
temp_char = getchar();// wait till receiver ready
if(temp_char == CAN)
return 0;
}
if (LEN < PACKET_DATA_BUFFER_LENGTH)
{
for(i=0;i <LEN;i++) xModem-> Message[i]=(*User_Data++);
for(i=LEN;i <128;i++) xModem-> Message[i]=CTRL_Z;
if(tx_packet(packet_number, xModem-> Message, temp_char)==0) return 0;
}
else
{
do
{
for(i=0;i <128;i++) xModem-> Message[i]=(*User_Data++);
if(tx_packet(packet_number, xModem-> Message, temp_char)==0)return 0;
packet_number++;
LEN=LEN-128;
}while(LEN> =128);
if (LEN)
{
for(i=0;i <LEN;i++) xModem-> Message[i]=(*User_Data++);
for(i=LEN;i <128;i++) xModem-> Message[i]=CTRL_Z;
if( tx_packet(packet_number, xModem-> Message, temp_char)==0)return 0;
}
}
if (!tx_EOT()) return 0; // end tx data failed
return 1;
}
BYTE tx_EOT(void)
{
BYTE attempt;
for(attempt = 1; attempt <= MAX_TX_TRY; attempt++)
{
send_a_byte(EOT); // send file end
if(getchar() == ACK) return 1; // file end acknowledged
}
return 0; // file tx failed
}
UINT update_CRC(BYTE inData, UINT checksum)
{
return (checksum < < 8) ^ crc16_table[ (checksum > > 8) ^ inData ];
}
xmodem.h
#ifndef _XMODEM_H_
#define _XMODEM_H_
#include "inc\datatype.h"
#define SOH 0x01
#define EOT 0x04
#define ACK 0x06
#define NAK 0x15
#define CAN 0x18
#define CTRL_Z 0x1a
#define SPACE 0x20
#define ASCII_C 0x43
#define PACKET_DATA_BUFFER_LENGTH 128
#define MAX_TX_TRY 3
#define PRINT_BUFFER_LENGTH 80
#define COUNT_STEP 1
#define MAX_COUNT 100
#define MAX_MESSAGE_LEN 132
struct Message
{
BYTE Data_Len; /* 消息内容长度,即Message中的内容字节数 */
// char mType; /* 层间消息类型, */
BYTE Message[PACKET_DATA_BUFFER_LENGTH]; /* 消息内容, 由发送进程填写 */
void *User_Data;
};
extern BYTE tx_packet(BYTE packet_number,BYTE xdata * packet_data_buffer, BYTE temp_char );
bit send_packet_data(BYTE xdata *User_Data , UINT LEN);
#endif