找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 38299|回复: 61
打印 上一主题 下一主题
收起左侧

ESP8266用STC单片机发送AT命令来连接网络的程序

  [复制链接]
跳转到指定楼层
楼主
ID:112317 发表于 2016-4-5 14:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

全部源码下载:
ESP8266用单片机发送AT命令来连接网络的程序.zip (215.17 KB, 下载次数: 626)


主程序:
  1. /*

  2.   本程序用51单片机经过AT指令控制模块,完成从SMARTLINK 到 手机与模块的绑定,以及云品台的登录,本地数据发给异地手机,手机异地控制测试板上的继电器动作。
  3.   本程序可以移植到STM8这款只要1元钱的单片机上配合AT模块,完成高性价的产品,比如开关插座。主要演示安信可的云平台的试用!以及整个物联网的流程

  4.   注意:变量初始化成0,否者随机  数组注意溢出问题  0X55 在其他数据中有可能出现,并造成混乱,主要是计数  过滤数据,根据网络环境不同,返回有可能变化,注意通用性
  5.   内部 ID KEY 输出格式已经固定为8个字节模式          本程序用的AT固件版本是1.01 ,内置合法芯片ID 和授权KEY ,并且这条记录已经在安信可云服务器内存在
  6.   安信可的云有多简单?
  7.   1 登录:    55 26 00 A0 00 60 96 96 60 02 DD 1E 00 00 00 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1E DD 26 AC 55
  8.   2 发送数据:55 28 00 AA EE EA 8F 8F EA 02 DD 1E 00 00 00 00 00 00 08 4A 42 85 A9 94 85 0C 00 54 02 45 4D 50 3A 32 35 35 3B 00 42 5C 55
  9.   只要构造出上面的数据包,经过UDP 发送到安信可云服务器,就能通讯了
  10.    
  11.   时间仓促,完成功能后,未经过优化代码优化,和语法风格修改,供参考。辅助文档有这个程序设计框架解释,和详细的指导,这些文件均可以在安信可官网
  12.   WWW.AI-THINKER.COM  ai-cloud 云平台板块得到最新的资讯

  13.       本测试程序在安信可科技50元 的大测试板上正确运行,所有安信可出的的模块从ESP-01到ESP-14均可以正确运行,与远程控制。

  14. */


  15. /*************        本地常量声明        **************/
  16. #define MAIN_Fosc                22118400L        //定义主时钟
  17. #define        RX1_Lenth                32                        //串口接收缓冲长度
  18. #define        BaudRate1                115200UL        //选择波特率
  19. #define        Timer1_Reload        (65536UL -(MAIN_Fosc / 4 / BaudRate1))                //Timer 1 重装值, 对应300KHZ
  20. #define        Timer2_Reload        (65536UL -(MAIN_Fosc / 4 / BaudRate1))                //Timer 2 重装值, 对应300KHZ
  21. #include        "STC15Fxxxx.H"
  22. /*************        本地变量声明        **************/
  23. u8        idata RX1_Buffer[RX1_Lenth];        //接收缓冲
  24. u8        TX1_Cnt;        //发送计数
  25. u8        RX1_Cnt;        //接收计数
  26. bit        B_TX1_Busy;        //发送忙标志
  27. /*************        端口引脚定义        **************/
  28. unsigned char two_lab=0;
  29. sbit LED1=P1^0;//LED1
  30. sbit LED2=P1^1;//LED2
  31. sbit LED3=P3^7;//LED3
  32. sbit DK1=P3^3;//继电器
  33. sbit BEEP=P3^4;//蜂鸣器
  34. sbit K1=P1^3;//按键1
  35. sbit K2=P1^2;//按键2
  36. sbit K3=P1^4;//按键3
  37. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  38. /////这是安信可云平台数据包的全部组成结构,细节可参照安信可的云平台V1.0版本规格书,包结构章节
  39. #define O_PF    0X00  //包头1字节固定0X55
  40. #define O_LEN_L 0X01  //整个包长低字节
  41. #define O_LEN_H 0X02  //整个包长高字节 注意转义码 两个这里只计算一个数据处理!
  42. #define O_CMD_T 0X03  //命令类型
  43. #define O_CMD_C 0X04  //具体命令
  44. #define O_CIX_L 0X05  //本命令序列编号低字节
  45. #define O_CIX_H 0X06  //本命令序列编号高字节
  46. #define O_EXMSH 0X07  //扩展信息高字节
  47. #define O_EXMSL 0X08  //扩展信息低字节
  48. #define O_RESTA 0X09  //数据包状态信息,成功 失败 请求 未知
  49. #define O_DEVID_START 0x0A  //8字节设备识别  低字节在前
  50. #define O_DEVID 0x0A  //8字节设备识别
  51. #define O_TK_LEN      0X12 //1 BYTS TL_LEN          //获得的设备临时通讯令牌长度
  52. #define O_TOKE_START  0X13
  53. #define O_DATAS_START 0X1B
  54. //N BYTS DATAS          //客户的数据包串
  55. //CRC_L    1BYTE          //CRC16 低字节
  56. //CRC_H    1BYTE          //CRC16 高字节
  57. //PACK_END 1BYTE          //包尾1字节固定0X55

  58. ////////////////////////////////////////////////////////////////////////以上定义了包中的各参数的绝对位置//////////////////////////////////
  59. #define uart_rec_tcp_udp_data 0        //系统进入正常网络数据收发状态
  60. #define uart_rec_csysid       1        //系统获取ESP8266WIFI模块的许可号状态,获取四个字节的芯片ID 和 4个字节的授权码
  61. #define uart_rec_smartlink    2        //系统进入获取上网账号密码状态
  62. #define uart_rec_bander       3        //系统进入将本WIFI设备 和APP 手机绑定控制状态
  63. //////////////////////////////////////////////////////////////////////以上部分定义了系统的几种状态///////////////////////////////////////
  64. bit have_tok=0;
  65. bit have_data=0;
  66. unsigned char rec_len=0;
  67. bit                   a_vec=0;                   //设置一个标志位,串口程序 出现指定的字串,并动态过滤到指定的字符后 置1
  68. unsigned char          ceng=0;         //最多 多少字节内 会出现指定字串,静态变量,
  69. unsigned char str_len_limt=16;         //设置一个限定参考数值,在这个参考个数内必定出现指定字符串
  70. unsigned char   str_len_num=11;        //字符个数
  71. char str_ref=':';
  72. /////////////////////////////////////////////////////////////////////上面几个变量用来作为在串口中过滤指定字符串的 限定参数,改变过滤内容后必定先初始化这几个/////
  73. code char CYSYS_code[]="+CSYSID:CHIP";
  74. code char PIPD_code[]="+IPD,";
  75. code char bander_code[]="+IPD,4,26:RPL:";//这里过滤有漏洞
  76. code char smartlink_code[]="SMART SUCCESS";
  77. /////////////////////////////////////////////////////////////////////以上是从WIFI模块串口输出到本单片机串口输入后,本单片机要过滤的各种头部////////////////////
  78. unsigned char uart_rec_sta=uart_rec_csysid;// 串口目前所处于的状态,比如进入正常数据接收,或者SMARTLINK 或者 获取模块的ID。
  79. code unsigned char AT_RST[]="AT+RST";                                                     
  80. code unsigned char AT_MODE[]="AT+CWMODE=1";
  81. code unsigned char AT_CWJAP[]="AT+CWJAP=\"360we\",\"zty0012001\"";
  82. code unsigned char AT_CIP3[]="AT+CIPSTART=3,\"UDP\",\"cloud.ai-thinker.com\",5001,2468,0" ;
  83. code unsigned char temp_bander[]="RPT:\"0xa1b23467\",\"0xaf321234\",\"192.168.0.123\",\"light\",\"123456a\"";
  84. code unsigned char AT_CIPMUX[]="AT+CIPMUX=1";
  85. code unsigned char CIPSTART[]="AT+CIPSTART=4,\"UDP\",\"cloud.ai-thinker.com\",5001,2468,0";
  86. code unsigned char AT_CSYSID[]="AT+CSYSID";
  87. code unsigned char AT_SMARTLINK[]="AT+CWSMARTSTART=1";
  88. code unsigned char ZERO[]="00000000000000000000000000000000001";
  89. code unsigned char CIPSEND_LEN[]="AT+CIPSEND=4,";
  90. code unsigned char CIP3SEND_LEN[]="AT+CIPSEND=3,63";
  91. /////////////////////////////////////////////////////////////////////以上字串是单片机发给串口模块的AT语句有的是直接给WIFI模块的指令,有些是用来拷贝字符串用/////////////

  92. xdata unsigned char at_send_len_ox[20];               
  93. idata unsigned char send_buf[64]="jisifsfhello:99999;oop";                             //发送缓冲区
  94. unsigned char recd_buf[64]= {0x55 ,0x25 ,0x00 ,0xAA ,0xFF ,0x00, 0x00, 0x00, 0x00 ,0x02 ,0x31, 0x0A ,0xFE ,0x00, 0x00, 0x00, 0x00 ,0x00, 0x08, 0x00 ,0x7C ,0xC8, 0x52 ,0xFE, 0x3D ,0x64 ,0x29, 0x4C ,0x49, 0x47, 0x48 ,0x54 ,0x02, 0x3A ,0x3F, 0x6C, 0x02, 0x55};                                                 //接收缓冲区
  95. data unsigned char temp_buf[72];                                 //加工缓冲区
  96. idata unsigned char toke[8]={0x24,0x41,0xD6,0x39,0x48,0x83,0xAC,0x00};//此设备在服务器上获得的令牌包
  97. unsigned char esp_dev_id[8]={0,0,0,0,0,0,0X1E,0XDE};         //    8266的8个字节的器件ID号,可在服务器数据库中查到,唯一标示一个器件,登录过程需要一个器件ID,和数据区放一个数据密码,这么简单登录
  98. unsigned char esp_TOK_id[8]={0,0,0,0,0,0,0,0};                                 //    服务器分给器件器件的令牌包,另外个地方也定义了,完全可以用一个数组完成的
  99. unsigned char esp_user_data[14]={0,0,0,0,0,0,0X1E,0XDE};         //    客户的净数据负荷区,可以很大,因为本款单片机有限,并且一般控制信号,定义几个字节够了!注意在登录的时候,这里是器件密码!
  100. unsigned char temp_cd[]="TEMP:123;";                                                 //    一个数据包,前面是包格式定义,后面是客户数据区,这里定义一个即将要发送的温度数据
  101. unsigned char need_seed_len=0;                                                                 //    全局变量,本次总共需要发到串口的数据
  102. bit t_o=0;                                                                                                         //  在构造一个如00123 的数据时候,去掉前面的00变成123 这里若碰到0就置1
  103. code unsigned char cip3_lcport[]="2469,0";
  104. data unsigned char chip_id[8]={'0','0','0','0','0','0','0','0'};
  105. data unsigned char flash_id[8]={'0','0','0','0','0','0','0','0'};
  106. pdata unsigned char pass_id[8]={'0','0','0','0','0','0','0','0'};

  107. unsigned int time=0; //每隔30秒把一个变量加1,然后把这个变量作为温度数据上报给云平台,转给手机端

  108. xdata unsigned char ssid[32];          //暂存SSID账户信息
  109. xdata unsigned char password[20]; //暂存客户密码
  110. idata char ssid_len=0;                  //记录SSID 长度
  111. idata char pasd_len=0;                          //记录密码长度

  112. bit have_id=0;                                          //记录是否用AT指令获取到了这个模块的ID 和KEY信息
  113. bit have_smartlink=0;                          //记录是否过滤到 从串口来的TCP UDP 数据  smartlink
  114. bit have_bander=0;                                  //记录是从串口中输出的网络数据中过滤到 手机用UDP发来的请求信息

  115. unsigned char stac_a=0;                      //全局专用变量
  116. unsigned char stac_b=0;                          //全局专用变量
  117.                                                                   //
  118. #include "intrins.h"

  119. typedef unsigned char BYTE;
  120. typedef unsigned int WORD;

  121. void IapIdle();
  122. BYTE IapReadBYTE(WORD addr);
  123. #define EEPROM_SSID_LC     0                  //定义SSID 存在FLASH上的相对位置
  124. #define EEPROM_PASSWORD_LC 64                //定义密码 存在FLASH上的相对位置
  125. #define EEPROM_LAB         128                //定义是否已将路由器账户和密码保存到FLASH中



  126. #define CMD_IDLE      0
  127. #define CMD_READ      1
  128. #define CMD_PROGRAM   2
  129. #define CMD_ERASE     3

  130. #define ENABLE_IAP  0X81
  131. #define IAP_ADDRESS 0X1200        //设置客户参数保存的位置,这里选择FLASH的最后一个扇区。


  132. /////////////////////////////////////////////////////////////////下面部分定义了CRC16校验函数用到的表格///////////////////////////////////
  133. code unsigned int crc_table[256]=
  134. {               /* CRC余式表 */
  135. 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
  136. 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
  137. 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
  138. 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
  139. 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
  140. 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
  141. 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
  142. 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
  143. 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
  144. 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
  145. 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
  146. 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
  147. 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
  148. 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
  149. 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
  150. 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
  151. 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
  152. 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
  153. 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
  154. 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
  155. 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
  156. 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
  157. 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
  158. 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
  159. 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
  160. 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
  161. 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
  162. 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
  163. 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
  164. 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
  165. 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
  166. 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
  167. };
  168.    /////////////////////////////////////////////////////////////////上面部分定义了CRC16校验函数用到的表格///////////////////////////////////


  169. /////////////////////////////////////////////////////////////////////以下部分是STC的掉电存储程序,读写内部的EEPROM 保存上网账户和密码////////////////////////
  170. void Delay(BYTE n);
  171. void IapIdle();
  172. BYTE IapReadByte(WORD addr);
  173. void IapProgramByte(WORD addr,BYTE dat);
  174. void IapEraseSector(WORD addr);


  175. void IapIdle()
  176. {
  177.   IAP_CONTR=0;
  178.   IAP_CMD=0;
  179.   IAP_TRIG=0;
  180.   IAP_ADDRH=0X80;
  181.   IAP_ADDRL=0;
  182. }

  183. BYTE IapReadByte(WORD addr)
  184. {
  185.    BYTE dat;
  186.    IAP_CONTR=ENABLE_IAP;
  187.    IAP_CMD=CMD_READ;
  188.    IAP_ADDRL=addr;
  189.    IAP_ADDRH=addr>>8;
  190.    IAP_TRIG=0x5a;
  191.    IAP_TRIG=0xa5;
  192.    _nop_();
  193.    dat=IAP_DATA;
  194.    IapIdle();
  195.    return dat;
  196. }

  197. void IapProgramByte(WORD addr,BYTE dat)
  198. {
  199.   IAP_CONTR=ENABLE_IAP;
  200.   IAP_CMD=CMD_PROGRAM;
  201.   IAP_ADDRL=addr;
  202.   IAP_ADDRH=addr>>8;
  203.   IAP_DATA=dat;
  204.   IAP_TRIG=0x5a;
  205.   IAP_TRIG=0xa5;
  206.   _nop_();
  207.   IapIdle();
  208. }

  209. void IapEraseSector(WORD addr)
  210. {
  211.   IAP_CONTR=ENABLE_IAP;
  212.   IAP_CMD=CMD_ERASE;
  213.   IAP_ADDRL=addr;
  214.   IAP_ADDRH=addr>>8;
  215.   IAP_TRIG=0x5a;
  216.   IAP_TRIG=0xa5;
  217.   _nop_();
  218.   IapIdle();
  219. }
  220. /////////////////////////////////////////////////////////////////////以上部分是STC的掉电存储程序,读写内部的EEPROM 保存上网账户和密码////////////////////////


  221. void make_AT_CIP3(void)
  222. //根据上边 在2468 端口监听到的 广播内容 用广播内容的IP 地址192.168.1.10和端口 48008新建一个3连接,
  223. //AT+CIPSTART=3,"UDP","192.168.1.10",48008,2469,0
  224. ///新建一个连接3
  225. {
  226.   unsigned char a,b;
  227.   for(a=0,b=0;a<21;a++,b++)
  228.   temp_buf[b]=AT_CIP3[b];
  229.   for(a=0;recd_buf[a]!=',';a++,b++)
  230.   temp_buf[b]=recd_buf[a];
  231.   temp_buf[b]=',';
  232.   b++;
  233.   a+=2;
  234.   for(;recd_buf[a]!='"';a++,b++)
  235.   temp_buf[b]=recd_buf[a];
  236.   temp_buf[b]=',';
  237.   b++;
  238.   for(a=0;cip3_lcport[a]!=0;a++,b++)
  239.   temp_buf[b]=cip3_lcport[a];
  240.   temp_buf[b]=0;
  241. }
  242. //将16进制数,变成16进制字符比如10变成A
  243. char back_char(unsigned char user_d)
  244. {
  245.   if(user_d<10)
  246.   return (user_d+'0');
  247.   else
  248.   return (user_d-10+'A');
  249. }
  250. ////制作 向手机发送如下格式UDP数据
  251. ////RPT:"0x00FE6738","0xB8B3C281","192.168.0.123","light","123456a"
  252. void make_bander_data()
  253. {
  254.   unsigned char a,b=0;
  255.   for(a=0;temp_bander[a]!=0;a++)
  256.   temp_buf[a]=temp_bander[a];
  257.   temp_buf[a]=0;

  258.   //以上硬拷贝 code unsigned char temp_bander[]="RPT:\"0xa1b23467\",\"0xaf321234\",\"192.168.0.123\",\"light\",\"123456a\"";到 temp_buf
  259.   //以下语句修改RPT:"0x00FE6738","0xB8B3C281","192.168.0.123","light","123456a" 中将本身的设备ID(如0x00FE6738) 和 KEY(0xB8B3C281)放到上面修改后的temp_buf
  260.   //后面的 "light","123456a"  为本设备名字,和本设备的密码,暂时未用 可随便填写

  261.   temp_buf[7]=back_char(esp_dev_id[4]>>4);
  262.   temp_buf[8]=back_char(esp_dev_id[4]&0x0f);
  263.   temp_buf[9]=back_char(esp_dev_id[5]>>4);
  264.   temp_buf[10]=back_char(esp_dev_id[5]&0x0f);
  265.   temp_buf[11]=back_char(esp_dev_id[6]>>4);
  266.   temp_buf[12]=back_char(esp_dev_id[6]&0x0f);
  267.   temp_buf[13]=back_char(esp_dev_id[7]>>4);
  268.   temp_buf[14]=back_char(esp_dev_id[7]&0x0f);

  269.   temp_buf[20]=back_char(esp_user_data[7]>>4);
  270.   temp_buf[21]=back_char(esp_user_data[7]&0x0f);
  271.   temp_buf[22]=back_char(esp_user_data[6]>>4);
  272.   temp_buf[23]=back_char(esp_user_data[6]&0x0f);
  273.   temp_buf[24]=back_char(esp_user_data[5]>>4);
  274.   temp_buf[25]=back_char(esp_user_data[5]&0x0f);
  275.   temp_buf[26]=back_char(esp_user_data[4]>>4);
  276.   temp_buf[27]=back_char(esp_user_data[4]&0x0f);
  277. }

  278. void make_AT_SEND(unsigned char a_len)   //生成右边这样的指令,将参数a_len 改成10进制,右边这条指令  "AT+CIPSEND=XX" XX是发送的数量
  279. {
  280.   unsigned char aa=0;
  281.   for(aa=0;aa<13;aa++)
  282.   {
  283.     at_send_len_ox[aa]=CIPSEND_LEN[aa];         //剪贴"AT+CIPSEND= 到RAM  后面的十进制参数由下面的部分生成
  284.   }
  285.   t_o=0;                                 //去掉前面的0,比如发送38个字节,038,前面的0就可以去掉了。
  286.   if((a_len/100))
  287.   {
  288.   at_send_len_ox[aa]=a_len/100+'0';
  289.   aa++;
  290.   t_o=1;
  291.   }
  292.   if((a_len%100)/10)
  293.   {
  294.   at_send_len_ox[aa]=(a_len%100)/10+'0';
  295.   aa++;
  296.   t_o=1;
  297.   }
  298.   else if(t_o)
  299.   {
  300.     at_send_len_ox[aa]=0+'0';
  301.         aa++;
  302.   }
  303.   at_send_len_ox[aa]=(a_len%10)+'0';
  304.   aa++;
  305.   at_send_len_ox[aa]=0;
  306. }
  307. //下面函数获得CRC校验码 采用标准CRC16 初始CRC=0XFFFF  运算多项式参数 8005 非1021
  308. unsigned int GetRevCrc_16(unsigned char * pData, int nLength)
  309. {
  310.   unsigned int cRc_16 = 0xffff;
  311.   unsigned char temp;
  312.   while(nLength-- > 0)
  313.   {
  314.     temp = cRc_16&0xff;
  315.     cRc_16 = (cRc_16 >> 8) ^ crc_table[(temp ^ *pData++) & 0xFF];
  316.   }
  317.   return cRc_16;   
  318. }
  319. //下面这个函数构造一个发送的数据格式,请看数据格式文档,完全可以用结构体完成,这里采用数据,从上到下描述这个数据包
  320. //发送的数据包,目前只有登录数据包,和上报温度数据包,这两个基本的数据包,上报数据包可以充当心跳包,第一个参数决定着,是发送登录包还是温度包
  321. //其他几个入口参数是器件ID,令牌包,以及客户的数据,以及客户数据长度

  322. void make_send_pack(unsigned char ms_opt,unsigned char *dev_id,unsigned char *toke_id,unsigned char *use_data,unsigned char use_data_len)
  323. {
  324.   unsigned char a,b,i=0;
  325.   unsigned esp_crc=0;
  326.   send_buf[0]=0x55;                                                     //包头是0X55固定
  327.   
  328.   send_buf[O_LEN_L]=(O_DATAS_START+use_data_len+3)%0xff; //本数据包的所有数据长度,包头至包尾,记得是没有经过转义前的包长
  329.   send_buf[O_LEN_H]=(O_DATAS_START+use_data_len+3)/0xff;

  330.   if(ms_opt==0)                                                                                         //根据入口参数判断是发送登录链路操作,还是发送数据包云平台
  331.   send_buf[O_CMD_T]=0XA0;// 0XA0 链路操作 0XAA 数据传输 0XAC 实时检测指令 0XF0 终端操作
  332.   else if (ms_opt==1)
  333.   send_buf[O_CMD_T]=0XAA;// 0XA0 链路操作 0XAA 数据传输 0XAC 实时检测指令 0XF0 终端操作

  334.   if(ms_opt==0)                                                                //0X00代表登录操作
  335.   send_buf[O_CMD_C]=0X00;// reg  option
  336.   else if (ms_opt==1)
  337.   send_buf[O_CMD_C]=0XEE;                                                    //0XEE代表数据是从设备到云平台的方向

  338.   send_buf[O_CIX_L]=0XF3;// CMD INDEXL                        //命令序列编号,暂时不用,可以作为对方应答的数据包号标示
  339.   send_buf[O_CIX_H]=0XC0;//        CMD INDEXL                                        //命令序列编号,暂时不用,可以作为对方应答的数据包号标示
  340.   send_buf[O_EXMSH]=0XC0;//        EXTERN MESSAGE1                                //扩展子暂时保留
  341.   send_buf[O_EXMSL]=0XF3;//        EXTERN MESSAGE2                                //扩展子暂时保留

  342.   send_buf[O_RESTA]=0X02;//        CMD_STA 00 OK 01 FAIL 02 SEND 03 NO SUP         //代表本数据包的状态,是发送还是应答成功还是失败

  343.   for(i=0;i<8;i++)
  344.   send_buf[O_DEVID+i]=*(dev_id+(7-i)); // 拷贝设备的唯一ID号到数据包里


  345.   send_buf[O_TK_LEN] =8;                   //代表接下来的令牌包是8个字节


  346.   for(i=0;i<8;i++)
  347.   send_buf[O_TOKE_START+i]=*(toke_id+i);//8个字节令牌包,初始令牌包为00 后续服务器会分配一个令牌包给这个设备,设备每次通讯要携带这个令牌包


  348.   for(i=0;i<use_data_len;i++)
  349.   send_buf[O_DATAS_START+i]=*(use_data+i); // 客户的数据区,登录的时候放数据密码文本
  350.   
  351.   temp_buf[0]=0x55;                                                   //包尾

  352.   esp_crc=GetRevCrc_16(send_buf,O_DATAS_START+use_data_len);//得到转义之前的总数据包CRC,具体可以参照CRC数据格式,因此CRC是针对转义之前的数据生成

  353.   for(a=1,b=1;a<(O_DATAS_START+use_data_len);a++)           //将出去包头,所有的数据中含有有0X55的数据转义成0X54,0X01,将0X54 变成0X54,02,重新转义数据包
  354.   {
  355.     if(send_buf[a]==0x55)
  356.         {
  357.           temp_buf[b]=0x54;
  358.           b+=1;
  359.           temp_buf[b]=0x01;
  360.           b+=1;
  361.         }
  362.         else if(send_buf[a]==0x54)
  363.         {
  364.           temp_buf[b]=0x54;
  365.           b+=1;
  366.           temp_buf[b]=0x02;
  367.           b+=1;
  368.         }
  369.         else
  370.         {
  371.         temp_buf[b]=send_buf[a];
  372.         b+=1;
  373.         }
  374. }         ///////////////////////////////////////////////////////////以上的语句转义数据包中除包头到CRC之前的全部的数据///////////////////////////////////////////////////////////////////////
  375. //55 28 00 AA EE F3 C0 C0 F3 02 E6 1E 00 00 00 00 00 00 08 24 41 D6 39 48 83 AC 00 54 02 45 4D 50 3A 32 35 35 3B 00 D1 52 55
  376. //55 28 00 AA EE F3 C0 C0 F3 02 E6 1E 00 00 00 00 00 00 08 24 41 D6 39 48 83 AC 00 54 02 45 4D 50 3A 32 35 35 3B 00 D1 52 55

  377. temp_buf[b]=(esp_crc>>8);
  378. b+=1;
  379. temp_buf[b]=(esp_crc&0x00ff);         
  380. b+=1;
  381.     ///////////////////////////////////////////////////////////上面两句加上CRC校验////////////////////////////////////////
  382. temp_buf[b]=0x55;        //包尾
  383. b+=1;
  384. temp_buf[b]=0x0d;
  385. b+=1;
  386. temp_buf[b]=0x0a;
  387. b+=1;                                //以上构成回车
  388. need_seed_len=b;        //至此构造出了需要发送的全部数据 包括AT指令需要的换行
  389. temp_buf[b]=0x00;
  390. }



  391. void Delay1(unsigned long ms)//简单延迟函数,单位是毫秒
  392. {
  393.         unsigned char i, j,k;
  394.         for(k=0;k<ms;k++)
  395.         {
  396.                 _nop_();
  397.                 _nop_();
  398.                 i = 22;
  399.                 j = 128;
  400.                 do
  401.                 {
  402.                         while (--j);
  403.                 } while (--i);
  404.         }
  405. }


  406. void Delay2(unsigned long cnt)
  407. {
  408.         long i;
  409.         for(i=0;i<cnt*100;i++);
  410. }

  411. void at_uart_send_str(unsigned char *str)//发送AT字符串到串口
  412. {
  413.   unsigned char *st_p=str;
  414.   do{
  415.      SBUF=*st_p;
  416.          st_p++;
  417.          Delay1(1);
  418.         }while(*st_p);
  419.         SBUF='\r';
  420.         Delay1(1);
  421.         SBUF='\n';
  422.         Delay1(1);
  423. }
  424. void at_uart_send_buf(unsigned char *str,unsigned char len)//发送数据缓冲区的非字符串信息,数据流信息到串口
  425. {
  426.   unsigned char *st_p=str;
  427.   
  428.   while(len){
  429.      SBUF=*st_p;
  430.          st_p++;
  431.          Delay1(1);
  432.          len--;
  433.         }while(*st_p);
  434.         Delay1(1);
  435. }


  436. void change_pack()                                          //把接收到的数据包转义过来,0X55 转义成0X54 0X01 0X54 替换成0X54 02
  437. {
  438.                                      for(stac_a=1,stac_b=1;recd_buf[stac_a]!=0x55;)
  439.                                    {
  440.                                      if((recd_buf[stac_a]==0x54)&&(recd_buf[stac_a+1]==0x01))
  441.                                          {
  442.                                          temp_buf[stac_b]=0x55;
  443.                                          stac_b++;
  444.                                          stac_a+=2;
  445.                                          }
  446.                                          else if((recd_buf[stac_a]==0x54)&&(recd_buf[stac_a+1]==0x02))
  447.                                          {
  448.                                          temp_buf[stac_b]=0x54;
  449.                                          stac_b++;
  450.                                          stac_a+=2;
  451.                                          }
  452.                                          else
  453.                                          {
  454.                                            temp_buf[stac_b]=recd_buf[stac_a];
  455.                                            stac_b++;
  456.                                            stac_a++;
  457.                                          }
  458.                                   }
  459.                                   temp_buf[stac_b]=0x55;
  460.                                   temp_buf[0]=0x55;
  461.                                   recd_buf[0]=temp_buf[0];
  462.                                   for(stac_a=1;temp_buf[stac_a]!=0x55;stac_a++)
  463.                                   recd_buf[stac_a]=temp_buf[stac_a];
  464.                                   recd_buf[stac_a]=0x55;
  465.                                   recd_buf[0]=0x55;
  466. }
  467. void init_uart(void)
  468. {
  469.           B_TX1_Busy = 0;
  470.         RX1_Cnt = 0;
  471.         TX1_Cnt = 0;
  472.         S1_8bit();                                //8位数据
  473.         S1_USE_P30P31();                //UART1 使用P30 P31口        默认
  474.         AUXR &= ~(1<<4);        //Timer stop                波特率使用Timer2产生
  475.         AUXR |= 0x01;                //S1 BRT Use Timer2;
  476.         AUXR |=  (1<<2);        //Timer2 set as 1T mode
  477.         TH2 = (u8)(Timer2_Reload >> 8);
  478.         TL2 = (u8)Timer2_Reload;
  479.         AUXR |=  (1<<4);        //Timer run enable
  480.         REN = 1;        //允许接收
  481.         ES  = 1;        //允许中断
  482.         EA = 1;                //允许全局中断
  483.         P3M1 = 0x00;
  484.     P3M0 = 0xFF;
  485.         RX1_Cnt=0;
  486.         DK1=0;
  487.         BEEP=0;
  488. }
  489. bit have_config=0;
  490. void main(void)
  491. {
  492.         char tt,i,k,n,z=0;
  493.         unsigned int h=0;
  494.         //////////////////////////////////////////////////////////////////////////////////////下面部分为定时器以及串口初始化/////////////////////
  495.         init_uart();
  496.         Delay2(1000);
  497.         if(K1==0)           //开机的时候发现按键1也就是MCU_P1.3 被按下,那么清除单片机中EEPROM存的数据
  498.         {
  499.                 IapEraseSector(IAP_ADDRESS);  //擦除客户EEPROM扇区 512字节
  500.                         LED2=0;
  501.                         BEEP=1;
  502.                         Delay2(200);
  503.                     LED2=1;
  504.                         BEEP=0;      //闪亮心跳指示灯,和心跳音
  505.         }
  506.         Delay2(300);
  507.         if(IapReadByte(IAP_ADDRESS+EEPROM_LAB)==0x55) //开机后检测是否已经保存了客户的信息在EEPROM中
  508.         have_config=0;
  509.         else
  510.         have_config=1; //EEPROM没有记录客户的路由器账户和密码,需要配置
  511.         ///////////////////////////////////////////////////////////////////////////////////以上部分主要完成串口的初始化////////////////////////////
  512.         for(;;)
  513.         {         
  514.         a_vec=0;                          //出现指定的字串,并动态过滤到指定的字符后 置1
  515.         ceng=0;                   //最多 多少字节内 会出现指定字串,静态变量,
  516.         str_len_limt=22;          //设置一个限定参考数值,在这个参考个数内必定出现指定字符串
  517.         str_len_num=13;           //要过滤连续字符个数
  518.         str_ref=':';                          // 过滤到字符串后,接着要出现的字符,这个字符出现的位置才是绝对0位置
  519.                 uart_rec_sta=uart_rec_smartlink; //设置在串口中的过滤分支条件,串口中断中,根据这个标志调用不同的字符串过滤参数

  520.                 at_uart_send_str(AT_MODE);                 //设置模块进入STATION 模式
  521.                 Delay2(1000);
  522.                 if(have_config)                                         //需要配置 模块连入本地的路由器账户和密码
  523.                 {
  524.                 at_uart_send_str(AT_SMARTLINK);         //发送进入SMARTLINK AT指令
  525.                 Delay2(2000);
  526.                 }
  527.                 else
  528.                 have_smartlink=1;                                 //否则设置已经进入过SMARTLINK 状态

  529.                 do                                                                 //此循环完成SMARTLINK 的配置
  530.                 {
  531.                 LED1=0;
  532.                 LED2=0;
  533.                 LED3=0;
  534.                 Delay2(200);
  535.                 LED1=1;
  536.                 LED2=1;
  537.                 LED3=1;
  538.                 Delay2(200);
  539.                 if(have_smartlink)//假如从串口中获得正确的 SMARTLINK 用户路由器账户和密码
  540.                 {
  541.                    if(have_config)//需要客户重新设置路由器账户和密码
  542.                    {
  543.                          for(i=0;recd_buf[i]!=0x0d;i++)
  544.                          {
  545.                                 ssid_len++;
  546.                                 ssid[i]=recd_buf[i];                                  //拷贝串口缓冲区中的用户路由器名字
  547.                                 IapProgramByte(IAP_ADDRESS+EEPROM_SSID_LC+i+1,recd_buf[i]);    //存储客户账户到EEPROM中
  548.                          }
  549.                          IapProgramByte(IAP_ADDRESS+EEPROM_SSID_LC,ssid_len);                           //存储客户的账户长度到EEPROM中
  550.                          for(i=0;recd_buf[ssid_len+11+i]!='\r';i++)
  551.                          {
  552.                                 password[i]=recd_buf[ssid_len+11+i];                               //拷贝串口缓冲区中的用户路由器密码
  553.                                 IapProgramByte(IAP_ADDRESS+EEPROM_PASSWORD_LC+i+1,password[i]);//存储客户密码到EEPROM中
  554.                                 pasd_len++;                                                                                                          
  555.                          }

  556.                          IapProgramByte(IAP_ADDRESS+EEPROM_PASSWORD_LC,pasd_len);          //存储客户的密码长度到EEPROM中
  557.                          IapProgramByte(IAP_ADDRESS+EEPROM_LAB,0x55);
  558.                    }
  559.                    else        //无需用SMARTLINK 方式获取路由器账户和秘密,账户和密码直接从单片机的EEPROM直接读取
  560.                    {
  561.                     ssid_len=IapReadByte(IAP_ADDRESS+EEPROM_SSID_LC);         //从EEPROM中的账户长度
  562.                         pasd_len=IapReadByte(IAP_ADDRESS+EEPROM_PASSWORD_LC);//从EEPROM中的密码长度
  563.                     for(i=0;i<ssid_len;i++)
  564.                         {
  565.                         ssid[i]=IapReadByte(IAP_ADDRESS+EEPROM_SSID_LC+i+1); //从EEPROM中读取账户信息到RAM中
  566.                         }
  567.                         for(i=0;i<pasd_len;i++)
  568.                         {
  569.                         password[i]=IapReadByte(IAP_ADDRESS+EEPROM_PASSWORD_LC+i+1); //从EEPROM中读取密码信息到RAM中
  570.                         }
  571.                    }
  572.                 //code unsigned char AT_CWJAP[]="AT+CWJAP=\"360we\",\"zty0012001\"";
  573.                         n=0;
  574.                         for(i=0;i<63;i++)
  575.                     temp_buf[i]=0;                //清空临时缓冲区

  576.                         for(i=0;i<10;i++,n++)
  577.                         temp_buf[n]=AT_CWJAP[i];      //拷贝AT指令加入路由器的格式头AT+CWJAP="

  578.                         for(i=0;i<ssid_len;i++,n++)          //用SMARTLINK 获得的 SSID 和PASSWORLD 填充 加入路由器所需要的两个参数        AT+CWJAP="360we","zty0012001"
  579.                         temp_buf[n]=ssid[i];
  580.                         temp_buf[n]='"';
  581.                         n++;
  582.                         temp_buf[n]=',';
  583.                         n++;
  584.                         temp_buf[n]='"';
  585.                         n++;
  586.                         for(i=0;i<pasd_len;i++,n++)
  587.                         temp_buf[n]=password[i];
  588.                         temp_buf[n]='"';                         //以上语句构造出:AT+CWJAP="360we","zty0012001" 这样的指令,其中路由器账户和密码 随客户变动
  589.                 }
  590.             }while(have_smartlink==0); //此循环完成SMARTLINK 的配置

  591.                 LED1=1;
  592.                 LED2=1;
  593.                 LED3=1;
  594.             //////////////////////////////////////////////////////////下面的语句获得模块的设备ID/////////////////////////////////////////////////////////////
  595.         a_vec=0;                          //出现指定的字串,并动态过滤到指定的字符后 置1
  596.         ceng=0;                   //最多 多少字节内 会出现指定字串,静态变量,
  597.         str_len_limt=16;          //设置一个限定参考数值,在这个参考个数内必定出现指定字符串
  598.         str_len_num=12;           //要过滤的字符个数 +CSYSID:CHIP: 为下一个字符留个位置: 因此是12个字符
  599.         str_ref=':';                          // 要过滤到的字符
  600.                 uart_rec_sta=uart_rec_csysid;
  601.                 at_uart_send_str(AT_CSYSID); //返回如下:+CSYSID:CHIP:00FE6738;FLASH:001640EF;KEY:81C2B3B8;
  602.                 Delay2(2000);                                 //延时两秒后,串口中必定输出 所需要的器件ID FLASH ID 和KEY
  603.                 if(have_id)                                         //从串口中获取了芯片的ID 信息 和KEY 以及FLASH 信息
  604.                 {
  605.                 have_id=0;
  606.                 k=0;
  607.                 for(i=0,tt=0;i<8;i++,tt++)        //  获取模块内部的芯片ID                          
  608.                 chip_id[tt]=recd_buf[i];
  609.                 for(i=15,tt=0;i<23;i++,tt++)//  获取模块内部的FLASH ID
  610.                 flash_id[tt]=recd_buf[i];
  611.                 for(i=28,tt=0;i<36;i++,tt++)//  获取模块内部的KEY
  612.                 pass_id[tt]=recd_buf[i];
  613.         //下面的语句将获取的16进制字符换成 16进制数据,8个字节的字符最总得到四个字节的16进制数据 比如字符串"A2345678"最终变成0XA2,0X34,0X56,0X78 四个字节存放
  614.             for(i=0;i<8;i++)            
  615.             {
  616.                           if((chip_id[i]>='A')&&(chip_id[i]<='F'))
  617.                           chip_id[i]=(chip_id[i]-'A'+10);
  618.                           else if((chip_id[i]>='a')&&(chip_id[i]<='f'))
  619.               chip_id[i]=(chip_id[i]-'a'+10);
  620.                           else
  621.                           chip_id[i]-='0';
  622.             }
  623.                                
  624.                 for(i=0;i<8;i++)
  625.             esp_dev_id[i]=0;

  626.                 esp_dev_id[7]=((chip_id[6])<<4)+chip_id[7];// 将字符串16进制转换后,变成16进制数据四个字节存放到对应内存中
  627.                 esp_dev_id[6]=((chip_id[4])<<4)+chip_id[5];
  628.                 esp_dev_id[5]=((chip_id[2])<<4)+chip_id[3];
  629.                 esp_dev_id[4]=((chip_id[0])<<4)+chip_id[1];
  630.                 //将获取的16进制字符换成 16进制数据,8个字节的字符最总得到四个字节的16进制数据 比如字符串"A2345678"最终变成0XA2,0X34,0X56,0X78 四个字节存放
  631.             for(i=0;i<8;i++)
  632.             {
  633.                           if((pass_id[i]>='A')&&(pass_id[i]<='F'))
  634.                           pass_id[i]=(pass_id[i]-'A'+10);
  635.                           else if((pass_id[i]>='a')&&(pass_id[i]<='f'))
  636.               pass_id[i]=(pass_id[i]-'a'+10);
  637.                           else
  638.                           pass_id[i]-='0';
  639.             }
  640.                 for(i=0;i<8;i++)
  641.                 flash_id[i]=0;

  642.                 flash_id[7]=((pass_id[6])<<4)+pass_id[7];// 将字符串16进制转换后,变成16进制数据四个字节存放到对应内存中
  643.                 flash_id[6]=((pass_id[4])<<4)+pass_id[5];
  644.                 flash_id[5]=((pass_id[2])<<4)+pass_id[3];
  645.                 flash_id[4]=((pass_id[0])<<4)+pass_id[1];

  646.                 for(i=0;i<8;i++)
  647.             esp_user_data[i]=flash_id[i];

  648.                 // 以上操作将模块输出的内部字符串形式的芯片ID 和KEY (都是4个字节的)换成16进制 存放到内存中,在登录服务器的时候的两个必要参数。
  649.                 //////////////////////////////////////////////////////////上面的语句获得模块的设备ID和KEY/////////////////////////////////////////////////////////////
  650.                 }
  651.                 //while(1);
  652.                 //////////////////////////////////////////////////////////下面的语句发送AT指令加入内网,并链接到安信可物联网服务器/////////////////////

  653.                 a_vec=0;                          //出现指定的字串,并动态过滤到指定的字符后 置1
  654.         ceng=0;                   //最多 多少字节内 会出现指定字串,静态变量,
  655.         str_len_limt=16;          //设置一个限定参考数值,在这个参考个数内必定出现指定字符串
  656.         str_len_num=7;            //字符个数
  657.         str_ref='"';
  658.                 uart_rec_sta=uart_rec_bander;

  659.                 Delay2(2000);
  660.         at_uart_send_str(AT_MODE);
  661.                 Delay2(2000);
  662.         at_uart_send_str(temp_buf); //temp_buf 中此时存放的是  AT+CWJAP="360we","zty0012001"        这样的AT指令,这一步加入路由器中
  663.                 Delay2(10000);
  664.                 at_uart_send_str(AT_CIPMUX);//进入多连接模式,单连接其实也可以的
  665.                 Delay2(2000);
  666.         at_uart_send_str(CIPSTART);        //用UDP方式连接到安信可的云,连接到目标5001安信可云服务,顺便监听 2468 端口,code unsigned char CIPSTART[]="AT+CIPSTART=4,\"UDP\",\"cloud.ai-thinker.com\",5001,2468,0"
  667.                 Delay2(2000);
  668.                
  669.                 if(have_config)                           //客户需要重新配置,这个时候也顺便把模块和手机的绑定关系建立:原理是模块把芯片ID和KEY经过UDP发给手机,手机把这个合法ID上报给服务器,从而绑定!
  670.                 {                                                   //过程是手机在和模块同一个局域网后,手机发送UDP到2468端口,而上一步,模块在监听2468端口!手机发送的UDP包内容是RPL:"192.168.1.10","48008"
  671.                 do                                                   //其实手机是把自己现在的IP地址192.168.1.10 和即将监听的端口48008 告诉模块,然后模块就可以把自己的芯片ID 和KEY授权 各四个字节 回送给手机
  672.                 {                                                   //因此任何一个手机只要获得这个模块的芯片ID 和KEY ,即可向服务器利用这个信息,进行控制权申请,也就是绑定!
  673.                 LED1=0;
  674.                 LED2=0;
  675.                 LED3=0;
  676.                 Delay2(200);
  677.                 LED1=1;
  678.                 LED2=1;
  679.                 LED3=1;
  680.                 Delay2(200);
  681.                
  682.                 if(have_bander)
  683.                 {
  684.                   ;
  685.                 }

  686.                 }while(have_bander==0);        //监听局域网内手机向2468端口(2468端口和连接4绑定) 发出的UDP扫描信息,获得RPL:"192.168.1.10","48008"  手机透露自己的IP和端口
  687.                  
  688.                  make_AT_CIP3();                                    //根据上边 在2468 端口监听到手机透露的IP地址和端口 构造一条建立连接指令如右边示意:AT+CIPSTART=3,"UDP","192.168.1.10",48008,2469,0
  689.                  at_uart_send_str(temp_buf);         //发送出上面构造的连接到AT指令,模块得以执行上面构造的AT指令
  690.                  Delay2(2000);
  691.                  make_bander_data();                     //从绑定手机和设备关系的处理中,构造出如右边的UDP数据:RPT:"0x00FE6738","0xB8B3C281","192.168.0.123","light","123456a"
  692.                  at_uart_send_str(CIP3SEND_LEN); //发送AT指令,告诉模块即将经过路由器发给手机的数据长度,  code unsigned char CIP3SEND_LEN[]="AT+CIPSEND=3,63";
  693.                  Delay2(1000);
  694.                  at_uart_send_str(temp_buf);         //发送构造好的UDP数据!
  695.                  Delay2(2000);
  696.                  }                                                                 //根据上面的几个步骤,手机获取到了模块的芯片ID 和 KEY ID,手机得到后会利用这个信息让服务器绑定它们两个

  697.                 //////////////////////////////////////////////////////////上面面的语句发送AT指令加入内网,并链接到安信可物联网服务器/////////////////////
  698.                 at_uart_send_str(AT_MODE);
  699.                 a_vec=0;                          //出现指定的字串,并动态过滤到指定的字符后 置1
  700.         ceng=0;                   //最多 多少字节内 会出现指定字串,静态变量,
  701.         str_len_limt=12;          //设置一个限定参考数值,在这个参考个数内必定出现指定字符串
  702.         str_len_num=5;            //字符个数
  703.         str_ref=':';
  704.                 uart_rec_sta=uart_rec_tcp_udp_data;

  705.                 make_send_pack(0,esp_dev_id,esp_TOK_id,esp_user_data,8);//构造登录数据包
  706.                 make_AT_SEND(need_seed_len);                            //将要进过WIFI发送的总字节数变成10进制,动态生成发送数据AT指令
  707.                 two_lab=0;                                                                                                ////////////////////////////////////////////////////////////////////两个55计数!!有可能错乱
  708.         at_uart_send_str(at_send_len_ox);                       //将构造好的AT发送数据到互联网的动态发送数据长度
  709.                 Delay2(2000);
  710.                 at_uart_send_buf(temp_buf,need_seed_len);                                //经过WIFI模块发送构造好的登录包
  711.                 Delay2(4000);

  712.                 //while(1);

  713.                 while(1)
  714.                 {                                                                                                         //主循环体中,每30秒构造一个上传数据,上传数据每次加1.
  715.                         for(tt=0;tt<60;tt++)
  716.                         {
  717.                         Delay2(200);
  718.                         Delay2(200);
  719.                     }
  720.                     make_send_pack(1,esp_dev_id,toke,temp_cd,10);    //构造上传数据到云,转给手机的温度数据包,符合基本数据格式
  721.                     make_AT_SEND(need_seed_len);                                          //动态构造发送AT指令
  722.                         at_uart_send_str(at_send_len_ox);                //发送构造好的发送指令
  723.                     Delay2(2000);
  724.                     at_uart_send_buf(temp_buf,need_seed_len);             //经过WIFI发送数据

  725.                         LED2=0;
  726.                         BEEP=1;
  727.                         Delay2(200);
  728.                     LED2=1;
  729.                         BEEP=0;                                         //闪亮心跳指示灯,和心跳音
  730.                                                                                                                         //每30秒会运行到这里一次。更新一次温度数值
  731.                         time++;
  732.                         temp_cd[5]=(((time%1000)/100)+'0');
  733.                         temp_cd[6]=(((time%100)/10)+'0');
  734.                     temp_cd[7]=(((time%10))+'0');
  735.                 }
  736.         }
  737.         Delay2(2000);
  738. }

  739. /********************* 字符串过滤函数初始参数************************/
  740. /*
  741. bit a_vec=0;                          //出现指定的字串,并动态过滤到指定的字符后 置1
  742. unsigned char ceng=0;         //最多 多少字节内 会出现指定字串,静态变量,
  743. unsigned char str_len_limt=12;//设置一个限定参考数值,在这个参考个数内必定出现指定字符串
  744. unsigned char str_len_num=5;  //字符个数
  745. char str_ref=':';
  746. code char test_code[]="+IPD,";
  747. */

  748. void fit_stb(unsigned char *str_p) // 每次串口接收到一个字符都会进入本过滤函数,看是否过滤到指定的字符串。
  749. {
  750.    if((a_vec==0)&&(ceng<str_len_limt))
  751.    {
  752.       if(ceng<str_len_num)
  753.           {
  754.       if(SBUF==(*(str_p+ceng)))
  755.           ceng++;
  756.           else
  757.           ceng=0;
  758.           }
  759.           else
  760.           {
  761.                 ceng++;
  762.                 if(SBUF==str_ref)
  763.                 {
  764.                   a_vec=1;
  765.                   ceng=0;       
  766.                 }
  767.           }
  768.           RX1_Cnt=0;
  769.    }
  770.    else if(ceng>=str_len_limt)
  771.    {
  772.                a_vec=0;
  773.                   ceng=0;
  774.    }
  775. }

  776. //unsigned char
  777. void UART1_int (void) interrupt UART1_VECTOR
  778. {
  779.         if(RI)
  780.         {
  781.                 RI = 0;
  782.                 if(a_vec==0)//上次未曾过滤到指定的字符串中所有的字符出现,每次只过滤一个字符
  783.                 {
  784.                  switch(uart_rec_sta)              //根据系统的状态,决定过滤哪个字符
  785.                  {
  786.                   case uart_rec_tcp_udp_data: //串口进入正常的UDP TCP 数据收发
  787.                   fit_stb(PIPD_code);                  //过滤数据接收头
  788.                   break;
  789.                   case  uart_rec_csysid:          //串口进入获得模块内部ID 和KEY 状态
  790.                   fit_stb(CYSYS_code);              //过滤指定的头部
  791.                   break;
  792.                   case uart_rec_smartlink:          //串口进入获得客户的路由器账户密码状态
  793.                   fit_stb(smartlink_code);
  794.                   break;
  795.                   case uart_rec_bander:
  796.                   fit_stb(bander_code);
  797.                  }
  798.                 }
  799.                 else//////////////////////////////过滤到指定的头部
  800.                 {
  801.                
  802.                  recd_buf[RX1_Cnt] = SBUF;                //保存一个字节
  803.                  if(recd_buf[RX1_Cnt]==0X55)    //记录0X55的个数,出现两次后,代表一个有数据包结束
  804.                  two_lab++;
  805.                  if(RX1_Cnt<62)        /////////////////////防止64字节的缓冲区溢出
  806.                  RX1_Cnt++;
  807.                  else                        ///////每次收到的指令超过64字节,就把数据清空,接收指针指向开头
  808.                  {
  809.                    RX1_Cnt=0;
  810.                    a_vec=0;
  811.                    two_lab=0;
  812.                  }
  813.                  switch(uart_rec_sta)
  814.                   {
  815.                     case uart_rec_tcp_udp_data:
  816.                         //have_dd=1;
  817.                            //LED2=0;
  818.                                 if(two_lab==2)//////////////////////////////////////////得到一包有效的数据!取出2个OX55之间的有效数据////////////////////
  819.                                  {
  820.                                    a_vec=0;
  821.                                    rec_len=RX1_Cnt;
  822.                                    two_lab=0;
  823.                                    RX1_Cnt=0;
  824.                    LED1=0;
  825.                                    LED2=0;
  826.                                    LED3=0;

  827.                                    change_pack();
  828.                                    have_data=1;
  829.                                     if((recd_buf[32])==':')              /////////////////////////////////////简单得到手机的开关指令////////////////////
  830.                                         {
  831.                                          if((recd_buf[33])=='0')
  832.                                          {
  833.                                           DK1=0;
  834.                                           LED1=1;          //关灯指令
  835.                                          }
  836.                                          else if((recd_buf[33])=='1')
  837.                                          {
  838.                                           DK1=1;
  839.                                       LED1=0;    //开灯指令
  840.                                          }
  841.                                         }
  842.                                         if((recd_buf[3]==0xa0)&&(recd_buf[9]==0x00)&&(have_tok==0))////////////////////获得TOKE包//////////////////////////////////
  843.                                         {
  844.                                           have_tok=1;
  845.                                           toke[7]=recd_buf[19];             
  846.                                           toke[6]=recd_buf[20];               
  847.                                           toke[5]=recd_buf[21];       
  848.                                           toke[4]=recd_buf[22];                 
  849.                                           toke[3]=recd_buf[23];
  850.                                           toke[2]=recd_buf[24];
  851.                                           toke[1]=recd_buf[25];
  852.                                           toke[0]=recd_buf[26];

  853.                                         }
  854.                                  }
  855.                         break;
  856.                    case  uart_rec_csysid:
  857.                    if(RX1_Cnt>40)
  858.                    have_id=1;
  859.                    break;
  860.                    case  uart_rec_smartlink:
  861.                    if(RX1_Cnt>10)
  862.                    have_smartlink=1;
  863.                    break;
  864.                    case  uart_rec_bander:
  865.                    if(RX1_Cnt>20)
  866.                    have_bander=1;
  867.                    break;
  868.                  };
  869.           }
  870.         }
  871.         if(TI)
  872.         {
  873.                 TI = 0;
  874.                 B_TX1_Busy = 0;                //清除发送忙标志
  875.         }
  876. }
