#include #include "string.h" #include #include #include //串口缓存区改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 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(200); //分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); } function_Star(); delay(20); } } //剩余图片长度 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) { function_Star(); 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); function_Star(); delay(200); //在上电复位后要等1-2秒摄像头才能接收指令 function_Star(); delay(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; } digitalWrite(LED_PIN,0); delay(1); }