Browse Source

添加esp8266 tcp

liuhao 3 years ago
parent
commit
ffec77b007
1 changed files with 1184 additions and 0 deletions
  1. 1184 0
      TEST_Prj/esp8266tcp/tcp/tcp.ino

+ 1184 - 0
TEST_Prj/esp8266tcp/tcp/tcp.ino

@@ -0,0 +1,1184 @@
+#include <ESP8266WiFi.h>
+#include "string.h"
+#include <string.h>
+#include <stdio.h>
+
+#include <SoftwareSerial.h>
+//串口缓存区改C:\Users\liuhao\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266\HardwareSerial.cpp
+#ifndef D5
+#if defined(ESP8266)
+#define D5 (14)
+#define D6 (12)
+#define D7 (13)
+#define D8 (15)
+#define TX (1)
+#elif defined(ESP32)
+#define D5 (18)
+#define D6 (19)
+#define D7 (23)
+#define D8 (5)
+#define TX (1)
+#endif
+#endif
+
+#ifdef ESP32
+#define BAUD_RATE 9600
+#else
+#define BAUD_RATE 9600
+#endif
+
+// Reminder: the buffer size optimizations here, in particular the isrBufSize that only accommodates
+// a single 8N1 word, are on the basis that any char written to the loopback SoftwareSerial adapter gets read
+// before another write is performed. Block writes with a size greater than 1 would usually fail. 
+SoftwareSerial swSer;
+
+//定义可连接的客户端数目最大值
+#define MAX_SRV_CLIENTS 3
+
+#define Serial_RX_MAXSIZE  256
+#define TCP_RX_MAXSIZE     256
+
+const char* ssid = "ESP8266";
+const char* password = "12345678";
+
+WiFiServer server(60000);
+WiFiClient serverClients[MAX_SRV_CLIENTS];
+
+unsigned char Serial_Buffer[Serial_RX_MAXSIZE]={0};
+
+uint32_t timeTick = 0;
+unsigned int  buffUartIndex = 0;
+unsigned long preUartTick = 0;
+int LED_PIN=2;//GPIO2--D0 模块自带的led
+int connectedCnt=0;
+String Rxstr="";
+char getflag=0;
+char SendBuff[20]={0};
+int openCnt=0;
+int volt=0;
+
+/*****************使用摄像头发送宏开关*************************/
+#ifndef USING_CAMERA_FOR_MMS
+#define  USING_CAMERA_FOR_MMS    1
+#endif
+
+/******************使用SD卡存储图片宏开关*************************/
+#ifndef USING_SAVE_SD
+#define USING_SAVE_SD              0
+#endif
+
+
+
+
+typedef unsigned char u8;
+typedef unsigned short int u16;
+typedef unsigned int u32;
+
+#define  USART1_RECEIVE_BUFSIZE     100
+#define  USART1_MAX_SIZE            96
+
+#define  USART2_RECEIVE_BUFSIZE     2048
+#define  USART2_MAX_SIZE            4996
+
+#define  second   1000000
+
+#define  L_TIME  (1*second)
+#define  Z_TIME  (10*second)
+#define  HH_TIME (90*second)
+#define  H_TIME  (30*second) //设置串口接收的等待时间
+
+
+//硬件引脚定义
+#define  camer_pwerH()    GPIO_SetBits(GPIOA,GPIO_Pin_1)
+#define  camer_pwerL()    GPIO_ResetBits(GPIOA,GPIO_Pin_1)
+
+//用户自定义宏变量
+//#define N_BYTE  512        //每次读取N_BYTE字节,N_BYTE必须是8的倍数
+
+#define N_BYTE  1024        //每次读取N_BYTE字节,N_BYTE必须是8的倍数
+
+//#define N_BYTE  224        //每次读取N_BYTE字节,N_BYTE必须是8的倍数/
+#define IMAGE_SIZE_160X120     0x22
+#define IMAGE_SIZE_320X240     0x11
+#define IMAGE_SIZE_640X480     0x00
+
+
+#define COMPRESS_RATE_36       0x36   //该压缩率是默认压缩率,160x120和320x240可用此压缩率
+
+#define COMPRESS_RATE_60       0x60   //640X480尺寸,默认压缩率36会占用45K左右的空间
+                                      //选择60压缩率可将45K压缩到20K左右
+
+
+
+typedef enum
+{
+    SERIAL_NUM_0 = 0x00,
+    SERIAL_NUM_1,
+    SERIAL_NUM_2,
+    SERIAL_NUM_3,
+    SERIAL_NUM_5,
+    SERIAL_NUM_6,
+    SERIAL_NUM_7,
+    SERIAL_NUM_8,
+    SERIAL_NUM_9,
+    SERIAL_NUM_10
+}nSerialNum;
+//extern const nSerialNum SerialNum_Byte;
+//
+//extern u8 g_SerialNumber;
+//extern volatile u8 cameraReady;
+//extern u32 picLen;//图片长度
+
+//串口驱动接口函数,移植时需要修改接口函数
+void cam_write(const u8 *buf,u8 len);
+u16 cam_receiver( u8 *buf,u16 send_len);
+
+void server_sendByte(u8 *data,u32 len);
+// 应用实例函数
+u8 CameraDemoApp(u8 Serialnumber,u8 nCameraImageSize);
+
+u8 camera_init(u8 Serialnumber,u8 nSetImageSize);
+u8 send_cmd(const u8 *cmd,u8 n0,const u8 *rev,u8 n1);
+void SetSerailNumber(u8 *DstCmd, const u8 *SrcCmd, u8 SrcCmdLength,
+                     u8 *DstRcv, const u8 *SrcRcv, u8 SrcRcvLength,u8 nID);
+
+//摄像头属性设置:复位/图片尺寸大小/图片压缩率
+u8 send_reset(u8 Serialnumber);
+u8 current_photo_size(u8 Serialnumber,u8 * nImageSize);
+u8 send_photo_size(u8 Serialnumber,u8 nImageSize);
+u8 send_compress_rate(u8 Serialnumber,u8 nCompressRate);
+void UART1Write(char *data,u32 len) ;
+//移动侦测控制函数
+u8 send_motion_sensitivity(u8 Serialnumber);
+u8 send_open_motion(u8 Serialnumber);
+u8 send_close_motion(u8 Serialnumber);
+u8 Motion_Detecte_Idle(u8 *pSerialnumber);
+//拍照处理函数
+u8 send_photoBuf_cls(u8 Serialnumber);
+u8 send_start_photo(u8 Serialnumber);
+u32 send_read_len(u8 Serialnumber);
+u8 send_get_photo(u16 add,u16 read_len,u8 *buf,u8 Serialnumber);
+
+
+
+
+#define CLEAR_FRAME            1     //去掉返回图片数据携带的协议头和尾76 00 32 00
+#define ECHO_CMD_DEBUG_INFO    0     //1,开启指令调试;0,关闭
+
+#define ID_SERIAL_NUM       1        //序号在数组的所在位置
+
+//复位指令与复位回复
+const u8 reset_rsp[] = {0x76,0x00,0x26,0x00};
+const u8 reset_cmd[] = {0x56,0x00,0x26,0x00};
+
+
+//清除图片缓存指令与回复
+const u8 photoBufCls_cmd [] = {0x56,0x00,0x36,0x01,0x02};
+const u8 photoBufCls_rsp[] = {0x76,0x00,0x36,0x00,0x00};    
+
+//拍照指令与回复
+const u8 start_photo_cmd[] = {0x56,0x00,0x36,0x01,0x00};    
+const u8 start_photo_rsp[] = {0x76,0x00,0x36,0x00,0x00};   
+
+//读图片长度指令与回复
+//图片长度指令回复的前7个字节是固定的,最后2个字节表示图片的长度
+//如0xA0,0x00,10进制表示是40960,即图片长度(大小)为40K
+const u8 read_len_cmd[] = {0x56,0x00,0x34,0x01,0x00};
+const u8 read_len_rsp[] = {0x76,0x00,0x34,0x00,0x04,0x00,0x00};
+
+//读图片数据指令与回复
+//get_photo_cmd前6个字节是固定的,
+//第9,10字节是图片的起始地址
+//第13,14字节是图片的末尾地址,即本次读取的长度
+
+//如果是一次性读取,第9,10字节的起始地址是0x00,0x00;
+//第13,14字节是图片长度的高字节,图片长度的低字节(如0xA0,0x00)
+
+//如果是分次读取,每次读N字节(N必须是8的倍数)长度,
+//则起始地址最先从0x00,0x00读取N长度(即N & 0xff00, N & 0x00ff),
+//后几次读的起始地址就是上一次读取数据的末尾地址
+const u8 get_photo_cmd [] = {0x56,0x00,0x32,0x0C,0x00,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF }; 
+const u8 get_photo_rsp []  = {0x76,0x00,0x32,0x00,0x00};
+
+//设置压缩率指令与回复,最后1个字节为压缩率选项
+//范围是:00 - FF
+//默认压缩率是36
+const u8 set_compress_cmd [] = {0x56,0x00,0x31,0x05,0x01,0x01,0x12,0x04,0x36};
+const u8 compress_rate_rsp [] = {0x76,0x00,0x31,0x00,0x00};
+
+//设置图片尺寸指令与回复
+//set_photo_size_cmd最后1个字节的意义
+//0x22 - 160X120
+//0x11 - 320X240
+//0x00 - 640X480
+const u8 set_photo_size_cmd [] = {0x56,0x00,0x31,0x05,0x04,0x01,0x00,0x19,0x11};
+const u8 set_photo_size_rsp [] = {0x76,0x00,0x31,0x00,0x00 };
+
+//读取图片尺寸指令与回复
+//read_photo_size_rsp最后1个字节的意义
+//0x22 - 160X120
+//0x11 - 320X240
+//0x00 - 640X480
+const u8 read_photo_size_cmd [] = {0x56,0x00,0x30,0x04,0x04,0x01,0x00,0x19};
+const u8 read_photo_size_rsp [] = {0x76,0x00,0x30,0x00,0x01,0x00};
+
+
+
+//移动侦测指令
+//motion_enable_cmd 打开移动侦测
+//motion_disable_cmd 关闭移动侦测
+const u8 motion_enable_cmd [] = {0x56,0x00,0x37,0x01,0x01};
+const u8 motion_disable_cmd [] = {0x56,0x00,0x37,0x01,0x00};
+const u8 motion_rsp [] = {0x76,0x00,0x37,0x00,0x00};
+
+//当系统检测到有移动时,自动从串口输出motio_detecte
+const u8 motion_detecte [] = {0x76,0x00,0x39,0x00,0x00};
+
+//移动侦测灵敏度设置
+const u8 motion_sensitivity_cmd [] = {0x56,0x00,0x31,0x05,0x01,0x01,0x1A,0x6E,0x03};
+const u8 motion_sensitivity_rsp [] = {0x76,0x00,0x31,0x00,0x00};
+volatile u8 cameraReady = 0;
+u32 picLen = 0;   //数据长度
+//CommandPacket和ResponsePacket用于拷贝只读区的指令及应答到内存
+u8 CommandPacket[16];
+u8 ResponsePacket[7];
+//const nSerialNum SerialNum_Byte;//序列号枚举变量
+u8 g_SerialNumber = 0;//串口上报移动侦测时保存的当前序列号
+u8 usa1_buf[USART1_RECEIVE_BUFSIZE] = {0};
+u8 gprs_buf[USART2_RECEIVE_BUFSIZE] = {0};
+void UART3Write(u8 *data,u32 len)   //发送n个字符
+{
+  Serial.write(&data[0],len);
+}
+void UART1Write(char *data,u32 len)   //发送n个字符
+{ 
+    u16 i;
+    if( len == 0) 
+    { 
+        for(i = 0;data[i] != '\0';i++)
+        {
+           swSer.write(data[i]);
+        }
+    }
+
+    else
+    {   
+        for(i = 0;i < len;i++)
+        {
+           swSer.write(data[i]);
+        }
+    }
+
+}
+//等待接收数据 接收到的数据,接收到的个数等待接收的时间
+u16 UART3_Receiver_buf(u8 *data,u32 len,u32 time)  
+{
+  u16 i=0;
+  u32 time0=0;
+  while(1)
+  {
+     if(Serial.available() > 0) {
+     data[i]=Serial.read();
+     time0 = 0;
+     i++;
+     if( i == len && (len != 0) )
+     { 
+                break; 
+     }
+    yield();
+    }else
+    {
+         if( time0 > 10000 )
+                break;
+         else 
+               time0++;
+    }
+  }
+   return i;
+//    u16 i=0;
+//    u32 time0=0;
+//    i = USART_ReceiveData(USART1);
+//    while((USART_GetFlagStatus(USART1,USART_FLAG_RXNE)) == RESET)
+//    {   
+//        delay_us(1);
+//        time0++;
+//        if( time0 > time)
+//        {
+//            return 0;
+//        } 
+//    }
+//    data[0] = USART_ReceiveData(USART1);
+//    i = 1;
+//    time0 = 0;
+//    while(1)
+//    { 
+//        if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE) != RESET)
+//        {
+//            time0 = 0;
+//            data[i] = USART_ReceiveData(USART1);
+//            i++;
+//            if( i == len && (len != 0) )
+//            { 
+//                break; 
+//            }
+//        }
+//        else 
+//        {
+//            if( time0 > 10000 )
+//                break;
+//            else 
+//                time0++;
+//        }
+//    }
+//    return i;
+}
+
+/****************************************************************
+函数名:SetSerailNumber
+函数描述: 修改协议中的序号
+输入参数:目标指令缓存首地址,源指令首地址,源指令长度,
+          目标应答缓存首地址,源应答首地址,源应答长度,需要修改的
+          序号值
+返回:无
+******************************************************************/   
+void SetSerailNumber(u8 *DstCmd, const u8 *SrcCmd, u8 SrcCmdLength,
+                     u8 *DstRsp, const u8 *SrcRsp, u8 SrcRspLength,u8 nID)
+{
+    memset(&CommandPacket,0,sizeof(CommandPacket));
+    memset(&ResponsePacket,0,sizeof(ResponsePacket));
+    
+    memcpy(DstCmd,SrcCmd,SrcCmdLength);
+    memcpy(DstRsp,SrcRsp,SrcRspLength);
+    
+    DstCmd[ID_SERIAL_NUM] = nID & 0xFF;
+    DstRsp[ID_SERIAL_NUM] = nID & 0xFF;
+
+}
+
+/****************************************************************
+函数名:cam_write
+函数描述: 接口函数,写入控制摄像头的串口
+输入参数:数据的首地址,长度
+返回:无
+******************************************************************/   
+void cam_write(const u8 *buf,u8 len)
+{ 
+    
+    //需要调试时开启,观察打印的数据,这里使用串口2调试
+    #if ECHO_CMD_DEBUG_INFO
+    
+    UART1Write("\r\n",0);
+    UART1Write((u8 *)buf,len);
+    UART1Write("\r\n",0);     
+    #endif
+    
+    //写串口驱动函数
+    UART3Write((u8 *)buf,len);
+    
+}
+
+/****************************************************************
+函数名:cam_receiver
+函数描述:接口函数,读取控制摄像头的串口
+输出参数:接收数据的地址,长度
+返回:接收到数据个数
+******************************************************************/   
+u16 cam_receiver(u8 *buf,u16 send_len)
+{ 
+    u16 i = 0;
+    
+    i = UART3_Receiver_buf(buf,send_len,L_TIME);
+    
+    #if ECHO_CMD_DEBUG_INFO
+    
+    UART1Write("\r\n",0);
+    UART1Write(buf,send_len);
+    UART1Write("\r\n",0);
+    
+    #endif
+    return i;
+}
+
+/****************************************************************
+函数名:camera_init
+函数描述:摄像头初始化
+输入参数:序列号,需要设置的图片尺寸
+返回:初始化成功返回1,初始化失败返回0
+******************************************************************/   
+u8 camera_init(u8 Serialnumber,u8 nSetImageSize)
+{    
+    u8 CurrentImageSize = 0xFF;
+    u8 CurrentCompressRate = COMPRESS_RATE_36;
+    
+    //读取当前的图片尺寸到currentImageSize
+    if ( !current_photo_size(Serialnumber,&CurrentImageSize))
+    {
+        UART1Write("\r\nread_photo_size error\r\n",0);
+        return 0;
+    }
+    
+    //判断是否需要修改图片尺寸
+    if(nSetImageSize != CurrentImageSize)
+    {
+        //设置图片尺寸,设置后复位生效,该项设置后会永久保存
+        if ( !send_photo_size(Serialnumber,nSetImageSize))
+        {
+            UART1Write("\r\nset_photo_size error\r\n",0);
+            return 0;
+        }
+        else
+        {
+            //复位生效
+            if ( !send_reset(Serialnumber))
+            {
+                UART1Write("\r\reset error\r\n",0);
+                return 0;
+            }
+            delay(1000);
+            CurrentImageSize = nSetImageSize;
+        }
+        
+    }
+    
+    //给不同图片尺寸设置适当的图片压缩率
+    if(nSetImageSize == CurrentImageSize)
+    {
+        switch(CurrentImageSize)
+        {
+            case IMAGE_SIZE_160X120:
+            case IMAGE_SIZE_320X240:
+                 CurrentCompressRate = COMPRESS_RATE_36;
+                 break;
+            case IMAGE_SIZE_640X480:
+                 CurrentCompressRate = COMPRESS_RATE_60;
+                 break;
+            default:
+                break;
+        }
+    }
+    //设置图片压缩率,该项不保存,每次上电后需重新设置
+    if ( !send_compress_rate(Serialnumber,CurrentCompressRate))
+    {
+        UART1Write("\r\nsend_compress_rate error\r\n",0);
+        return 0;
+    }
+    //这里要注意,设置压缩率后要延时
+    delay(100);
+
+    return 1;
+    
+}
+
+/****************************************************************
+ 函数名:send_cmd
+ 函数描述:发送指令并识别指令返回
+ 输入参数:指令的首地址,指令的长度,匹配指令的首地址,需验证的个数
+ 返回:成功返回1,失败返回0
+******************************************************************/ 
+u8 send_cmd( const u8 *cmd,u8 n0,const u8 *rev,u8 n1)
+{
+    u8  i;
+    u8  tmp[5] = {0x00,0x00,0x00,0x00,0x00};
+
+  
+    cam_write(cmd, n0);
+
+    if ( !cam_receiver(tmp,5) ) 
+    {
+        return 0;
+    }
+   
+    //检验数据
+    for (i = 0; i < n1; i++)
+    {  
+        if (tmp[i] != rev[i]) 
+        {
+            return 0;
+        }
+    }
+    
+    return 1;
+
+}
+
+
+/****************************************************************
+函数名:current_photo_size
+函数描述:读取当前设置的图片尺寸
+输入参数:Serialnumber序列号,nImageSize传递图片尺寸的引用变量
+返回:成功返回1,失败返回0
+******************************************************************/ 
+u8 current_photo_size(u8 Serialnumber,u8 * nImageSize)
+{  
+    u8  i;
+    u8  tmp[6] = {0x00,0x00,0x00,0x00,0x00,0x00};
+
+    SetSerailNumber( CommandPacket,
+                     read_photo_size_cmd,
+                     sizeof(read_photo_size_cmd),
+                     ResponsePacket,
+                     read_photo_size_rsp,
+                     sizeof(read_photo_size_rsp),
+                     Serialnumber );
+      
+    cam_write(CommandPacket, sizeof(read_photo_size_cmd));
+
+    if ( !cam_receiver(tmp,6) ) 
+    {
+        return 0;
+    }
+   
+    //检验数据,对比前5个字节
+    for (i = 0; i < 5; i++)
+    {  
+        if (tmp[i] != ResponsePacket[i]) 
+        {
+            return 0;
+        }
+    }
+    
+    //最后一个字节表示当前的图片大小
+    *nImageSize = tmp[5];
+    return 1;
+}
+
+
+/****************************************************************
+函数名:send_photo_size
+函数描述:设置拍照的图片尺寸(可选择:160X120,320X240,640X480)
+输入参数:序列号,需要设置的图片尺寸
+返回:成功返回1,失败返回0
+******************************************************************/ 
+u8 send_photo_size(u8 Serialnumber,u8 nImageSize)
+{  
+    u8  i;
+    
+    SetSerailNumber( CommandPacket,
+                     set_photo_size_cmd,
+                     sizeof(set_photo_size_cmd),
+                     ResponsePacket,
+                     set_photo_size_rsp,
+                     sizeof(set_photo_size_rsp),
+                     Serialnumber );
+    
+    CommandPacket [sizeof(set_photo_size_cmd) - 1] = nImageSize;
+    
+    i = send_cmd( CommandPacket,
+                  sizeof(set_photo_size_cmd),
+                  ResponsePacket,
+                  sizeof(set_photo_size_rsp) );
+    return i;
+}
+
+
+/****************************************************************
+函数名:send_reset
+函数描述:发送复位指令复位后要延时1-2秒
+输入参数:序列号
+返回:成功返回1 失败返回0
+******************************************************************/   
+u8 send_reset(u8 Serialnumber)
+{  
+    u8 i;
+    //复制命令与应答,修改序号
+    SetSerailNumber( CommandPacket,
+                     reset_cmd,
+                     sizeof(reset_cmd),
+                     ResponsePacket,
+                     reset_rsp,
+                     sizeof(reset_rsp),
+                     Serialnumber );
+    
+    i = send_cmd( CommandPacket,
+                  sizeof(reset_cmd),
+                  ResponsePacket,
+                  sizeof(reset_rsp) );
+    
+    return i;
+
+}
+
+/****************************************************************
+函数名:send_stop_photo
+函数描述:清空图片缓存
+输入参数:序列号
+返回:成功返回1,失败返回0
+******************************************************************/    
+u8 send_photoBuf_cls(u8 Serialnumber)
+{ 
+    u8 i;
+    
+    SetSerailNumber( CommandPacket,
+                     photoBufCls_cmd,
+                     sizeof(photoBufCls_cmd),
+                     ResponsePacket,
+                     photoBufCls_rsp,
+                     sizeof(photoBufCls_rsp),
+                     Serialnumber );
+    
+    i = send_cmd( CommandPacket,
+                  sizeof(photoBufCls_cmd),
+                  ResponsePacket,
+                  sizeof(photoBufCls_rsp) );
+    return i;
+}  
+
+
+/****************************************************************
+函数名:send_compress_rate
+函数描述:发送设置图片压缩率
+输入参数:序列号
+返回:成功返回1,失败返回0
+******************************************************************/    
+u8 send_compress_rate(u8 Serialnumber,u8 nCompressRate)
+{
+    u8 i;
+    
+    SetSerailNumber( CommandPacket,
+                     set_compress_cmd,
+                     sizeof(set_compress_cmd),
+                     ResponsePacket,
+                     compress_rate_rsp,
+                     sizeof(compress_rate_rsp),
+                     Serialnumber );
+    
+    if(nCompressRate > 0x36)
+    {
+        //最后一个字节表示压缩率
+        CommandPacket [sizeof(set_compress_cmd) - 1] = nCompressRate;
+    }
+    
+    i = send_cmd( CommandPacket,
+                  sizeof(set_compress_cmd),
+                  ResponsePacket,
+                  sizeof(compress_rate_rsp) );
+    return i;
+}
+
+
+/****************************************************************
+函数名:send_start_photo
+函数描述:发送开始拍照的指令
+输入参数:序列号
+返回:识别成功返回1 失败返回0
+******************************************************************/   
+u8 send_start_photo(u8 Serialnumber)
+{
+    u8 i;
+    
+    SetSerailNumber( CommandPacket,
+                     start_photo_cmd,
+                     sizeof(start_photo_cmd),
+                     ResponsePacket,
+                     start_photo_rsp,
+                     sizeof(start_photo_rsp),
+                     Serialnumber );
+    
+    i = send_cmd( CommandPacket,
+                  sizeof(start_photo_cmd),
+                  ResponsePacket,
+                  sizeof(start_photo_rsp) );
+    return i;
+}   
+
+
+/****************************************************************
+函数名:send_read_len
+函数描述:读取拍照后的图片长度,即图片占用空间大小
+输入参数:序列号
+返回:图片的长度
+******************************************************************/ 
+u32 send_read_len(u8 Serialnumber)
+{
+    u8 i;
+    u32 len;
+    u8 tmp[9];  
+    
+    SetSerailNumber( CommandPacket,
+                     read_len_cmd,
+                     sizeof(read_len_cmd),
+                     ResponsePacket,
+                     read_len_rsp,
+                     sizeof(read_len_rsp),
+                     Serialnumber );
+    
+    //发送读图片长度指令
+    cam_write(CommandPacket, 5);
+
+    if ( !cam_receiver(tmp,9)) 
+    {
+        return 0;
+    }
+
+    //检验数据
+    for (i = 0; i < 7; i++)
+    {
+        if ( tmp[i] != ResponsePacket[i]) 
+        {
+            return 0;
+        }
+    }
+    
+    len = (u32)tmp[7] << 8;//高字节
+    len |= tmp[8];//低字节
+    
+    return len;
+}
+
+
+/****************************************************************
+函数名:send_get_photo
+函数描述:读取图片数据
+输入参数:读图片起始地址StaAdd, 
+          读取的长度readLen ,
+          接收数据的缓冲区buf
+          序列号
+返回:成功返回1,失败返回0
+FF D8 ... FF D9 是JPG的图片格式
+
+1.一次性读取的回复格式:76 00 32 00 00 FF D8 ... FF D9 76 00 32 00 00
+
+2.分次读取,每次读N字节,循环使用读取图片数据指令读取M次或者(M + 1)次读取完毕:
+如第一次执行后回复格式
+76 00 32 00 <FF D8 ... N> 76 00 32 00
+下次执行读取指令时,起始地址需要偏移N字节,即上一次的末尾地址,回复格式
+76 00 32 00 <... N> 76 00 32 00
+......
+76 00 32 00 <... FF D9> 76 00 32 00 //lastBytes <= N
+
+Length = N * M 或 Length = N * M + lastBytes
+
+******************************************************************/ 
+u8 send_get_photo(u16 staAdd,u16 readLen,u8 *buf,u8 Serialnumber)
+{
+    u8 i = 0;
+    u8 *ptr = NULL;
+    
+    
+    SetSerailNumber( CommandPacket,
+                     get_photo_cmd,
+                     sizeof(get_photo_cmd),
+                     ResponsePacket,
+                     get_photo_rsp,
+                     sizeof(get_photo_rsp),
+                     Serialnumber );
+    
+    //装入起始地址高低字节
+    CommandPacket[8] = (staAdd >> 8) & 0xff;
+    CommandPacket[9] = staAdd & 0xff;
+    //装入末尾地址高低字节
+    CommandPacket[12] = (readLen >> 8) & 0xff;
+    CommandPacket[13] = readLen & 0xff;
+    
+    //执行指令
+    cam_write(CommandPacket,16);
+    
+    //等待图片数据存储到buf,超时或无数据回复则返回0
+    if ( !cam_receiver(buf,readLen + 10))
+    {
+        return 0;
+    }
+    
+    //检验帧头76 00 32 00 00
+    for (i = 0; i < 5; i++)
+    {
+        if ( buf[i] != ResponsePacket[i] )
+        {
+            return 0;
+        }
+    }
+
+    //检验帧尾76 00 32 00 00
+    for (i = 0; i < 5; i++)
+    {
+        if ( buf[i + 5 + readLen] != ResponsePacket[i] )
+        {
+            return 0;
+        }
+    }
+    
+    
+    //宏开关选择丢弃/保留 帧头帧尾76 00 32 00 00
+    #if CLEAR_FRAME
+//    memcpy(buf,buf + 5,read_len);
+    ptr = buf;
+    
+    for (; readLen > 0; ++ptr)
+    {
+        *(ptr) = *(ptr + 5);
+        readLen--;
+    }
+    #endif
+    
+    return 1;
+}
+
+/****************************************************************
+函数名:send_open_motion
+函数描述:发送打开移动侦测指令
+输入参数:序列号
+返回:识别成功返回1 失败返回0
+******************************************************************/   
+u8 send_motion_sensitivity(u8 Serialnumber)
+{
+    u8 i;
+    
+    SetSerailNumber( CommandPacket,
+                     motion_sensitivity_cmd,
+                     sizeof(motion_sensitivity_cmd),
+                     ResponsePacket,
+                     motion_sensitivity_rsp,
+                     sizeof(motion_sensitivity_rsp),
+                     Serialnumber );
+    
+    i = send_cmd( CommandPacket,
+                  sizeof(motion_sensitivity_cmd),
+                  ResponsePacket,
+                  sizeof(motion_sensitivity_rsp) );
+    return i;
+}
+
+/****************************************************************
+函数名:send_open_motion
+函数描述:发送打开移动侦测指令
+输入参数:序列号
+返回:识别成功返回1 失败返回0
+******************************************************************/   
+u8 send_open_motion(u8 Serialnumber)
+{
+    u8 i;
+    
+    SetSerailNumber( CommandPacket,
+                     motion_enable_cmd,
+                     sizeof(motion_enable_cmd),
+                     ResponsePacket,
+                     motion_rsp,
+                     sizeof(motion_rsp),
+                     Serialnumber );
+    
+    i = send_cmd( CommandPacket,
+                  sizeof(motion_enable_cmd),
+                  ResponsePacket,
+                  sizeof(motion_rsp) );
+    return i;
+}
+
+/****************************************************************
+函数名:send_close_motion
+函数描述:发送关闭移动侦测指令
+输入参数:序列号
+返回:识别成功返回1 失败返回0
+******************************************************************/   
+u8 send_close_motion(u8 Serialnumber)
+{
+    u8 i;
+    
+    SetSerailNumber( CommandPacket,
+                     motion_disable_cmd,
+                     sizeof(motion_disable_cmd),
+                     ResponsePacket,
+                     motion_rsp,
+                     sizeof(motion_rsp),
+                     Serialnumber );
+    
+    i = send_cmd( CommandPacket,
+                  sizeof(motion_disable_cmd),
+                  ResponsePacket,
+                  sizeof(motion_rsp) );
+    return i;
+}
+
+/****************************************************************
+函数名:Motion_Detecte_Idle
+函数描述: 等待移动侦测事件,该函数可在RS485同时接多个摄像头时,传递
+          当前是第几个序列号上报移动侦测
+输入参数:传递一个指针变量
+返回:成功返回1 失败返回0
+******************************************************************/   
+u8 Motion_Detecte_Idle(u8 *pSerialnumber)
+{
+    u8  tmp[5] = {0x00,0x00,0x00,0x00,0x00};
+    
+    if ( !cam_receiver(tmp,5) ) 
+    {
+        return 0;
+    }
+    
+    //检验数据
+    //全部有5个数据,只校验4个,其中数组下标为1是序列号
+    if(!(tmp[0] == motion_detecte[0] && 
+         tmp[2] == motion_detecte[2] &&
+         tmp[3] == motion_detecte[3] &&
+         tmp[4] == motion_detecte[4] ))
+    {
+        return 0;
+    }
+    
+    //取出序列号
+    *pSerialnumber = tmp[1];
+    return 1;
+
+}
+
+u8 sendComBuff[8]={0};
+
+/****************************************************************
+函数名:CameraDemoApp
+函数描述:摄像头应用实例
+输入参数:序列号,图片尺寸
+返回:成功返回1,失败返回0
+******************************************************************/   
+u8 CameraDemoApp(u8 Serialnumber,u8 nCameraImageSize)
+{
+    u16 cntM = 0,lastBytes = 0,i = 0;
+    
+    #if USING_SAVE_SD
+    FRESULT res;
+    u8 pname[20];
+    u8 Issuccess = 0;
+    u32 defaultbw = 1;
+    #endif
+    
+    
+    //初始化摄像头
+    cameraReady = camera_init(Serialnumber,nCameraImageSize);
+    if(!cameraReady)
+    {
+        return 0;
+    }
+    //清空图片缓存
+    if( !send_photoBuf_cls(Serialnumber) )
+    {
+        return 0;
+    }
+    //开始拍照
+    if( !send_start_photo(Serialnumber) )
+    {
+        return 0;
+    }
+    else
+    {
+        //读取拍照后的图片长度
+        picLen = send_read_len(Serialnumber);
+    }
+    
+    if( !picLen )
+    {
+        return 0;
+    }
+    else
+    {
+        cntM = picLen / N_BYTE;
+        lastBytes = picLen % N_BYTE;
+    }
+    sendComBuff[0]=0xaa;
+    sendComBuff[5]=0x05; //图像命令
+    sendComBuff[6]=0xaf;
+    sendComBuff[1]=picLen>>24;
+    sendComBuff[2]=picLen>>16;
+    sendComBuff[3]=picLen>>8;
+    sendComBuff[4]=picLen;
+    //UART2Write(sendComBuff,7);
+    server_sendByte(sendComBuff,7);
+    delay(100);
+    //分M次,每次读N_BYTE字节
+    if( cntM )
+    {
+        for( i = 0; i < cntM; i++)
+        {  
+            memset(gprs_buf, 0, sizeof(gprs_buf));
+            //按图片长度读取数据
+            if( !send_get_photo( i * N_BYTE,
+                               N_BYTE,
+                               gprs_buf,
+                               Serialnumber) )
+            {
+                return 0;
+            }
+            else
+            {
+                //此分支可将图片数据输出到指定的串口
+                //如接口函数,将图片数据写入到串口2
+                //uart1_putchar(0x15);//发送标识符
+               server_sendByte(gprs_buf,N_BYTE);
+                
+            }
+            delay(50);
+        }
+    }
+    //剩余图片长度
+    if(lastBytes)
+    {
+
+        memset(gprs_buf, 0, sizeof(gprs_buf));  
+        
+        //读取剩余长度
+        if( !send_get_photo( i * N_BYTE,
+                            lastBytes,
+                            gprs_buf,
+                            Serialnumber) )
+        {
+        
+            return 0;
+        }
+        else
+        {
+           // uart1_putchar(0x15);//发送标识符
+            //UART2Write(gprs_buf,lastBytes);//发送图片数据
+            server_sendByte(gprs_buf,lastBytes);
+        }
+        delay(50);
+    }
+    
+   
+    return 1;
+}
+
+
+    
+
+void  function_Star(){
+  static int led_State=0;  
+  digitalWrite(LED_PIN,led_State);
+  led_State=(~led_State);
+}
+
+
+/*
+  检查串口是否有数据
+*/
+void Usart_RxTask(void)
+{
+  unsigned char i =0;
+  if (Serial.available() > 0)
+  {
+    uint8_t t = Serial.read();
+    Serial_Buffer[buffUartIndex++] = t;
+    preUartTick = millis();
+    if (buffUartIndex >= Serial_RX_MAXSIZE - 1) {
+      buffUartIndex = Serial_RX_MAXSIZE - 2;
+      preUartTick = preUartTick - 10;
+    }
+  }
+  if (buffUartIndex > 0 && (millis() - preUartTick >= 10))
+  { //data ready
+    Serial_Buffer[buffUartIndex] = 0x00;
+          if(strstr((char*)&Serial_Buffer[0],"esp_get")!=NULL) 
+          {
+                getflag=1;
+          }
+          if(strstr((char*)&Serial_Buffer[0],"esp_close")!=NULL) 
+          {
+                getflag=0;
+          }
+    // 将UART端口数据推送到所有已连接的telnet客户端,实现双向通信
+       for(i = 0; i < MAX_SRV_CLIENTS; i++){
+          if (serverClients[i] && serverClients[i].connected()){
+          serverClients[i].write(&Serial_Buffer[0], buffUartIndex);
+            delay(1);
+         }
+       }
+    buffUartIndex = 0;
+  }
+}
+
+
+void server_sendByte(u8 *data,u32 len)
+{
+  int i=0;
+  for(i = 0; i < MAX_SRV_CLIENTS; i++){
+            if (serverClients[i] && serverClients[i].connected()){
+             serverClients[i].write(&data[0], len);
+                delay(1);
+     }
+  }
+}
+
+
+void setup() {
+  
+  swSer.begin(BAUD_RATE, SWSERIAL_8N1, D5, D6, false, 95, 11);
+  for (char ch = ' '; ch <= 'z'; ch++) {
+    swSer.write(ch);
+  }
+  swSer.println("");
+  WiFi.softAP(ssid, password);
+  swSer.println();
+  swSer.print("IP address: ");
+  swSer.println(WiFi.softAPIP());
+  pinMode(LED_PIN,OUTPUT);//设置对应引脚为输出模式
+  digitalWrite(LED_PIN,HIGH);
+  //启动UART传输和服务器
+  server.begin();
+  server.setNoDelay(true);//停止小包合并发送
+  swSer.print("Ready! Use 'telnet ");
+  swSer.print(WiFi.localIP());//获得服务器本地IP
+
+  Serial.begin(115200);
+  //摄像头模块初始化  
+  if (!camera_init(SERIAL_NUM_0,IMAGE_SIZE_160X120))
+  {
+      while(1)
+      {
+        swSer.println("\r\nCamera Init fail!\r\n");
+        delay(1000);     //
+      }       
+  }
+  else
+  {
+        swSer.println("\r\nCamera Init Success!\r\n");
+//        GPIO_ResetBits(GPIOC,GPIO_Pin_13);
+//        delay_ms(200);     //在上电复位后要等1-2秒摄像头才能接收指令
+//        GPIO_SetBits(GPIOC,GPIO_Pin_13);//初始化成功短鸣一声并亮灯
+//        delay_ms(200);     //在上电复位后要等1-2秒摄像头才能接收指令
+//        GPIO_SetBits(GPIOC,GPIO_Pin_13);//初始化成功 亮灯
+  }
+}
+
+
+void loop() {
+  uint8_t i;
+  //检测服务器端是否有活动的客户端连接
+  if (server.hasClient()){
+    for(i = 0; i < MAX_SRV_CLIENTS; i++){
+      //查找空闲或者断开连接的客户端,并置为可用
+      if (!serverClients[i] || !serverClients[i].connected()){
+        if(serverClients[i]) serverClients[i].stop();
+        serverClients[i] = server.available();
+         swSer.print("New client: "); swSer.println(i);
+        continue;
+      }
+    }
+    //若没有可用客户端,则停止连接
+    WiFiClient serverClient = server.available();
+    serverClient.stop();
+  }
+  //检查客户端的数据
+  for(i = 0; i < MAX_SRV_CLIENTS; i++){
+    if (serverClients[i] && serverClients[i].connected()){
+      if(serverClients[i].available()){
+        //从Telnet客户端获取数据,并推送到URAT端口
+       while(serverClients[i].available()) 
+       {
+          Rxstr = serverClients[i].readStringUntil('\r\n');
+          if(Rxstr.indexOf("esp_get")!=-1) 
+          {
+                getflag=1;
+          }
+          if(Rxstr.indexOf("esp_close")!=-1) 
+          {
+                getflag=0;
+          }
+          swSer.println(Rxstr);
+       }
+      }
+    }
+  }
+  //Usart_RxTask();
+  if(getflag==1)
+  {
+    CameraDemoApp(SERIAL_NUM_0,IMAGE_SIZE_160X120); 
+    getflag=0; 
+  }
+  delay(1);
+}