复制代码
  1. /*
  2.   注意:变量初始化成0,否者随机  数组注意溢出问题  0X55 在其他数据中有可能出现,并造成混乱,主要是计数  过滤数据,根据网络环境不同,返回有可能变化,注意通用性
  3.   内部 ID KEY 输出格式已经固定为8个字节模式
  4. */


  5. /*************        本地常量声明        **************/
  6. #define MAIN_Fosc                22118400L        //定义主时钟
  7. #define        RX1_Lenth                32                        //串口接收缓冲长度
  8. #define        BaudRate1                115200UL        //选择波特率
  9. #define        Timer1_Reload        (65536UL -(MAIN_Fosc / 4 / BaudRate1))                //Timer 1 重装值, 对应300KHZ
  10. #define        Timer2_Reload        (65536UL -(MAIN_Fosc / 4 / BaudRate1))                //Timer 2 重装值, 对应300KHZ
  11. #include        "STC15Fxxxx.H"
  12. /*************        本地变量声明        **************/
  13. u8        idata RX1_Buffer[RX1_Lenth];        //接收缓冲
  14. u8        TX1_Cnt;        //发送计数
  15. u8        RX1_Cnt;        //接收计数
  16. bit        B_TX1_Busy;        //发送忙标志
  17. /*************        端口引脚定义        **************/
  18. unsigned char two_lab=0;
  19. sbit LED1=P1^0;//LED1
  20. sbit LED2=P1^1;//LED2
  21. sbit LED3=P3^7;//LED3
  22. sbit DK1=P3^3;//继电器
  23. sbit BEEP=P3^4;//蜂鸣器
  24. sbit K1=P1^3;//按键1
  25. sbit K2=P1^2;//按键2
  26. sbit K3=P1^4;//按键3
  27. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  28. /////这是安信可云平台数据包的全部组成结构,细节可参照安信可的云平台V1.0版本规格书,包结构章节
  29. #define O_PF    0X00  //包头1字节固定0X55
  30. #define O_LEN_L 0X01  //整个包长低字节
  31. #define O_LEN_H 0X02  //整个包长高字节 注意转义码 两个这里只计算一个数据处理!
  32. #define O_CMD_T 0X03  //命令类型
  33. #define O_CMD_C 0X04  //具体命令
  34. #define O_CIX_L 0X05  //本命令序列编号低字节
  35. #define O_CIX_H 0X06  //本命令序列编号高字节
  36. #define O_EXMSH 0X07  //扩展信息高字节
  37. #define O_EXMSL 0X08  //扩展信息低字节
  38. #define O_RESTA 0X09  //数据包状态信息,成功 失败 请求 未知
  39. #define O_DEVID_START 0x0A  //8字节设备识别  低字节在前
  40. #define O_DEVID 0x0A  //8字节设备识别
  41. #define O_TK_LEN      0X12 //1 BYTS TL_LEN          //获得的设备临时通讯令牌长度
  42. #define O_TOKE_START  0X13
  43. #define O_DATAS_START 0X1B
  44. //N BYTS DATAS          //客户的数据包串
  45. //CRC_L    1BYTE          //CRC16 低字节
  46. //CRC_H    1BYTE          //CRC16 高字节
  47. //PACK_END 1BYTE          //包尾1字节固定0X55

  48. ////////////////////////////////////////////////////////////////////////以上定义了包中的各参数的绝对位置//////////////////////////////////
  49. #define uart_rec_tcp_udp_data 0        //系统进入正常网络数据收发状态
  50. #define uart_rec_csysid       1        //系统获取ESP8266WIFI模块的许可号状态,获取四个字节的芯片ID 和 4个字节的授权码
  51. #define uart_rec_smartlink    2        //系统进入获取上网账号密码状态
  52. #define uart_rec_bander       3        //系统进入将本WIFI设备 和APP 手机绑定控制状态
  53. //////////////////////////////////////////////////////////////////////以上部分定义了系统的几种状态///////////////////////////////////////
  54. bit have_tok=0;
  55. bit have_data=0;
  56. unsigned char rec_len=0;
  57. bit                   a_vec=0;                   //设置一个标志位,串口程序 出现指定的字串,并动态过滤到指定的字符后 置1
  58. unsigned char          ceng=0;         //最多 多少字节内 会出现指定字串,静态变量,
  59. unsigned char str_len_limt=16;         //设置一个限定参考数值,在这个参考个数内必定出现指定字符串
  60. unsigned char   str_len_num=11;        //字符个数
  61. char str_ref=':';
  62. /////////////////////////////////////////////////////////////////////上面几个变量用来作为在串口中过滤指定字符串的 限定参数,改变过滤内容后必定先初始化这几个/////
  63. code char CYSYS_code[]="+CSYSID:CHIP";
  64. code char PIPD_code[]="+IPD,";
  65. code char bander_code[]="+IPD,4,26:RPL:";//这里过滤有漏洞
  66. code char smartlink_code[]="SMART SUCCESS";
  67. /////////////////////////////////////////////////////////////////////以上是从WIFI模块串口输出到本单片机串口输入后,本单片机要过滤的各种头部////////////////////
  68. unsigned char uart_rec_sta=uart_rec_csysid;// 串口目前所处于的状态,比如进入正常数据接收,或者SMARTLINK 或者 获取模块的ID。
  69. code unsigned char AT_RST[]="AT+RST";                                                     
  70. code unsigned char AT_MODE[]="AT+CWMODE=1";
  71. code unsigned char AT_CWJAP[]="AT+CWJAP=\"360we\",\"zty0012001\"";
  72. code unsigned char AT_CIP3[]="AT+CIPSTART=3,\"UDP\",\"cloud.ai-thinker.com\",5001,2468,0" ;
  73. code unsigned char temp_bander[]="RPT:\"0xa1b23467\",\"0xaf321234\",\"192.168.0.123\",\"light\",\"123456a\"";
  74. code unsigned char AT_CIPMUX[]="AT+CIPMUX=1";
  75. code unsigned char CIPSTART[]="AT+CIPSTART=4,\"UDP\",\"cloud.ai-thinker.com\",5001,2468,0";
  76. code unsigned char AT_CSYSID[]="AT+CSYSID";
  77. code unsigned char AT_SMARTLINK[]="AT+CWSMARTSTART=1";
  78. code unsigned char ZERO[]="00000000000000000000000000000000001";
  79. code unsigned char CIPSEND_LEN[]="AT+CIPSEND=4,";
  80. code unsigned char CIP3SEND_LEN[]="AT+CIPSEND=3,63";
  81. /////////////////////////////////////////////////////////////////////以上字串是单片机发给串口模块的AT语句有的是直接给WIFI模块的指令,有些是用来拷贝字符串用/////////////

  82. xdata unsigned char at_send_len_ox[20];               
  83. idata unsigned char send_buf[64]="jisifsfhello:99999;oop";                             //发送缓冲区
  84. unsigned char recd_buf[64]= {0x55 ,0x25 ,0x00 ,0xAA ,0xFF ,0x00, 0x00, 0x00, 0x00 ,0x02 ,0x31, 0x0A ,0xFE ,0x00, 0x00, 0x00, 0x00 ,0x00, 0x08, 0x00 ,0x7C ,0xC8, 0x52 ,0xFE, 0x3D ,0x64 ,0x29, 0x4C ,0x49, 0x47, 0x48 ,0x54 ,0x02, 0x3A ,0x3F, 0x6C, 0x02, 0x55};                                                 //接收缓冲区
  85. data unsigned char temp_buf[72];                                 //加工缓冲区
  86. idata unsigned char toke[8]={0x24,0x41,0xD6,0x39,0x48,0x83,0xAC,0x00};//此设备在服务器上获得的令牌包
  87. unsigned char esp_dev_id[8]={0,0,0,0,0,0,0X1E,0XDE};         //    8266的8个字节的器件ID号,可在服务器数据库中查到,唯一标示一个器件,登录过程需要一个器件ID,和数据区放一个数据密码,这么简单登录
  88. unsigned char esp_TOK_id[8]={0,0,0,0,0,0,0,0};                                 //    服务器分给器件器件的令牌包,另外个地方也定义了,完全可以用一个数组完成的
  89. unsigned char esp_user_data[14]={0,0,0,0,0,0,0X1E,0XDE};         //    客户的净数据负荷区,可以很大,因为本款单片机有限,并且一般控制信号,定义几个字节够了!注意在登录的时候,这里是器件密码!
  90. unsigned char temp_cd[]="TEMP:123;";                                                 //    一个数据包,前面是包格式定义,后面是客户数据区,这里定义一个即将要发送的温度数据
  91. unsigned char need_seed_len=0;                                                                 //    全局变量,本次总共需要发到串口的数据
  92. bit t_o=0;                                                                                                         //  在构造一个如00123 的数据时候,去掉前面的00变成123 这里若碰到0就置1
  93. code unsigned char cip3_lcport[]="2469,0";
  94. data unsigned char chip_id[8]={'0','0','0','0','0','0','0','0'};
  95. data unsigned char flash_id[8]={'0','0','0','0','0','0','0','0'};
  96. pdata unsigned char pass_id[8]={'0','0','0','0','0','0','0','0'};

  97. unsigned int time=0; //每隔30秒把一个变量加1,然后把这个变量作为温度数据上报给云平台,转给手机端

  98. xdata unsigned char ssid[32];          //暂存SSID账户信息
  99. xdata unsigned char password[20]; //暂存客户密码
  100. idata char ssid_len=0;                  //记录SSID 长度
  101. idata char pasd_len=0;                          //记录密码长度

  102. bit have_id=0;                                          //记录是否用AT指令获取到了这个模块的ID 和KEY信息
  103. bit have_smartlink=0;                          //记录是否过滤到 从串口来的TCP UDP 数据  smartlink
  104. bit have_bander=0;                                  //记录是从串口中输出的网络数据中过滤到 手机用UDP发来的请求信息

  105. unsigned char stac_a=0;                      //全局专用变量
  106. unsigned char stac_b=0;                          //全局专用变量

  107. #include "intrins.h"

  108. typedef unsigned char BYTE;
  109. typedef unsigned int WORD;

  110. void IapIdle();
  111. BYTE IapReadBYTE(WORD addr);



  112. #define CMD_IDLE      0
  113. #define CMD_READ      1
  114. #define CMD_PROGRAM   2
  115. #define CMD_ERASE     3

  116. #define ENABLE_IAP  0X81
  117. #define IAP_ADDRESS 0X0400


  118. /////////////////////////////////////////////////////////////////下面部分定义了CRC16校验函数用到的表格///////////////////////////////////
  119. code unsigned int crc_table[256]=
  120. {               /* CRC余式表 */
  121. 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
  122. 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
  123. 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
  124. 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
  125. 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
  126. 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
  127. 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
  128. 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
  129. 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
  130. 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
  131. 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
  132. 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
  133. 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
  134. 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
  135. 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
  136. 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
  137. 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
  138. 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
  139. 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
  140. 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
  141. 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
  142. 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
  143. 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
  144. 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
  145. 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
  146. 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
  147. 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
  148. 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
  149. 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
  150. 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
  151. 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
  152. 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
  153. };

  154. void Delay(BYTE n);
  155. void IapIdle();
  156. BYTE IapReadByte(WORD addr);
  157. void IapProgramByte(WORD addr,BYTE dat);
  158. void IapEraseSector(WORD addr);

  159. void flash_main()
  160. {  
  161.    WORD i;
  162.    //P1=0xfe;
  163.    Delay(10);
  164.    IapEraseSector(IAP_ADDRESS);
  165.    for(i=0;i<512;i++)
  166.    {
  167.      if(IapReadByte(IAP_ADDRESS+i)!=0xff)
  168.          goto Error;
  169.    }
  170.    //P1=0xfc;
  171.    Delay(10);
  172.    for(i=0;i<512;i++)
  173.    {
  174.       IapProgramByte(IAP_ADDRESS+i,(BYTE)i);
  175.    }
  176.    //P1=0XF8;
  177.    Delay(10);
  178.    for(i=0;i<512;i++)
  179.    {
  180.      if(IapReadByte(IAP_ADDRESS+i)!=(BYTE)i)
  181.          goto Error;
  182.    }
  183.    //P1=0XF0;
  184.    while(1);
  185.    Error:
  186.    //P1&=0x7f;
  187.    while(1);
  188. }
  189. void Delay(BYTE n)
  190. {
  191.   WORD x;
  192.   while(n--)
  193.   {
  194.    x=0;
  195.    while(++x);
  196.   }
  197. }
  198. void IapIdle()
  199. {
  200.   IAP_CONTR=0;
  201.   IAP_CMD=0;
  202.   IAP_TRIG=0;
  203.   IAP_ADDRH=0X80;
  204.   IAP_ADDRL=0;
  205. }

  206. BYTE IapReadByte(WORD addr)
  207. {
  208.    BYTE dat;
  209.    IAP_CONTR=ENABLE_IAP;
  210.    IAP_CMD=CMD_READ;
  211.    IAP_ADDRL=addr;
  212.    IAP_ADDRH=addr>>8;
  213.    IAP_TRIG=0x5a;
  214.    IAP_TRIG=0xa5;
  215.    _nop_();
  216.    dat=IAP_DATA;
  217.    IapIdle();
  218.    return dat;
  219. }

  220. void IapProgramByte(WORD addr,BYTE dat)
  221. {
  222.   IAP_CONTR=ENABLE_IAP;
  223.   IAP_CMD=CMD_PROGRAM;
  224.   IAP_ADDRL=addr;
  225.   IAP_ADDRH=addr>>8;
  226.   IAP_DATA=dat;
  227.   IAP_TRIG=0x5a;
  228.   IAP_TRIG=0xa5;
  229.   _nop_();
  230.   IapIdle();
  231. }

  232. void IapEraseSector(WORD addr)
  233. {
  234.   IAP_CONTR=ENABLE_IAP;
  235.   IAP_CMD=CMD_ERASE;
  236.   IAP_ADDRL=addr;
  237.   IAP_ADDRH=addr>>8;
  238.   IAP_TRIG=0x5a;
  239.   IAP_TRIG=0xa5;
  240.   _nop_();
  241.   IapIdle();
  242. }
  243. /////////////////////////////////////////////////////////////////上面部分定义了CRC16校验函数用到的表格///////////////////////////////////


  244. void make_AT_CIP3(void)
  245. //根据上边 在2468 端口监听到的 广播内容 用广播内容的IP 地址192.168.1.10和端口 48008新建一个3连接,
  246. //AT+CIPSTART=3,"UDP","192.168.1.10",48008,2469,0
  247. ///新建一个连接3
  248. {
  249.   unsigned char a,b;
  250.   for(a=0,b=0;a<21;a++,b++)
  251.   temp_buf[b]=AT_CIP3[b];
  252.   for(a=0;recd_buf[a]!=',';a++,b++)
  253.   temp_buf[b]=recd_buf[a];
  254.   temp_buf[b]=',';
  255.   b++;
  256.   a+=2;
  257.   for(;recd_buf[a]!='"';a++,b++)
  258.   temp_buf[b]=recd_buf[a];
  259.   temp_buf[b]=',';
  260.   b++;
  261.   for(a=0;cip3_lcport[a]!=0;a++,b++)
  262.   temp_buf[b]=cip3_lcport[a];
  263.   temp_buf[b]=0;
  264. }
  265. //将16进制数,变成16进制字符比如10变成A
  266. char back_char(unsigned char user_d)
  267. {
  268.   if(user_d<10)
  269.   return (user_d+'0');
  270.   else
  271.   return (user_d-10+'A');
  272. }
  273. ////制作 向手机发送如下格式UDP数据
  274. ////RPT:"0x00FE6738","0xB8B3C281","192.168.0.123","light","123456a"
  275. void make_bander_data()
  276. {
  277.   unsigned char a,b=0;
  278.   for(a=0;temp_bander[a]!=0;a++)
  279.   temp_buf[a]=temp_bander[a];
  280.   temp_buf[a]=0;

  281.   //以上硬拷贝 code unsigned char temp_bander[]="RPT:\"0xa1b23467\",\"0xaf321234\",\"192.168.0.123\",\"light\",\"123456a\"";到 temp_buf
  282.   //以下语句修改RPT:"0x00FE6738","0xB8B3C281","192.168.0.123","light","123456a" 中将本身的设备ID(如0x00FE6738) 和 KEY(0xB8B3C281)放到上面修改后的temp_buf
  283.   temp_buf[7]=back_char(esp_dev_id[4]>>4);
  284.   temp_buf[8]=back_char(esp_dev_id[4]&0x0f);
  285.   temp_buf[9]=back_char(esp_dev_id[5]>>4);
  286.   temp_buf[10]=back_char(esp_dev_id[5]&0x0f);
  287.   temp_buf[11]=back_char(esp_dev_id[6]>>4);
  288.   temp_buf[12]=back_char(esp_dev_id[6]&0x0f);
  289.   temp_buf[13]=back_char(esp_dev_id[7]>>4);
  290.   temp_buf[14]=back_char(esp_dev_id[7]&0x0f);

  291.   temp_buf[20]=back_char(esp_user_data[7]>>4);
  292.   temp_buf[21]=back_char(esp_user_data[7]&0x0f);
  293.   temp_buf[22]=back_char(esp_user_data[6]>>4);
  294.   temp_buf[23]=back_char(esp_user_data[6]&0x0f);
  295.   temp_buf[24]=back_char(esp_user_data[5]>>4);
  296.   temp_buf[25]=back_char(esp_user_data[5]&0x0f);
  297.   temp_buf[26]=back_char(esp_user_data[4]>>4);
  298.   temp_buf[27]=back_char(esp_user_data[4]&0x0f);
  299. }

  300. void make_AT_SEND(unsigned char a_len)   //生成右边这样的指令,将参数a_len 改成10进制,右边这条指令  "AT+CIPSEND=XX" XX是发送的数量
  301. {
  302.   unsigned char aa=0;
  303.   for(aa=0;aa<13;aa++)
  304.   {
  305.     at_send_len_ox[aa]=CIPSEND_LEN[aa];         //剪贴"AT+CIPSEND= 到RAM  后面的十进制参数由下面的部分生成
  306.   }
  307.   t_o=0;                                 //去掉前面的0,比如发送38个字节,038,前面的0就可以去掉了。
  308.   if((a_len/100))
  309.   {
  310.   at_send_len_ox[aa]=a_len/100+'0';
  311.   aa++;
  312.   t_o=1;
  313.   }
  314.   if((a_len%100)/10)
  315.   {
  316.   at_send_len_ox[aa]=(a_len%100)/10+'0';
  317.   aa++;
  318.   t_o=1;
  319.   }
  320.   else if(t_o)
  321.   {
  322.     at_send_len_ox[aa]=0+'0';
  323.         aa++;
  324.   }
  325.   at_send_len_ox[aa]=(a_len%10)+'0';
  326.   aa++;
  327.   at_send_len_ox[aa]=0;
  328. }
  329. //下面函数获得CRC校验码 采用标准CRC16 初始CRC=0XFFFF  运算多项式参数 8005 非1021
  330. unsigned int GetRevCrc_16(unsigned char * pData, int nLength)
  331. {
  332.   unsigned int cRc_16 = 0xffff;
  333.   unsigned char temp;
  334.   while(nLength-- > 0)
  335.   {
  336.     temp = cRc_16&0xff;
  337.     cRc_16 = (cRc_16 >> 8) ^ crc_table[(temp ^ *pData++) & 0xFF];
  338.   }
  339.   return cRc_16;   
  340. }
  341. //下面这个函数构造一个发送的数据格式,请看数据格式文档,完全可以用结构体完成,这里采用数据,从上到下描述这个数据包
  342. //发送的数据包,目前只有登录数据包,和上报温度数据包,这两个基本的数据包,上报数据包可以充当心跳包,第一个参数决定着,是发送登录包还是温度包
  343. //其他几个入口参数是器件ID,令牌包,以及客户的数据,以及客户数据长度

  344. void make_send_pack(unsigned char ms_opt,unsigned char *dev_id,unsigned char *toke_id,unsigned char *use_data,unsigned char use_data_len)
  345. {
  346.   unsigned char a,b,i=0;
  347.   unsigned esp_crc=0;
  348.   send_buf[0]=0x55;                                                     //包头是0X55固定
  349.   
  350.   send_buf[O_LEN_L]=(O_DATAS_START+use_data_len+3)%0xff; //本数据包的所有数据长度,包头至包尾,记得是没有经过转义前的包长
  351.   send_buf[O_LEN_H]=(O_DATAS_START+use_data_len+3)/0xff;

  352.   if(ms_opt==0)                                                                                         //根据入口参数判断是发送登录链路操作,还是发送数据包云平台
  353.   send_buf[O_CMD_T]=0XA0;// 0XA0 链路操作 0XAA 数据传输 0XAC 实时检测指令 0XF0 终端操作
  354.   else if (ms_opt==1)
  355.   send_buf[O_CMD_T]=0XAA;// 0XA0 链路操作 0XAA 数据传输 0XAC 实时检测指令 0XF0 终端操作

  356.   if(ms_opt==0)                                                                //0X00代表登录操作
  357.   send_buf[O_CMD_C]=0X00;// reg  option
  358.   else if (ms_opt==1)
  359.   send_buf[O_CMD_C]=0XEE;                                                    //0XEE代表数据是从设备到云平台的方向

  360.   send_buf[O_CIX_L]=0XF3;// CMD INDEXL                        //命令序列编号,暂时不用,可以作为对方应答的数据包号标示
  361.   send_buf[O_CIX_H]=0XC0;//        CMD INDEXL                                        //命令序列编号,暂时不用,可以作为对方应答的数据包号标示
  362.   send_buf[O_EXMSH]=0XC0;//        EXTERN MESSAGE1                                //扩展子暂时保留
  363.   send_buf[O_EXMSL]=0XF3;//        EXTERN MESSAGE2                                //扩展子暂时保留

  364.   send_buf[O_RESTA]=0X02;//        CMD_STA 00 OK 01 FAIL 02 SEND 03 NO SUP         //代表本数据包的状态,是发送还是应答成功还是失败

  365.   for(i=0;i<8;i++)
  366.   send_buf[O_DEVID+i]=*(dev_id+(7-i)); // 拷贝设备的唯一ID号到数据包里


  367.   send_buf[O_TK_LEN] =8;                   //代表接下来的令牌包是8个字节


  368.   for(i=0;i<8;i++)
  369.   send_buf[O_TOKE_START+i]=*(toke_id+i);//8个字节令牌包,初始令牌包为00 后续服务器会分配一个令牌包给这个设备,设备每次通讯要携带这个令牌包


  370.   for(i=0;i<use_data_len;i++)
  371.   send_buf[O_DATAS_START+i]=*(use_data+i); // 客户的数据区,登录的时候放数据密码文本
  372.   
  373.   temp_buf[0]=0x55;                                                   //包尾

  374.   esp_crc=GetRevCrc_16(send_buf,O_DATAS_START+use_data_len);//得到转义之前的总数据包CRC,具体可以参照CRC数据格式,因此CRC是针对转义之前的数据生成

  375.   for(a=1,b=1;a<(O_DATAS_START+use_data_len);a++)           //将出去包头,所有的数据中含有有0X55的数据转义成0X54,0X01,将0X54 变成0X54,02,重新转义数据包
  376.   {
  377.     if(send_buf[a]==0x55)
  378.         {
  379.           temp_buf[b]=0x54;
  380.           b+=1;
  381.           temp_buf[b]=0x01;
  382.           b+=1;
  383.         }
  384.         else if(send_buf[a]==0x54)
  385.         {
  386.           temp_buf[b]=0x54;
  387.           b+=1;
  388.           temp_buf[b]=0x02;
  389.           b+=1;
  390.         }
  391.         else
  392.         {
  393.         temp_buf[b]=send_buf[a];
  394.         b+=1;
  395.         }
  396. }         ///////////////////////////////////////////////////////////以上的语句转义数据包中除包头到CRC之前的全部的数据///////////////////////////////////////////////////////////////////////
  397. //55 28 00 AA EE F3 C0 C0 F3 02 E6 1E 00 00 00 00 00 00 08 24 41 D6 39 48 83 AC 00 54 02 45 4D 50 3A 32 35 35 3B 00 D1 52 55
  398. //55 28 00 AA EE F3 C0 C0 F3 02 E6 1E 00 00 00 00 00 00 08 24 41 D6 39 48 83 AC 00 54 02 45 4D 50 3A 32 35 35 3B 00 D1 52 55

  399. temp_buf[b]=(esp_crc>>8);
  400. b+=1;
  401. temp_buf[b]=(esp_crc&0x00ff);         
  402. b+=1;
  403.     ///////////////////////////////////////////////////////////上面两句加上CRC校验////////////////////////////////////////
  404. temp_buf[b]=0x55;        //包尾
  405. b+=1;
  406. temp_buf[b]=0x0d;
  407. b+=1;
  408. temp_buf[b]=0x0a;
  409. b+=1;                                //以上构成回车
  410. need_seed_len=b;        //至此构造出了需要发送的全部数据 包括AT指令需要的换行
  411. temp_buf[b]=0x00;
  412. }



  413. void Delay1(unsigned long ms)//简单延迟函数,单位是毫秒
  414. {
  415.         unsigned char i, j,k;
  416.         for(k=0;k<ms;k++)
  417.         {
  418.                 _nop_();
  419.                 _nop_();
  420.                 i = 22;
  421.                 j = 128;
  422.                 do
  423.                 {
  424.                         while (--j);
  425.                 } while (--i);
  426.         }
  427. }


  428. void Delay2(unsigned long cnt)
  429. {
  430.         long i;
  431.         for(i=0;i<cnt*100;i++);
  432. }

  433. void at_uart_send_str(unsigned char *str)//发送AT字符串到串口
  434. {
  435.   unsigned char *st_p=str;
  436.   do{
  437.      SBUF=*st_p;
  438.          st_p++;
  439.          Delay1(1);
  440.         }while(*st_p);
  441.         SBUF='\r';
  442.         Delay1(1);
  443.         SBUF='\n';
  444.         Delay1(1);
  445. }
  446. void at_uart_send_buf(unsigned char *str,unsigned char len)//发送数据缓冲区的非字符串信息,数据流信息到串口
  447. {
  448.   unsigned char *st_p=str;
  449.   
  450.   while(len){
  451.      SBUF=*st_p;
  452.          st_p++;
  453.          Delay1(1);
  454.          len--;
  455.         }while(*st_p);
  456.         //SBUF='\r';
  457.         Delay1(1);
  458.         //SBUF='\n';
  459.         Delay1(1);
  460. }


  461. void change_pack()                                          //把接收到的数据包转义过来,0X55 转义成0X54 0X01 0X54 替换成0X54 02
  462. {
  463.                                      for(stac_a=1,stac_b=1;recd_buf[stac_a]!=0x55;)
  464.                                    {
  465.                                      if((recd_buf[stac_a]==0x54)&&(recd_buf[stac_a+1]==0x01))
  466.                                          {
  467.                                          temp_buf[stac_b]=0x55;
  468.                                          stac_b++;
  469.                                          stac_a+=2;
  470.                                          }
  471.                                          else if((recd_buf[stac_a]==0x54)&&(recd_buf[stac_a+1]==0x02))
  472.                                          {
  473.                                          temp_buf[stac_b]=0x54;
  474.                                          stac_b++;
  475.                                          stac_a+=2;
  476.                                          }
  477.                                          else
  478.                                          {
  479.                                            temp_buf[stac_b]=recd_buf[stac_a];
  480.                                            stac_b++;
  481.                                            stac_a++;
  482.                                          }
  483.                                   }
  484.                                   temp_buf[stac_b]=0x55;
  485.                                   temp_buf[0]=0x55;
  486.                                   recd_buf[0]=temp_buf[0];
  487.                                   for(stac_a=1;temp_buf[stac_a]!=0x55;stac_a++)
  488.                                   recd_buf[stac_a]=temp_buf[stac_a];
  489.                                   recd_buf[stac_a]=0x55;
  490.                                   recd_buf[0]=0x55;
  491. }
  492. void init_uart(void)
  493. {
  494.           B_TX1_Busy = 0;
  495.         RX1_Cnt = 0;
  496.         TX1_Cnt = 0;
  497.         S1_8bit();                                //8位数据
  498.         S1_USE_P30P31();                //UART1 使用P30 P31口        默认
  499.         AUXR &= ~(1<<4);        //Timer stop                波特率使用Timer2产生
  500.         AUXR |= 0x01;                //S1 BRT Use Timer2;
  501.         AUXR |=  (1<<2);        //Timer2 set as 1T mode
  502.         TH2 = (u8)(Timer2_Reload >> 8);
  503.         TL2 = (u8)Timer2_Reload;
  504.         AUXR |=  (1<<4);        //Timer run enable
  505.         REN = 1;        //允许接收
  506.         ES  = 1;        //允许中断
  507.         EA = 1;                //允许全局中断
  508.         P3M1 = 0x00;
  509.     P3M0 = 0xFF;
  510.         RX1_Cnt=0;
  511.         DK1=0;
  512.         BEEP=0;
  513. }

  514. void main(void)
  515. {
  516.         char tt,i,k,n,z=0;
  517.         //////////////////////////////////////////////////////////////////////////////////////下面部分为定时器以及串口初始化/////////////////////
  518.         init_uart();
  519.         Delay2(2000);
  520.         flash_main();
  521.         ///////////////////////////////////////////////////////////////////////////////////以上部分主要完成串口的初始化////////////////////////////
  522.         for(;;)
  523.         {         
  524.         a_vec=0;                          //出现指定的字串,并动态过滤到指定的字符后 置1
  525.         ceng=0;                   //最多 多少字节内 会出现指定字串,静态变量,
  526.         str_len_limt=22;          //设置一个限定参考数值,在这个参考个数内必定出现指定字符串
  527.         str_len_num=13;           //要过滤连续字符个数
  528.         str_ref=':';                          // 过滤到字符串后,接着要出现的字符,这个字符出现的位置才是绝对0位置
  529.                 uart_rec_sta=uart_rec_smartlink; //设置在串口中的过滤分支条件,串口中断中,根据这个标志调用不同的字符串过滤参数

  530.                 at_uart_send_str(AT_MODE);                 //设置模块进入STATION 模式
  531.                 Delay2(1000);
  532.                 at_uart_send_str(AT_SMARTLINK);         //发送进入SMARTLINK AT指令
  533.                                          //PASSWORD:zty0012001       
  534.                 Delay2(2000);
  535.                 do                                                                 //此循环完成SMARTLINK 的配置
  536.                 {
  537.                 LED1=0;
  538.                 LED2=0;
  539.                 LED3=0;
  540.                 Delay2(200);
  541.                 LED1=1;
  542.                 LED2=1;
  543.                 LED3=1;
  544.                 Delay2(200);
  545.                 if(have_smartlink)//假如从串口中获得正确的 SMARTLINK 用户路由器账户和密码
  546.                 {
  547.                         for(i=0;recd_buf[i]!=0x0d;i++)
  548.                         {
  549.                                 ssid_len++;
  550.                                 ssid[i]=recd_buf[i];                                  //拷贝串口缓冲区中的用户路由器名字
  551.                         }
  552.                         for(i=0;recd_buf[ssid_len+11+i]!='\r';i++)
  553.                         {
  554.                                 password[i]=recd_buf[ssid_len+11+i];          //拷贝串口缓冲区中的用户路由器密码
  555.                                 pasd_len++;
  556.                         }
  557.                 //code unsigned char AT_CWJAP[]="AT+CWJAP=\"360we\",\"zty0012001\"";
  558.                         n=0;
  559.                         for(i=0;i<63;i++)
  560.                     temp_buf[i]=0;                //清空临时缓冲区

  561.                         for(i=0;i<10;i++,n++)
  562.                         temp_buf[n]=AT_CWJAP[i];      //拷贝AT指令加入路由器的格式头AT+CWJAP="

  563.                         for(i=0;i<ssid_len;i++,n++)          //用SMARTLINK 获得的 SSID 和PASSWORLD 填充 加入路由器所需要的两个参数        AT+CWJAP="360we","zty0012001"
  564.                         temp_buf[n]=ssid[i];
  565.                         temp_buf[n]='"';
  566.                         n++;
  567.                         temp_buf[n]=',';
  568.                         n++;
  569.                         temp_buf[n]='"';
  570.                         n++;
  571.                         for(i=0;i<pasd_len;i++,n++)
  572.                         temp_buf[n]=password[i];
  573.                         temp_buf[n]='"';
  574.                 }
  575.             }while(have_smartlink==0); //此循环完成SMARTLINK 的配置

  576.                 LED1=1;
  577.                 LED2=1;
  578.                 LED3=1;
  579.             //////////////////////////////////////////////////////////下面的语句获得模块的设备ID/////////////////////////////////////////////////////////////
  580.         a_vec=0;                          //出现指定的字串,并动态过滤到指定的字符后 置1
  581.         ceng=0;                   //最多 多少字节内 会出现指定字串,静态变量,
  582.         str_len_limt=16;          //设置一个限定参考数值,在这个参考个数内必定出现指定字符串
  583.         str_len_num=12;           //要过滤的字符个数 +CSYSID:CHIP: 为下一个字符留个位置: 因此是12个字符
  584.         str_ref=':';                          // 要过滤到的字符
  585.                 uart_rec_sta=uart_rec_csysid;
  586.                 at_uart_send_str(AT_CSYSID); //返回如下:+CSYSID:CHIP:00FE6738;FLASH:001640EF;KEY:81C2B3B8;
  587.                 Delay2(2000);                                 //延时两秒后,串口中必定输出 所需要的器件ID FLASH ID 和KEY
  588.                 if(have_id)
  589.                 {
  590.                 have_id=0;
  591.                 k=0;
  592.                 for(i=0,tt=0;i<8;i++,tt++)        //  获取模块内部的芯片ID                          
  593.                 chip_id[tt]=recd_buf[i];
  594.                 for(i=15,tt=0;i<23;i++,tt++)//  获取模块内部的FLASH ID
  595.                 flash_id[tt]=recd_buf[i];
  596.                 for(i=28,tt=0;i<36;i++,tt++)//  获取模块内部的KEY
  597.                 pass_id[tt]=recd_buf[i];
  598.         //将获取的16进制字符换成 16进制数据,8个字节的字符最总得到四个字节的16进制数据 比如字符串"A2345678"最终变成0XA2,0X34,0X56,0X78 四个字节存放
  599.             for(i=0;i<8;i++)            
  600.             {
  601.                           if((chip_id[i]>='A')&&(chip_id[i]<='F'))
  602.                           chip_id[i]=(chip_id[i]-'A'+10);
  603.                           else if((chip_id[i]>='a')&&(chip_id[i]<='f'))
  604.               chip_id[i]=(chip_id[i]-'a'+10);
  605.                           else
  606.                           chip_id[i]-='0';
  607.             }
  608.                                
  609.                 for(i=0;i<8;i++)
  610.             esp_dev_id[i]=0;

  611.                 esp_dev_id[7]=((chip_id[6])<<4)+chip_id[7];// 将字符串16进制转换后,变成16进制数据四个字节存放到对应内存中
  612.                 esp_dev_id[6]=((chip_id[4])<<4)+chip_id[5];
  613.                 esp_dev_id[5]=((chip_id[2])<<4)+chip_id[3];
  614.                 esp_dev_id[4]=((chip_id[0])<<4)+chip_id[1];
  615.                 //将获取的16进制字符换成 16进制数据,8个字节的字符最总得到四个字节的16进制数据 比如字符串"A2345678"最终变成0XA2,0X34,0X56,0X78 四个字节存放
  616.             for(i=0;i<8;i++)
  617.             {
  618.                           if((pass_id[i]>='A')&&(pass_id[i]<='F'))
  619.                           pass_id[i]=(pass_id[i]-'A'+10);
  620.                           else if((pass_id[i]>='a')&&(pass_id[i]<='f'))
  621.               pass_id[i]=(pass_id[i]-'a'+10);
  622.                           else
  623.                           pass_id[i]-='0';
  624.             }
  625.                 for(i=0;i<8;i++)
  626.                 flash_id[i]=0;

  627.                 flash_id[7]=((pass_id[6])<<4)+pass_id[7];// 将字符串16进制转换后,变成16进制数据四个字节存放到对应内存中
  628.                 flash_id[6]=((pass_id[4])<<4)+pass_id[5];
  629.                 flash_id[5]=((pass_id[2])<<4)+pass_id[3];
  630.                 flash_id[4]=((pass_id[0])<<4)+pass_id[1];

  631.                 for(i=0;i<8;i++)
  632.             esp_user_data[i]=flash_id[i];

  633.                 // 以上操作将模块输出的内部字符串形式的芯片ID 和KEY (都是4个字节的)换成16进制 存放到内存中,在登录服务器的时候的两个必要参数。
  634.                 //////////////////////////////////////////////////////////上面的语句获得模块的设备ID和KEY/////////////////////////////////////////////////////////////
  635.                 }
  636.                 //while(1);
  637.                 //////////////////////////////////////////////////////////下面的语句发送AT指令加入内网,并链接到安信可物联网服务器/////////////////////

  638.                 a_vec=0;                          //出现指定的字串,并动态过滤到指定的字符后 置1
  639.         ceng=0;                   //最多 多少字节内 会出现指定字串,静态变量,
  640.         str_len_limt=16;          //设置一个限定参考数值,在这个参考个数内必定出现指定字符串
  641.         str_len_num=7;            //字符个数
  642.         str_ref='"';
  643.                 uart_rec_sta=uart_rec_bander;

  644.                 Delay2(2000);
  645.         at_uart_send_str(AT_MODE);
  646.                 Delay2(2000);
  647.         at_uart_send_str(temp_buf);
  648.                 Delay2(10000);
  649.                 at_uart_send_str(AT_CIPMUX);
  650.                 Delay2(2000);
  651.         at_uart_send_str(CIPSTART);              //用UDP方式连接到安信可的云,连接到目标5001安信可云服务,顺便监听 2468 端口,
  652.                 Delay2(2000);
  653.                
  654.                 do
  655.                 {
  656.                 LED1=0;
  657.                 LED2=0;
  658.                 LED3=0;
  659.                 Delay2(200);
  660.                 LED1=1;
  661.                 LED2=1;
  662.                 LED3=1;
  663.                 Delay2(200);
  664.                
  665.                 if(have_bander)
  666.                 {
  667.                   ;
  668.                 }

  669.                  }while(have_bander==0);        //监听局域网内手机向2468端口(2468端口和连接4绑定) 发出的UDP扫描信息,获得RPL:"192.168.1.10","48008"  手机透露自己的IP和端口
  670.                  
  671.                  make_AT_CIP3();                                   //根据上边 在2468 端口监听到的 广播内容 新建一个3连接,AT+CIPSTART=3,"UDP","192.168.1.10",48008,2469,0
  672.                  at_uart_send_str(temp_buf);
  673.                  Delay2(2000);
  674.                  make_bander_data();                    //从绑定手机和设备关系的处理中,在串口输出缓冲区得到
  675.                  at_uart_send_str(CIP3SEND_LEN);
  676.                  Delay2(1000);
  677.                  at_uart_send_str(temp_buf);
  678.                  Delay2(2000);
  679.                 //////////////////////////////////////////////////////////上面面的语句发送AT指令加入内网,并链接到安信可物联网服务器/////////////////////
  680.                 at_uart_send_str(AT_MODE);
  681.                 a_vec=0;                          //出现指定的字串,并动态过滤到指定的字符后 置1
  682.         ceng=0;                   //最多 多少字节内 会出现指定字串,静态变量,
  683.         str_len_limt=12;          //设置一个限定参考数值,在这个参考个数内必定出现指定字符串
  684.         str_len_num=5;            //字符个数
  685.         str_ref=':';
  686.                 uart_rec_sta=uart_rec_tcp_udp_data;

  687.                 make_send_pack(0,esp_dev_id,esp_TOK_id,esp_user_data,8);//构造登录数据包
  688.                 make_AT_SEND(need_seed_len);                            //将要进过WIFI发送的总字节数变成10进制,动态生成发送数据AT指令
  689.                 two_lab=0;                                                                                                ////////////////////////////////////////////////////////////////////两个55计数!!有可能错乱
  690.         at_uart_send_str(at_send_len_ox);                       //将构造好的AT发送数据到互联网的动态发送数据长度
  691.                 Delay2(2000);

  692.        
  693.                 /*
  694.                  for(z=0;z<8;z++)
  695.                 {
  696.                 SBUF='0';
  697.                 Delay2(1);
  698.                 }

  699.                 for(z=0;z<1;z++)
  700.                 {
  701.                 SBUF=need_seed_len;
  702.                 Delay2(1);
  703.                 }

  704.                 for(z=0;z<8;z++)
  705.                 {
  706.                 SBUF='0';
  707.                 Delay2(1);
  708.                 }
  709.                 while(1);
  710.                 */
  711.                 at_uart_send_buf(temp_buf,need_seed_len);                                //经过WIFI模块发送构造好的登录包
  712.                 Delay2(4000);

  713.                 //while(1);

  714.                 while(1)
  715.                 {
  716.                         for(tt=0;tt<60;tt++)
  717.                         {
  718.                         Delay2(200);
  719.                         if(0)
  720.                         {
  721.                         have_data=0;
  722.                         for(z=0;z<8;z++)
  723.                         {
  724.                         SBUF='0';
  725.                         Delay2(1);
  726.                         }
  727.        
  728.                         for(z=0;z<40;z++)
  729.                         {
  730.                         SBUF=recd_buf[z];
  731.                         Delay2(1);
  732.                         }
  733.        
  734.                         for(z=0;z<8;z++)
  735.                         {
  736.                         SBUF='0';
  737.                         Delay2(1);
  738.                         }
  739.                     }
  740.                         Delay2(200);
  741.                    }
  742.                     make_send_pack(1,esp_dev_id,toke,temp_cd,10);    //构造上传数据到云,转给手机的温度数据包,符合基本数据格式
  743.                     make_AT_SEND(need_seed_len);                                          //动态构造发送AT指令
  744.                         at_uart_send_str(at_send_len_ox);                //发送构造好的发送指令
  745.                     Delay2(2000);
  746.                     at_uart_send_buf(temp_buf,need_seed_len);             //经过WIFI发送数据

  747.                         LED2=0;
  748.                         BEEP=1;
  749.                         Delay2(200);
  750.                     LED2=1;
  751.                         BEEP=0;      //闪亮心跳指示灯,和心跳音
  752.                                                                                                                         //每30秒会运行到这里一次。更新一次温度数值
  753.                         time++;
  754.                         temp_cd[5]=(((time%1000)/100)+'0');
  755.                         temp_cd[6]=(((time%100)/10)+'0');
  756.                     temp_cd[7]=(((time%10))+'0');
  757.                 }
  758.         }
  759.         Delay2(2000);
  760. }

  761. /********************* 字符串过滤函数初始参数************************/
  762. /*
  763. bit a_vec=0;                          //出现指定的字串,并动态过滤到指定的字符后 置1
  764. unsigned char ceng=0;         //最多 多少字节内 会出现指定字串,静态变量,
  765. unsigned char str_len_limt=12;//设置一个限定参考数值,在这个参考个数内必定出现指定字符串
  766. unsigned char str_len_num=5;  //字符个数
  767. char str_ref=':';
  768. code char test_code[]="+IPD,";
  769. */

  770. void fit_stb(unsigned char *str_p) // 每次串口接收到一个字符都会进入本过滤函数,看是否过滤到指定的字符串。
  771. {
  772.    if((a_vec==0)&&(ceng<str_len_limt))
  773.    {
  774.       if(ceng<str_len_num)
  775.           {
  776.       if(SBUF==(*(str_p+ceng)))
  777.           ceng++;
  778.           else
  779.           ceng=0;
  780.           }
  781.           else
  782.           {
  783.                 ceng++;
  784.                 if(SBUF==str_ref)
  785.                 {
  786.                   a_vec=1;
  787.                   ceng=0;       
  788.                 }
  789.           }
  790.           RX1_Cnt=0;
  791.    }
  792.    else if(ceng>=str_len_limt)
  793.    {
  794.                a_vec=0;
  795.                   ceng=0;
  796.    }
  797. }

  798. //unsigned char
  799. void UART1_int (void) interrupt UART1_VECTOR
  800. {
  801.         if(RI)
  802.         {
  803.                 RI = 0;
  804.                 if(a_vec==0)//上次未曾过滤到指定的字符串中所有的字符出现,每次只过滤一个字符
  805.                 {
  806.                  switch(uart_rec_sta)              //根据系统的状态,决定过滤哪个字符
  807.                  {
  808.                   case uart_rec_tcp_udp_data: //串口进入正常的UDP TCP 数据收发
  809.                   fit_stb(PIPD_code);                  //过滤数据接收头
  810.                   break;
  811.                   case  uart_rec_csysid:          //串口进入获得模块内部ID 和KEY 状态
  812.                   fit_stb(CYSYS_code);              //过滤指定的头部
  813.                   break;
  814.                   case uart_rec_smartlink:          //串口进入获得客户的路由器账户密码状态
  815.                   fit_stb(smartlink_code);
  816.                   break;
  817.                   case uart_rec_bander:
  818.                   fit_stb(bander_code);
  819.                  }
  820.                 }
  821.                 else//////////////////////////////过滤到指定的头部
  822.                 {
  823.                
  824.                  recd_buf[RX1_Cnt] = SBUF;                //保存一个字节
  825.                  if(recd_buf[RX1_Cnt]==0X55)    //记录0X55的个数,出现两次后,代表一个有数据包结束
  826.                  two_lab++;
  827.                  if(RX1_Cnt<62)        /////////////////////防止64字节的缓冲区溢出
  828.                  RX1_Cnt++;
  829.                  else                        ///////每次收到的指令超过64字节,就把数据清空,接收指针指向开头
  830.                  {
  831.                    RX1_Cnt=0;
  832.                    a_vec=0;
  833.                    two_lab=0;
  834.                  }
  835.                  switch(uart_rec_sta)
  836.                   {
  837.                     case uart_rec_tcp_udp_data:
  838.                         //have_dd=1;
  839.                            //LED2=0;
  840.                                 if(two_lab==2)//////////////////////////////////////////得到一包有效的数据!取出2个OX55之间的有效数据////////////////////
  841.                                  {
  842.                                    a_vec=0;
  843.                                    rec_len=RX1_Cnt;
  844.                                    two_lab=0;
  845.                                    RX1_Cnt=0;
  846.                    LED1=0;
  847.                                    LED2=0;
  848.                                    LED3=0;

  849.                                    change_pack();
  850.                                    have_data=1;
  851.                                     if((recd_buf[32])==':')              /////////////////////////////////////简单得到手机的开关指令////////////////////
  852.                                         {
  853.                                          if((recd_buf[33])=='0')
  854.                                          {
  855.                                           DK1=0;
  856.                                           LED1=1;          //关灯指令
  857.                                          }
  858.                                          else if((recd_buf[33])=='1')
  859.                                          {
  860.                                           DK1=1;
  861.                                       LED1=0;    //开灯指令
  862.                                          }
  863.                                         }
  864.                                         if((recd_buf[3]==0xa0)&&(recd_buf[9]==0x00)&&(have_tok==0))////////////////////获得TOKE包//////////////////////////////////
  865.                                         {
  866.                                           have_tok=1;
  867.                                           toke[7]=recd_buf[19];             
  868.                                           toke[6]=recd_buf[20];               
  869.                                           toke[5]=recd_buf[21];       
  870.                                           toke[4]=recd_buf[22];                 
  871.                                           toke[3]=recd_buf[23];
  872.                                           toke[2]=recd_buf[24];
  873.                                           toke[1]=recd_buf[25];
  874.                                           toke[0]=recd_buf[26];

  875.                                         }
  876.                                  }
  877.                         break;
  878.                    case  uart_rec_csysid:
  879.                    if(RX1_Cnt>40)
  880.                    have_id=1;
  881.                    break;
  882.                    case  uart_rec_smartlink:
  883.                    if(RX1_Cnt>10)
  884.                    have_smartlink=1;
  885.                    break;
  886.                    case  uart_rec_bander:
  887.                    if(RX1_Cnt>20)
  888.                    have_bander=1;
  889.                    break;
  890.                  };
  891.           }
  892.         }
  893.         if(TI)
  894.         {
  895.                 TI = 0;
  896.                 B_TX1_Busy = 0;                //清除发送忙标志
  897.         }
  898. }
复制代码


  1. /*************        本地常量声明        **************/
  2. #define MAIN_Fosc                22118400L        //定义主时钟
  3. #define        RX1_Lenth                32                        //串口接收缓冲长度
  4. #define        BaudRate1                115200UL        //选择波特率
  5. #define        Timer1_Reload        (65536UL -(MAIN_Fosc / 4 / BaudRate1))                //Timer 1 重装值, 对应300KHZ
  6. #define        Timer2_Reload        (65536UL -(MAIN_Fosc / 4 / BaudRate1))                //Timer 2 重装值, 对应300KHZ
  7. #include        "STC15Fxxxx.H"
  8. /*************        本地变量声明        **************/
  9. u8        idata RX1_Buffer[RX1_Lenth];        //接收缓冲
  10. u8        TX1_Cnt;        //发送计数
  11. u8        RX1_Cnt;        //接收计数
  12. bit        B_TX1_Busy;        //发送忙标志
  13. /*************        端口引脚定义        **************/
  14. unsigned char two_lab=0;
  15. sbit LED1=P1^0;//LED1
  16. sbit LED2=P1^1;//LED2
  17. sbit LED3=P3^7;//LED3
  18. sbit DK1=P3^3;//继电器
  19. sbit BEEP=P3^4;//蜂鸣器
  20. sbit K1=P1^3;//按键1
  21. sbit K2=P1^2;//按键2
  22. sbit K3=P1^4;//按键3
  23. #define O_PF    0X00  //包头1字节固定0X55
  24. #define O_LEN_L 0X01  //整个包长低字节
  25. #define O_LEN_H 0X02  //整个包长高字节 注意转义码 两个这里只计算一个数据处理!
  26. #define O_CMD_T 0X03  //命令类型
  27. #define O_CMD_C 0X04  //具体命令
  28. #define O_CIX_L 0X05  //本命令序列编号低字节
  29. #define O_CIX_H 0X06  //本命令序列编号高字节
  30. #define O_EXMSH 0X07  //扩展信息高字节
  31. #define O_EXMSL 0X08  //扩展信息低字节
  32. #define O_RESTA 0X09  //数据包状态信息,成功 失败 请求 未知
  33. #define O_DEVID 0x0A  //8字节设备识别
  34.    //1 BYTS TL_LEN          //获得的设备临时通讯令牌长度
  35.    //N BYTS TK                   //TL_LEN个通讯令牌串
  36.    //N BYTS DATAS          //客户的数据包串
  37.    //CRC_L    1BYTE          //CRC16 低字节
  38.    //CRC_H    1BYTE          //CRC16 高字节
  39.    //PACK_END 1BYTE          //包尾1字节固定0X55

  40. //

  41. char led1bl,led2bl,led3bl;
  42. code unsigned char AT_RST[]="AT+RST";
  43. code unsigned char AT_MODE[]="AT+CWMODE=3";
  44. code unsigned char AT_CWJAP[]="AT+CWJAP=\"360we\",\"zty0012001\"";
  45. code unsigned char CIPSTART[]="AT+CIPSTART=\"UDP\",\"cloud.ai-thinker.com\",5001";
  46. code unsigned char CIPSEND_LEN[]="AT+CIPSEND=4,38";
  47. unsigned char at_send_len_ox[16];
  48. unsigned char test_buff[38]={0x55,0x26,0x00,0xA0,0x00,0xA8,0x16,0x16,0xA8,0x02,0xE6,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0xE6,0xBD,0x5B,0x55};
  49. data unsigned char send_buf[64];
  50. pdata unsigned char recd_buf[64];
  51. unsigned char temp_buf[64];

  52. unsigned char toke[8]={0,0,0,0,0,0,0,0,};
  53. code unsigned int crc_table[256]=
  54. {               /* CRC余式表 */
  55. 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
  56. 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
  57. 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
  58. 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
  59. 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
  60. 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
  61. 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
  62. 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
  63. 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
  64. 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
  65. 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
  66. 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
  67. 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
  68. 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
  69. 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
  70. 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
  71. 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
  72. 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
  73. 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
  74. 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
  75. 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
  76. 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
  77. 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
  78. 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
  79. 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
  80. 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
  81. 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
  82. 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
  83. 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
  84. 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
  85. 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
  86. 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
  87. };
  88. bit t_o=0;
  89. void make_AT_SEND(unsigned char a_len)
  90. {
  91.   unsigned char aa=0;
  92.   for(aa=0;aa<11;aa++)
  93.   {
  94.     at_send_len_ox[aa]=CIPSEND_LEN[aa];
  95.   }
  96.   t_o=0;
  97.   if((a_len/100))
  98.   {
  99.   at_send_len_ox[aa]=a_len/100+'0';
  100.   aa++;
  101.   t_o=1;
  102.   }
  103.   if((a_len%100)/10)
  104.   {
  105.   at_send_len_ox[aa]=(a_len%100)/10+'0';
  106.   aa++;
  107.   t_o=1;
  108.   }
  109.   else if(t_o)
  110.   {
  111.     at_send_len_ox[aa]=0+'0';
  112.         aa++;
  113.   }
  114.   at_send_len_ox[aa]=(a_len%10)+'0';
  115.   aa++;
  116.   at_send_len_ox[aa]=0;
  117. }
  118. unsigned int GetRevCrc_16(unsigned char * pData, int nLength)
  119. {
  120.   unsigned int cRc_16 = 0xffff;
  121.   unsigned char temp;

  122.   while(nLength-- > 0)
  123.   {
  124.     temp = cRc_16&0xff;
  125.     cRc_16 = (cRc_16 >> 8) ^ crc_table[(temp ^ *pData++) & 0xFF];
  126.   }

  127.   return cRc_16;   
  128. }
  129. #define O_PF    0X00  //包头1字节固定0X55
  130. #define O_LEN_L 0X01  //整个包长低字节
  131. #define O_LEN_H 0X02  //整个包长高字节 注意转义码 两个这里只计算一个数据处理!
  132. #define O_CMD_T 0X03  //命令类型
  133. #define O_CMD_C 0X04  //具体命令
  134. #define O_CIX_L 0X05  //本命令序列编号低字节
  135. #define O_CIX_H 0X06  //本命令序列编号高字节
  136. #define O_EXMSH 0X07  //扩展信息高字节
  137. #define O_EXMSL 0X08  //扩展信息低字节
  138. #define O_RESTA 0X09  //数据包状态信息,成功 失败 请求 未知
  139. #define O_DEVID_START 0x0A  //8字节设备识别  低字节在前
  140. #define O_TK_LEN      0X12 //1 BYTS TL_LEN          //获得的设备临时通讯令牌长度
  141. #define O_TOKE_START  0X13
  142. #define O_DATAS_START 0X1B
  143.    //N BYTS DATAS          //客户的数据包串
  144.    //CRC_L    1BYTE          //CRC16 低字节
  145.    //CRC_H    1BYTE          //CRC16 高字节
  146.    //PACK_END 1BYTE          //包尾1字节固定0X55
  147. unsigned char esp_dev_id[8]={0,0,0,0,0,0,0X1E,0XE6};
  148. unsigned char esp_TOK_id[8]={0,0,0,0,0,0,0,0};
  149. unsigned char esp_user_data[8]={0,0,0,0,0,0,0X1E,0XE6};
  150. unsigned char need_seed_len=0;
  151. void make_send_pack(unsigned char ms_opt,unsigned char *dev_id,unsigned char *toke_id,unsigned char *use_data,unsigned char use_data_len)
  152. {
  153.   unsigned char a,b,i=0;
  154.   unsigned esp_crc=0;
  155.   send_buf[0]=0x55;

  156.   send_buf[O_LEN_L]=(O_DATAS_START+use_data_len+3)%0xff;
  157.   send_buf[O_LEN_H]=(O_DATAS_START+use_data_len+3)/0xff;

  158.   send_buf[O_CMD_T]=0XA0;// 0XA0 链路操作 0XAA 数据传输 0XAC 实时检测指令 0XF0 终端操作
  159.   send_buf[O_CMD_C]=0X00;// reg  option
  160.   send_buf[O_CIX_L]=0XA8;// CMD INDEXL
  161.   send_buf[O_CIX_H]=0X16;//        CMD INDEXL
  162.   send_buf[O_EXMSH]=0X16;//        EXTERN MESSAGE1
  163.   send_buf[O_EXMSL]=0XA8;//        EXTERN MESSAGE2
  164.   send_buf[O_RESTA]=0X02;//        CMD_STA 00 OK 01 FAIL 02 SEND 03 NO SUP

  165.   for(i=0;i<8;i++)
  166.   send_buf[O_DEVID+i]=*(dev_id+(7-i));

  167.   send_buf[O_TK_LEN] =8;
  168.   for(i=0;i<8;i++)
  169.   send_buf[O_TOKE_START+i]=*(toke_id+i);

  170.   for(i=0;i<use_data_len;i++)
  171.   send_buf[O_DATAS_START+i]=*(use_data+i); // 数据区,登录的时候放数据密码文本

  172.   temp_buf[0]=0x55;
  173.   for(a=1,b=1;a<(O_DATAS_START+use_data_len);a++)
  174.   {
  175.     if(send_buf[a]==0x55)
  176.         {
  177.           temp_buf[b]=0x54;
  178.           b+=1;
  179.           temp_buf[b]=0x01;
  180.           b+=1;
  181.         }
  182.         else if(send_buf[a]==0x54)
  183.         {
  184.           temp_buf[b]=0x54;
  185.           b+=1;
  186.           temp_buf[b]=0x02;
  187.           b+=1;
  188.         }
  189.         else
  190.         {
  191.         temp_buf[b]=send_buf[a];
  192.         b+=1;
  193.         }
  194. }
  195. esp_crc=GetRevCrc_16(temp_buf,O_DATAS_START+use_data_len);
  196. temp_buf[b]=(esp_crc>>8);
  197. b+=1;
  198. temp_buf[b]=(esp_crc&0x00ff);         
  199. b+=1;
  200. temp_buf[b]=0x55;
  201. b+=1;
  202. need_seed_len=b;
  203. }
  204. bit have_data=0;
  205. unsigned char rec_len=0;
  206. void Delay1(unsigned long ms)
  207. {
  208.         unsigned char i, j,k;
  209.         for(k=0;k<ms;k++)
  210.         {
  211.                 _nop_();
  212.                 _nop_();
  213.                 i = 22;
  214.                 j = 128;
  215.                 do
  216.                 {
  217.                         while (--j);
  218.                 } while (--i);
  219.         }
  220. }
  221. void Delay2(unsigned long cnt)
  222. {
  223.         long i;
  224.         for(i=0;i<cnt*100;i++);
  225. }
  226. void at_uart_send_str(unsigned char *str)
  227. {
  228.   unsigned char *st_p=str;
  229.   do{
  230.      SBUF=*st_p;
  231.          st_p++;
  232.          Delay1(1);
  233.         }while(*st_p);
  234.         SBUF='\r';
  235.         Delay1(1);
  236.         SBUF='\n';
  237.         Delay1(1);
  238. }
  239. void at_uart_send_buf(unsigned char *str,unsigned char len)
  240. {
  241.   unsigned char *st_p=str;
  242.   
  243.   while(len){
  244.      SBUF=*st_p;
  245.          st_p++;
  246.          Delay1(1);
  247.          len--;
  248.         }while(*st_p);
  249.         SBUF='\r';
  250.         Delay1(1);
  251.         SBUF='\n';
  252.         Delay1(1);
  253. }
  254. void main(void)
  255. {
  256.         char i=0;;
  257.         B_TX1_Busy = 0;
  258.         RX1_Cnt = 0;
  259.         TX1_Cnt = 0;
  260.         S1_8bit();                                //8位数据
  261.         S1_USE_P30P31();                //UART1 使用P30 P31口        默认
  262.         AUXR &= ~(1<<4);        //Timer stop                波特率使用Timer2产生
  263.         AUXR |= 0x01;                //S1 BRT Use Timer2;
  264.         AUXR |=  (1<<2);        //Timer2 set as 1T mode
  265.         TH2 = (u8)(Timer2_Reload >> 8);
  266.         TL2 = (u8)Timer2_Reload;
  267.         AUXR |=  (1<<4);        //Timer run enable
  268.         REN = 1;        //允许接收
  269.         ES  = 1;        //允许中断
  270.         EA = 1;                //允许全局中断
  271.         P3M1 = 0x00;
  272.     P3M0 = 0xFF;
  273.         RX1_Cnt=0;
  274.         DK1=0;
  275.         BEEP=0;
  276.         for(;;)//AT+CWMODE=2 设置成路由模式
  277.         {
  278.                 //SBUF='A';Delay1(1);


  279.                 Delay2(2000);
  280.         at_uart_send_str(AT_MODE);
  281.                 Delay2(2000);
  282.         at_uart_send_str(AT_CWJAP);
  283.                 Delay2(4000);
  284.         at_uart_send_str(CIPSTART);
  285.                 Delay2(2000);
  286.                 make_send_pack(0,esp_dev_id,esp_TOK_id,esp_user_data,8);
  287.                 make_AT_SEND(need_seed_len);                     //将要发送的总字节数变成10进制动态修改AT发送指令           at_uart_send_str(at_send_len_ox);
  288.         at_uart_send_str(at_send_len_ox);                //动态发送数据长度
  289.                 Delay2(2000);
  290.                 at_uart_send_buf(temp_buf,need_seed_len);
  291.                 while(1)
  292.                 {
  293.                   if(have_data)
  294.                   {
  295.                     have_data=0;
  296.                         LED1=0;
  297.                         Delay2(200);
  298.                     LED1=1;
  299.                   }
  300.                 }
  301.         }
  302.         Delay2(2000);
  303. }

  304. /********************* UART1中断函数************************/
  305. void UART1_int (void) interrupt UART1_VECTOR
  306. {
  307.         if(RI)
  308.         {
  309.                 RI = 0;
  310.                 LED1=0;
  311.                 LED1=1;
  312.                 recd_buf[RX1_Cnt] = SBUF;                //保存一个字节
  313.                 if(RX1_Cnt<62)
  314.                 RX1_Cnt++;
  315.                 else
  316.                 RX1_Cnt=0;
  317.                  if(recd_buf[RX1_Cnt]==0X55)
  318.                    two_lab++;
  319.                  if(two_lab==2)
  320.                  {
  321.                    have_data=1;
  322.                    two_lab=0;
  323.                    rec_len=RX1_Cnt;
  324.                    RX1_Cnt=0;
  325.                  }
  326.         }
  327.         if(TI)
  328.         {
  329.                 TI = 0;
  330.                 B_TX1_Busy = 0;                //清除发送忙标志
  331.         }
  332. }
复制代码


  1. /*************        本地常量声明        **************/
  2. #define MAIN_Fosc                22118400L        //定义主时钟
  3. #define        RX1_Lenth                32                        //串口接收缓冲长度
  4. #define        BaudRate1                115200UL        //选择波特率
  5. #define        Timer1_Reload        (65536UL -(MAIN_Fosc / 4 / BaudRate1))                //Timer 1 重装值, 对应300KHZ
  6. #define        Timer2_Reload        (65536UL -(MAIN_Fosc / 4 / BaudRate1))                //Timer 2 重装值, 对应300KHZ
  7. #include        "STC15Fxxxx.H"
  8. /*************        本地变量声明        **************/
  9. u8        idata RX1_Buffer[RX1_Lenth];        //接收缓冲
  10. u8        TX1_Cnt;        //发送计数
  11. u8        RX1_Cnt;        //接收计数
  12. bit        B_TX1_Busy;        //发送忙标志
  13. /*************        端口引脚定义        **************/
  14. unsigned char two_lab=0;
  15. sbit LED1=P1^0;//LED1
  16. sbit LED2=P1^1;//LED2
  17. sbit LED3=P3^7;//LED3
  18. sbit DK1=P3^3;//继电器
  19. sbit BEEP=P3^4;//蜂鸣器
  20. sbit K1=P1^3;//按键1
  21. sbit K2=P1^2;//按键2
  22. sbit K3=P1^4;//按键3


  23. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  24. #define O_PF    0X00  //包头1字节固定0X55
  25. #define O_LEN_L 0X01  //整个包长低字节
  26. #define O_LEN_H 0X02  //整个包长高字节 注意转义码 两个这里只计算一个数据处理!
  27. #define O_CMD_T 0X03  //命令类型
  28. #define O_CMD_C 0X04  //具体命令
  29. #define O_CIX_L 0X05  //本命令序列编号低字节
  30. #define O_CIX_H 0X06  //本命令序列编号高字节
  31. #define O_EXMSH 0X07  //扩展信息高字节
  32. #define O_EXMSL 0X08  //扩展信息低字节
  33. #define O_RESTA 0X09  //数据包状态信息,成功 失败 请求 未知
  34. #define O_DEVID 0x0A  //8字节设备识别
  35.    //1 BYTS TL_LEN          //获得的设备临时通讯令牌长度
  36.    //N BYTS TK                   //TL_LEN个通讯令牌串
  37.    //N BYTS DATAS          //客户的数据包串
  38.    //CRC_L    1BYTE          //CRC16 低字节
  39.    //CRC_H    1BYTE          //CRC16 高字节
  40.    //PACK_END 1BYTE          //包尾1字节固定0X55

  41. ////////////////////////////////////////////////////////////////////////以上定义了包中的各参数的绝对位置//////////////////////////////////

  42. char led1bl,led2bl,led3bl;

  43. code unsigned char AT_RST[]="AT+RST";                                                     
  44. code unsigned char AT_MODE[]="AT+CWMODE=3";
  45. code unsigned char AT_CWJAP[]="AT+CWJAP=\"360we\",\"zty0012001\"";
  46. code unsigned char CIPSTART[]="AT+CIPSTART=\"UDP\",\"cloud.ai-thinker.com\",5001";
  47. //////////////////////////////////////////////////////////////////////以上部分发送指令让单片机连入内部网络////////////////////////////////
  48. code unsigned char CIPSEND_LEN[]="AT+CIPSEND=38";//AT指令发送数据38字节的数据到网络上//////////////////////
  49. unsigned char at_send_len_ox[16];                //上面一条指令只能发送38的静态包长,这里用个RAM存储上边CODE的AT指令"AT+CIPSEND=38"可以修改后面的38,为任意数
  50. unsigned char send_buf[64];                             //发送缓冲区
  51. unsigned char recd_buf[64];                                                 //接收缓冲区
  52. data unsigned char temp_buf[64];                                 //加工缓冲区
  53. unsigned char toke[8]={0x24,0x41,0xD6,0x39,0x48,0x83,0xAC,0x00};//此设备在服务器上获得的令牌包

  54. /////////////////////////////////////////////////////////////////下面部分定义了CRC16校验函数用到的表格///////////////////////////////////
  55. code unsigned int crc_table[256]=
  56. {               /* CRC余式表 */
  57. 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
  58. 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
  59. 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
  60. 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
  61. 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
  62. 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
  63. 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
  64. 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
  65. 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
  66. 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
  67. 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
  68. 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
  69. 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
  70. 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
  71. 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
  72. 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
  73. 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
  74. 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
  75. 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
  76. 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
  77. 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
  78. 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
  79. 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
  80. 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
  81. 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
  82. 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
  83. 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
  84. 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
  85. 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
  86. 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
  87. 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
  88. 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
  89. };
  90. /////////////////////////////////////////////////////////////////上面部分定义了CRC16校验函数用到的表格///////////////////////////////////
  91. bit t_o=0;
  92. void make_AT_SEND(unsigned char a_len)//生成右边这样的指令,将参数a_len 改成10进制  "AT+CIPSEND=38"
  93. {
  94.   unsigned char aa=0;
  95.   for(aa=0;aa<11;aa++)
  96.   {
  97.     at_send_len_ox[aa]=CIPSEND_LEN[aa];         //剪贴"AT+CIPSEND= 到RAM  后面的十进制参数由下面的部分生成
  98.   }
  99.   t_o=0;                                 //去掉前面的0,比如发送38个字节,038,前面的0就可以去掉了。
  100.   if((a_len/100))
  101.   {
  102.   at_send_len_ox[aa]=a_len/100+'0';
  103.   aa++;
  104.   t_o=1;
  105.   }
  106.   if((a_len%100)/10)
  107.   {
  108.   at_send_len_ox[aa]=(a_len%100)/10+'0';
  109.   aa++;
  110.   t_o=1;
  111.   }
  112.   else if(t_o)
  113.   {
  114.     at_send_len_ox[aa]=0+'0';
  115.         aa++;
  116.   }
  117.   at_send_len_ox[aa]=(a_len%10)+'0';
  118.   aa++;
  119.   at_send_len_ox[aa]=0;
  120. }
  121. //下面函数获得CRC校验码 采用标准CRC16 初始CRC=0XFFFF  运算多项式参数 8005 非1021
  122. unsigned int GetRevCrc_16(unsigned char * pData, int nLength)
  123. {
  124.   unsigned int cRc_16 = 0xffff;
  125.   unsigned char temp;

  126.   while(nLength-- > 0)
  127.   {
  128.     temp = cRc_16&0xff;
  129.     cRc_16 = (cRc_16 >> 8) ^ crc_table[(temp ^ *pData++) & 0xFF];
  130.   }

  131.   return cRc_16;   
  132. }

  133. #define O_PF    0X00  //包头1字节固定0X55
  134. #define O_LEN_L 0X01  //整个包长低字节
  135. #define O_LEN_H 0X02  //整个包长高字节 注意转义码 两个这里只计算一个数据处理!
  136. #define O_CMD_T 0X03  //命令类型
  137. #define O_CMD_C 0X04  //具体命令
  138. #define O_CIX_L 0X05  //本命令序列编号低字节
  139. #define O_CIX_H 0X06  //本命令序列编号高字节
  140. #define O_EXMSH 0X07  //扩展信息高字节
  141. #define O_EXMSL 0X08  //扩展信息低字节
  142. #define O_RESTA 0X09  //数据包状态信息,成功 失败 请求 未知
  143. #define O_DEVID_START 0x0A  //8字节设备识别  低字节在前
  144. #define O_TK_LEN      0X12 //1 BYTS TL_LEN          //获得的设备临时通讯令牌长度
  145. #define O_TOKE_START  0X13
  146. #define O_DATAS_START 0X1B
  147.    //N BYTS DATAS          //客户的数据包串
  148.    //CRC_L    1BYTE          //CRC16 低字节
  149.    //CRC_H    1BYTE          //CRC16 高字节
  150.    //PACK_END 1BYTE          //包尾1字节固定0X55

  151. unsigned char esp_dev_id[8]={0,0,0,0,0,0,0X1E,0XE6};         //    8266的8个字节的器件ID号,可在服务器数据库中查到,唯一标示一个器件,登录过程需要一个器件ID,和数据区放一个数据密码,这么简单登录
  152. unsigned char esp_TOK_id[8]={0,0,0,0,0,0,0,0};                                 //    服务器分给器件器件的令牌包,另外个地方也定义了,完全可以用一个数组完成的
  153. unsigned char esp_user_data[14]={0,0,0,0,0,0,0X1E,0XE6};         //    客户的净数据负荷区,可以很大,因为本款单片机有限,并且一般控制信号,定义几个字节够了!注意在登录的时候,这里是器件密码!
  154. unsigned char temp_cd[]="TEMP:123;";                                                 //    一个数据包,前面是包格式定义,后面是客户数据区,这里定义一个即将要发送的温度数据
  155. unsigned char need_seed_len=0;                                                                 //    全局变量,本次总共需要发到串口的数据


  156. //下面这个函数构造一个发送的数据格式,请看数据格式文档,完全可以用结构体完成,这里采用数据,从上到下描述这个数据包
  157. //发送的数据包,目前只有登录数据包,和上报温度数据包,这两个基本的数据包,上报数据包可以充当心跳包,第一个参数决定着,是发送登录包还是温度包
  158. //其他几个入口参数是器件ID,令牌包,以及客户的数据,以及客户数据长度

  159. void make_send_pack(unsigned char ms_opt,unsigned char *dev_id,unsigned char *toke_id,unsigned char *use_data,unsigned char use_data_len)
  160. {
  161.   unsigned char a,b,i=0;
  162.   unsigned esp_crc=0;
  163.   send_buf[0]=0x55;                                                     //包头是0X55固定
  164.   
  165.   send_buf[O_LEN_L]=(O_DATAS_START+use_data_len+3)%0xff; //本数据包的所有数据长度,包头至包尾,记得是没有经过转义前的包长
  166.   send_buf[O_LEN_H]=(O_DATAS_START+use_data_len+3)/0xff;

  167.   if(ms_opt==0)                                                                                         //根据入口参数判断是发送登录链路操作,还是发送数据包云平台
  168.   send_buf[O_CMD_T]=0XA0;// 0XA0 链路操作 0XAA 数据传输 0XAC 实时检测指令 0XF0 终端操作
  169.   else if (ms_opt==1)
  170.   send_buf[O_CMD_T]=0XAA;// 0XA0 链路操作 0XAA 数据传输 0XAC 实时检测指令 0XF0 终端操作

  171.   if(ms_opt==0)                                                                //0X00代表登录操作
  172.   send_buf[O_CMD_C]=0X00;// reg  option
  173.   else if (ms_opt==1)
  174.   send_buf[O_CMD_C]=0XEE;                                                    //0XEE代表数据是从设备到云平台的方向

  175.   send_buf[O_CIX_L]=0XF3;// CMD INDEXL                        //命令序列编号,暂时不用,可以作为对方应答的数据包号标示
  176.   send_buf[O_CIX_H]=0XC0;//        CMD INDEXL                                        //命令序列编号,暂时不用,可以作为对方应答的数据包号标示
  177.   send_buf[O_EXMSH]=0XC0;//        EXTERN MESSAGE1                                //扩展子暂时保留
  178.   send_buf[O_EXMSL]=0XF3;//        EXTERN MESSAGE2                                //扩展子暂时保留

  179.   send_buf[O_RESTA]=0X02;//        CMD_STA 00 OK 01 FAIL 02 SEND 03 NO SUP         //代表本数据包的状态,是发送还是应答成功还是失败

  180.   for(i=0;i<8;i++)
  181.   send_buf[O_DEVID+i]=*(dev_id+(7-i)); // 拷贝设备的唯一ID号到数据包里


  182.   send_buf[O_TK_LEN] =8;                   //代表接下来的令牌包是8个字节


  183.   for(i=0;i<8;i++)
  184.   send_buf[O_TOKE_START+i]=*(toke_id+i);//8个字节令牌包,初始令牌包为00 后续服务器会分配一个令牌包给这个设备,设备每次通讯要携带这个令牌包


  185.   for(i=0;i<use_data_len;i++)
  186.   send_buf[O_DATAS_START+i]=*(use_data+i); // 客户的数据区,登录的时候放数据密码文本
  187.   
  188.   temp_buf[0]=0x55;                                                   //包尾

  189.   esp_crc=GetRevCrc_16(send_buf,O_DATAS_START+use_data_len);//得到转义之前的总数据包CRC,具体可以参照CRC数据格式,因此CRC是针对转义之前的数据生成

  190.   for(a=1,b=1;a<(O_DATAS_START+use_data_len);a++)           //将出去包头,所有的数据中含有有0X55的数据转义成0X54,0X01,将0X54 变成0X54,02,重新转义数据包
  191.   {
  192.     if(send_buf[a]==0x55)
  193.         {
  194.           temp_buf[b]=0x54;
  195.           b+=1;
  196.           temp_buf[b]=0x01;
  197.           b+=1;
  198.         }
  199.         else if(send_buf[a]==0x54)
  200.         {
  201.           temp_buf[b]=0x54;
  202.           b+=1;
  203.           temp_buf[b]=0x02;
  204.           b+=1;
  205.         }
  206.         else
  207.         {
  208.         temp_buf[b]=send_buf[a];
  209.         b+=1;
  210.         }
  211. }         ///////////////////////////////////////////////////////////以上的语句转义数据包中除包头到CRC之前的全部的数据///////////////////////////////////////////////////////////////////////
  212. //55 28 00 AA EE F3 C0 C0 F3 02 E6 1E 00 00 00 00 00 00 08 24 41 D6 39 48 83 AC 00 54 02 45 4D 50 3A 32 35 35 3B 00 D1 52 55
  213. //55 28 00 AA EE F3 C0 C0 F3 02 E6 1E 00 00 00 00 00 00 08 24 41 D6 39 48 83 AC 00 54 02 45 4D 50 3A 32 35 35 3B 00 D1 52 55

  214. temp_buf[b]=(esp_crc>>8);
  215. b+=1;
  216. temp_buf[b]=(esp_crc&0x00ff);         
  217. b+=1;
  218.     ///////////////////////////////////////////////////////////上面两句加上CRC校验////////////////////////////////////////
  219. temp_buf[b]=0x55;        //包尾
  220. b+=1;
  221. temp_buf[b]=0x0d;
  222. b+=1;
  223. temp_buf[b]=0x0a;
  224. b+=1;                                //以上构成回车
  225. need_seed_len=b;        //至此构造出了需要发送的全部数据 包括AT指令需要的换行
  226. }
  227. bit have_data=0;
  228. unsigned char rec_len=0;


  229. void Delay1(unsigned long ms)//简单延迟函数,单位是毫秒
  230. {
  231.         unsigned char i, j,k;
  232.         for(k=0;k<ms;k++)
  233.         {
  234.                 _nop_();
  235.                 _nop_();
  236.                 i = 22;
  237.                 j = 128;
  238.                 do
  239.                 {
  240.                         while (--j);
  241.                 } while (--i);
  242.         }
  243. }
  244. void Delay2(unsigned long cnt)
  245. {
  246.         long i;
  247.         for(i=0;i<cnt*100;i++);
  248. }

  249. void at_uart_send_str(unsigned char *str)//发送AT字符串到串口
  250. {
  251.   unsigned char *st_p=str;
  252.   do{
  253.      SBUF=*st_p;
  254.          st_p++;
  255.          Delay1(1);
  256.         }while(*st_p);
  257.         SBUF='\r';
  258.         Delay1(1);
  259.         SBUF='\n';
  260.         Delay1(1);
  261. }
  262. void at_uart_send_buf(unsigned char *str,unsigned char len)//发送数据缓冲区的非字符串信息,数据流信息到串口
  263. {
  264.   unsigned char *st_p=str;
  265.   
  266.   while(len){
  267.      SBUF=*st_p;
  268.          st_p++;
  269.          Delay1(1);
  270.          len--;
  271.         }while(*st_p);
  272.         SBUF='\r';
  273.         Delay1(1);
  274.         SBUF='\n';
  275.         Delay1(1);
  276. }
  277. unsigned int time=0; //每隔30秒把一个变量加1,然后把这个变量作为温度数据上报给云平台,转给手机端
  278. void main(void)
  279. {
  280.         char tt,i=0;;
  281.         //////////////////////////////////////////////////////////////////////////////////////下面部分为定时器以及串口初始化/////////////////////
  282.         B_TX1_Busy = 0;
  283.         RX1_Cnt = 0;
  284.         TX1_Cnt = 0;
  285.         S1_8bit();                                //8位数据
  286.         S1_USE_P30P31();                //UART1 使用P30 P31口        默认
  287.         AUXR &= ~(1<<4);        //Timer stop                波特率使用Timer2产生
  288.         AUXR |= 0x01;                //S1 BRT Use Timer2;
  289.         AUXR |=  (1<<2);        //Timer2 set as 1T mode
  290.         TH2 = (u8)(Timer2_Reload >> 8);
  291.         TL2 = (u8)Timer2_Reload;
  292.         AUXR |=  (1<<4);        //Timer run enable
  293.         REN = 1;        //允许接收
  294.         ES  = 1;        //允许中断
  295.         EA = 1;                //允许全局中断
  296.         P3M1 = 0x00;
  297.     P3M0 = 0xFF;
  298.         RX1_Cnt=0;
  299.         DK1=0;
  300.         BEEP=0;
  301.         ///////////////////////////////////////////////////////////////////////////////////以上部分主要完成串口的初始化////////////////////////////
  302.         for(;;)
  303.         {        //////////////////////////////////////////////////////////下面的语句发送AT指令加入内网,并链接到安信可物联网服务器/////////////////////
  304.                 Delay2(2000);
  305.         at_uart_send_str(AT_MODE);
  306.                 Delay2(2000);
  307.         at_uart_send_str(AT_CWJAP);
  308.                 Delay2(10000);
  309.         at_uart_send_str(CIPSTART);
  310.                 Delay2(2000);
  311.                 //////////////////////////////////////////////////////////上面面的语句发送AT指令加入内网,并链接到安信可物联网服务器/////////////////////
  312.                 make_send_pack(0,esp_dev_id,esp_TOK_id,esp_user_data,8);//构造登录数据包
  313.                 make_AT_SEND(need_seed_len);                            //将要进过WIFI发送的总字节数变成10进制,动态生成发送数据AT指令
  314.         at_uart_send_str(at_send_len_ox);                       //将构造好的AT发送数据到互联网的动态发送数据长度
  315.                 Delay2(2000);
  316.                 at_uart_send_buf(temp_buf,need_seed_len);                                //经过WIFI模块发送构造好的登录包
  317.                 while(1)
  318.                 {
  319.                         for(tt=0;tt<60;tt++)
  320.                         {
  321.                         Delay2(200);
  322.                         Delay2(200);
  323.                         }
  324.                     make_send_pack(1,esp_dev_id,toke,temp_cd,10);    //构造上传数据到云,转给手机的温度数据包,符合基本数据格式
  325.                     make_AT_SEND(need_seed_len);                                          //动态构造发送AT指令
  326.                         at_uart_send_str(at_send_len_ox);                //发送构造好的发送指令
  327.                     Delay2(2000);
  328.                     at_uart_send_buf(temp_buf,need_seed_len);             //经过WIFI发送数据

  329.                         LED1=0;
  330.                         Delay2(200);
  331.                     LED1=1;
  332.                         Delay2(200);
  333.                                                                                                                         //每30秒会运行到这里一次。更新一次温度数值
  334.                         time++;
  335.                         temp_cd[5]=(((time%1000)/100)+'0');
  336.                         temp_cd[6]=(((time%100)/10)+'0');
  337.                     temp_cd[7]=(((time%10))+'0');
  338.                 }
  339.         }
  340.         Delay2(2000);
  341. }

  342. /********************* UART1中断函数************************/
  343. bit a_vec=0;
  344. void UART1_int (void) interrupt UART1_VECTOR
  345. {
  346.         if(RI)
  347.         {
  348.                 RI = 0;
  349.                 if(SBUF==0x55)         //////////////////////////////////////下面的语句根据固定的数据包格式,简单取出想要的数据/////////////////////////////////
  350.                 a_vec=1;
  351.                 if(a_vec)
  352.                 {
  353.                  recd_buf[RX1_Cnt] = SBUF;                //保存一个字节
  354.                  if(RX1_Cnt<62)
  355.                    RX1_Cnt++;
  356.                  else
  357.                    RX1_Cnt=0;
  358.                  if(recd_buf[RX1_Cnt]==0X55)
  359.                    two_lab++;
  360.                  if(two_lab==2)//////////////////////////////////////////取出2个OX55之间的有效数据////////////////////
  361.                  {
  362.                    have_data=1;
  363.                    two_lab=0;
  364.                    rec_len=RX1_Cnt;
  365.                    RX1_Cnt=0;
  366.                    a_vec=0;
  367.                     if((recd_buf[33])==':')              /////////////////////////////////////简单得到手机的开指令////////////////////
  368.                         {

  369.                         if((recd_buf[34])=='0')
  370.                         {
  371.                           LED1=0;          //开灯指令
  372.                           toke[7]=recd_buf[19];             //////////////郁闷的是模块是令牌包,是登录服务器的时候,只发送一次! 这个时候串口处于未知状态,因此经常把第一个包丢了
  373.                           toke[6]=recd_buf[20];                 //////////////串口接收到的第一个数据包就是服务器回复的令牌包,本单片机第一恰好丢掉,但是一旦登录上服务器,只要手机发
  374.                           toke[5]=recd_buf[21];                 //////////////一个控制开关指令到模块,在这个指令的固定位置,比如19位置处,放的就是可能丢的令牌包!
  375.                           toke[4]=recd_buf[22];                 //////////////保留好这个令牌包,以后模块发送到云平台的数据,到要用到这个令牌包
  376.                           toke[3]=recd_buf[23];
  377.                           toke[2]=recd_buf[24];
  378.                           toke[1]=recd_buf[25];
  379.                           toke[0]=recd_buf[26];
  380.                         }
  381.                         else if((recd_buf[34])=='1')
  382.                       LED1=1;  //关灯指令
  383.                         }
  384.                  }
  385.                  }
  386.         }
  387.         if(TI)
  388.         {
  389.                 TI = 0;
  390.                 B_TX1_Busy = 0;                //清除发送忙标志
  391.         }
  392. }
复制代码


  1.                                                    /*------------------------------------------------------------------------------
  2. HELLO.C

  3. Copyright 1995-2005 Keil Software, Inc.
  4. ------------------------------------------------------------------------------*/

  5. #include <REG52.H>                /* special function register declarations   */
  6.                                   /* for the intended 8051 derivative         */

  7. #include <stdio.h>                /* prototype declarations for I/O functions */


  8. #ifdef MONITOR51                         /* Debugging with Monitor-51 needs   */
  9. char code reserve [3] _at_ 0x23;         /* space for serial interrupt if     */
  10. #endif                                   /* Stop Exection with Serial Intr.   */
  11.                                          /* is enabled                        */


  12. /*------------------------------------------------
  13. The main C function.  Program execution starts
  14. here after stack initialization.
  15. ------------------------------------------------*/
  16. #define CRC_SEED   0xFFFF   // 该位称为预置值,使用人工算法(长除法)时 需要将除数多项式先与该与职位 异或 ,才能得到最后的除数多项式
  17. #define POLY16 0x1021  // 该位为简式书写 实际为0x11021
  18. unsigned char crc_16[35]={0x55,0x26,0x00,0xA0,0x00,0xA8,0x16,0x16,0xA8,0x02,0xE6,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0xe6};
  19. unsigned char crc_12[6]={1,3,0,0,0,1};
  20. code unsigned int crc_table[256]={               /* CRC余式表 */
  21.     0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
  22.     0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
  23.     0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
  24.     0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
  25.     0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
  26.     0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
  27.     0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
  28.     0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
  29.     0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
  30.     0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
  31.     0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
  32.     0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
  33.     0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
  34.     0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
  35.     0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
  36.     0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
  37.     0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
  38.     0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
  39.     0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
  40.     0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
  41.     0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
  42.     0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
  43.     0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
  44.     0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
  45.     0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
  46.     0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
  47.     0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
  48.     0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
  49.     0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
  50.     0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
  51.     0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
  52.     0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
  53.   };
  54. /*
  55. unsigned int crc16(unsigned char *buf,unsigned short length)
  56. {
  57.   int shift,data1,val;
  58.   int i;

  59.   shift = CRC_SEED;


  60.   for(i=0;i<length;i++) {
  61.     if((i % 8) == 0)
  62.       data1 = (*buf++)<<8;
  63.     val = shift ^ data1;
  64.     shift = shift<<1;
  65.     data1 = data1 <<1;
  66.     if(val&0x8000)
  67.       shift = shift ^ POLY16;
  68.   }
  69.   return shift;
  70. }
  71. */


  72. unsigned char crc_t=0;
  73. unsigned int crc=0;
  74. unsigned int do_crc_table(unsigned char *ptr,int len)
  75. {
  76.    unsigned int crc;
  77.    unsigned char da;
  78.    crc=0;
  79.    while(len--!=0)
  80.     {

  81.        da=(unsigned char) (crc/256); //存储CRC的高8位

  82.        crc<<=8;//左移8位,相当于CRC的低8位乘以2^8

  83.       
  84.        crc^= crc_table[da^*ptr];         ptr++;

  85.       //高8位和当前字节相加后再查表求的CRC,再加上以前的CRC
  86.       }
  87.    return(crc);
  88. }

  89. void main (void) {

  90. /*------------------------------------------------
  91. Setup the serial port for 1200 baud at 16MHz.
  92. ------------------------------------------------*/
  93. #ifndef MONITOR51
  94.     SCON  = 0x50;                        /* SCON: mode 1, 8-bit UART, enable rcvr      */
  95.     TMOD |= 0x20;               /* TMOD: timer 1, mode 2, 8-bit reload        */
  96.     TH1   = 221;                /* TH1:  reload value for 1200 baud @ 16MHz   */
  97.     TR1   = 1;                  /* TR1:  timer 1 run                          */
  98.     TI    = 1;                  /* TI:   set TI to send first char of UART    */
  99. #endif

  100. /*------------------------------------------------
  101. Note that an embedded program never exits (because
  102. there is no operating system to return to).  It
  103. must loop and execute forever.
  104. ------------------------------------------------*/
  105. crc=do_crc_table(crc_16,35);
  106.   while (1) {
  107.     P1 ^= 0x01;                         /* Toggle P1.0 each time we print */
  108.     printf ("Hello World\n");   /* Print "Hello World" */
  109.   }
  110. }

复制代码



评分

参与人数 1黑币 +5 收起 理由
qjyjack612510 + 5 很给力!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏16 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:71423 发表于 2016-4-10 21:46 | 只看该作者
非常感谢楼主分享
回复

使用道具 举报

板凳
ID:114158 发表于 2016-4-14 11:42 | 只看该作者
感谢楼主分享
回复

使用道具 举报

地板
ID:126573 发表于 2016-6-23 11:21 | 只看该作者
谢谢楼主分享,学习学习。。。。。
回复

使用道具 举报

5#
ID:129989 发表于 2016-7-11 11:17 | 只看该作者
楼主好棒
回复

使用道具 举报

6#
ID:129989 发表于 2016-7-11 11:20 | 只看该作者
用什么软件打开呢
回复

使用道具 举报

7#
ID:79544 发表于 2016-7-11 19:41 | 只看该作者
很好的资料谢谢分享。
回复

使用道具 举报

8#
ID:79544 发表于 2016-7-11 19:42 | 只看该作者
楼主你好:手机AAP在哪里下载,谢谢请指教!
回复

使用道具 举报

9#
ID:79544 发表于 2016-7-11 19:43 | 只看该作者

kiluv4
回复

使用道具 举报

10#
ID:102293 发表于 2016-7-11 22:33 | 只看该作者
学习学习,非常感谢楼主分享
回复

使用道具 举报

11#
ID:129868 发表于 2016-7-12 10:36 | 只看该作者
来学习学习
回复

使用道具 举报

12#
ID:130791 发表于 2016-7-17 13:49 | 只看该作者
过来学习!!!
回复

使用道具 举报

13#
ID:134757 发表于 2016-7-23 21:20 | 只看该作者

学习学习,非常感谢楼主分享
回复

使用道具 举报

14#
ID:136422 发表于 2016-8-10 12:54 | 只看该作者
学习一下
回复

使用道具 举报

15#
ID:136422 发表于 2016-8-10 12:55 | 只看该作者
学习学习,非常感谢楼主分享
回复

使用道具 举报

16#
ID:137635 发表于 2016-8-26 09:42 | 只看该作者
先收藏了,谢谢楼主
回复

使用道具 举报

17#
ID:128463 发表于 2016-8-29 17:40 | 只看该作者
很好的资料谢谢分享!!!!
回复

使用道具 举报

18#
ID:138902 发表于 2016-9-8 23:51 | 只看该作者
谢谢分享!!!
回复

使用道具 举报

19#
ID:121470 发表于 2016-9-28 14:17 | 只看该作者
看得不是很多,学习一下
回复

使用道具 举报

20#
ID:149037 发表于 2016-12-17 14:37 | 只看该作者

学习学习,非常感谢楼主分享
回复

使用道具 举报

21#
ID:75062 发表于 2017-1-3 22:24 | 只看该作者
谢谢楼主分享
回复

使用道具 举报

22#
ID:162349 发表于 2017-1-18 21:34 | 只看该作者
感谢楼主
回复

使用道具 举报

23#
ID:166195 发表于 2017-2-23 15:45 | 只看该作者
已收藏,非常感谢楼主,学习中
回复

使用道具 举报

24#
ID:166347 发表于 2017-2-24 10:24 | 只看该作者
 非常感谢楼主分享
回复

使用道具 举报

25#
ID:169508 发表于 2017-3-9 21:57 | 只看该作者
其实我想知道发送原理是什么,既然PC可以通过串口向单片机发送信息,能否直接改为由单片机先模块发送信息,不过失败了,实在弄不清原理
回复

使用道具 举报

26#
ID:47286 发表于 2017-3-10 14:13 | 只看该作者
感谢楼主分享 学习了
回复

使用道具 举报

27#
ID:166895 发表于 2017-3-27 20:49 | 只看该作者
感谢楼主分享
回复

使用道具 举报

28#
ID:185256 发表于 2017-4-13 01:13 | 只看该作者
能直接移植到 STM8 上面吗? 怎么做呢?
回复

使用道具 举报

29#
ID:185256 发表于 2017-4-13 16:54 | 只看该作者
很好的资料谢谢分享!!!!
回复

使用道具 举报

30#
ID:186249 发表于 2017-4-14 15:22 | 只看该作者
这个不错,我看看
回复

使用道具 举报

31#
ID:110687 发表于 2017-4-24 13:03 | 只看该作者
谢谢搂住,谢谢你的共享!在学习中。。。。。。
回复

使用道具 举报

32#
ID:196946 发表于 2017-5-5 15:19 | 只看该作者
感谢分享
回复

使用道具 举报

33#
ID:25518 发表于 2017-5-29 15:12 | 只看该作者
真心感谢分享。
回复

使用道具 举报

34#
ID:209407 发表于 2017-6-9 02:31 | 只看该作者
这个看看,谢谢分享
回复

使用道具 举报

35#
ID:104683 发表于 2017-6-10 19:42 | 只看该作者
正好学到 谢谢分享
回复

使用道具 举报

36#
ID:211931 发表于 2017-6-16 18:46 | 只看该作者
非常感谢楼主的分享
回复

使用道具 举报

37#
ID:215781 发表于 2017-6-29 12:59 | 只看该作者
很棒,学习了
回复

使用道具 举报

38#
ID:218517 发表于 2017-7-10 15:13 | 只看该作者
感谢楼主的分享!
回复

使用道具 举报

39#
ID:227029 发表于 2017-8-11 17:36 | 只看该作者
很给力qqdqdq
回复

使用道具 举报

40#
ID:210861 发表于 2017-9-6 15:11 | 只看该作者
谢谢楼主的无私分享!!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表