找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 42281|回復: 61
收起左側

ESP8266用STC單片機發(fā)送AT命令來連接網絡的程序

  [復制鏈接]
ID:112317 發(fā)表于 2016-4-5 14:46 | 顯示全部樓層 |閱讀模式

全部源碼下載:
ESP8266用單片機發(fā)送AT命令來連接網絡的程序.zip (215.17 KB, 下載次數: 628)


主程序:
  1. /*

  2.   本程序用51單片機經過AT指令控制模塊,完成從SMARTLINK 到 手機與模塊的綁定,以及云品臺的登錄,本地數據發(fā)給異地手機,手機異地控制測試板上的繼電器動作。
  3.   本程序可以移植到STM8這款只要1元錢的單片機上配合AT模塊,完成高性價的產品,比如開關插座。主要演示安信可的云平臺的試用!以及整個物聯網的流程

  4.   注意:變量初始化成0,否者隨機  數組注意溢出問題  0X55 在其他數據中有可能出現,并造成混亂,主要是計數  過濾數據,根據網絡環(huán)境不同,返回有可能變化,注意通用性
  5.   內部 ID KEY 輸出格式已經固定為8個字節(jié)模式          本程序用的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 發(fā)送數據: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 發(fā)送到安信可云服務器,就能通訊了
  10.    
  11.   時間倉促,完成功能后,未經過優(yōu)化代碼優(yōu)化,和語法風格修改,供參考。輔助文檔有這個程序設計框架解釋,和詳細的指導,這些文件均可以在安信可官網
  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;        //發(fā)送計數
  25. u8        RX1_Cnt;        //接收計數
  26. bit        B_TX1_Busy;        //發(fā)送忙標志
  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. /////這是安信可云平臺數據包的全部組成結構,細節(jié)可參照安信可的云平臺V1.0版本規(guī)格書,包結構章節(jié)
  39. #define O_PF    0X00  //包頭1字節(jié)固定0X55
  40. #define O_LEN_L 0X01  //整個包長低字節(jié)
  41. #define O_LEN_H 0X02  //整個包長高字節(jié) 注意轉義碼 兩個這里只計算一個數據處理!
  42. #define O_CMD_T 0X03  //命令類型
  43. #define O_CMD_C 0X04  //具體命令
  44. #define O_CIX_L 0X05  //本命令序列編號低字節(jié)
  45. #define O_CIX_H 0X06  //本命令序列編號高字節(jié)
  46. #define O_EXMSH 0X07  //擴展信息高字節(jié)
  47. #define O_EXMSL 0X08  //擴展信息低字節(jié)
  48. #define O_RESTA 0X09  //數據包狀態(tài)信息,成功 失敗 請求 未知
  49. #define O_DEVID_START 0x0A  //8字節(jié)設備識別  低字節(jié)在前
  50. #define O_DEVID 0x0A  //8字節(jié)設備識別
  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 低字節(jié)
  56. //CRC_H    1BYTE          //CRC16 高字節(jié)
  57. //PACK_END 1BYTE          //包尾1字節(jié)固定0X55

  58. ////////////////////////////////////////////////////////////////////////以上定義了包中的各參數的絕對位置//////////////////////////////////
  59. #define uart_rec_tcp_udp_data 0        //系統進入正常網絡數據收發(fā)狀態(tài)
  60. #define uart_rec_csysid       1        //系統獲取ESP8266WIFI模塊的許可號狀態(tài),獲取四個字節(jié)的芯片ID 和 4個字節(jié)的授權碼
  61. #define uart_rec_smartlink    2        //系統進入獲取上網賬號密碼狀態(tài)
  62. #define uart_rec_bander       3        //系統進入將本WIFI設備 和APP 手機綁定控制狀態(tài)
  63. //////////////////////////////////////////////////////////////////////以上部分定義了系統的幾種狀態(tài)///////////////////////////////////////
  64. bit have_tok=0;
  65. bit have_data=0;
  66. unsigned char rec_len=0;
  67. bit                   a_vec=0;                   //設置一個標志位,串口程序 出現指定的字串,并動態(tài)過濾到指定的字符后 置1
  68. unsigned char          ceng=0;         //最多 多少字節(jié)內 會出現指定字串,靜態(tài)變量,
  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;// 串口目前所處于的狀態(tài),比如進入正常數據接收,或者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. /////////////////////////////////////////////////////////////////////以上字串是單片機發(fā)給串口模塊的AT語句有的是直接給WIFI模塊的指令,有些是用來拷貝字符串用/////////////

  92. xdata unsigned char at_send_len_ox[20];               
  93. idata unsigned char send_buf[64]="jisifsfhello:99999;oop";                             //發(fā)送緩沖區(qū)
  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};                                                 //接收緩沖區(qū)
  95. data unsigned char temp_buf[72];                                 //加工緩沖區(qū)
  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個字節(jié)的器件ID號,可在服務器數據庫中查到,唯一標示一個器件,登錄過程需要一個器件ID,和數據區(qū)放一個數據密碼,這么簡單登錄
  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};         //    客戶的凈數據負荷區(qū),可以很大,因為本款單片機有限,并且一般控制信號,定義幾個字節(jié)夠了!注意在登錄的時候,這里是器件密碼!
  100. unsigned char temp_cd[]="TEMP:123;";                                                 //    一個數據包,前面是包格式定義,后面是客戶數據區(qū),這里定義一個即將要發(fā)送的溫度數據
  101. unsigned char need_seed_len=0;                                                                 //    全局變量,本次總共需要發(fā)到串口的數據
  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發(fā)來的請求信息

  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的最后一個扇區(qū)。


  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 端口監(jiān)聽到的 廣播內容 用廣播內容的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. ////制作 向手機發(fā)送如下格式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是發(fā)送的數量
  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,比如發(fā)送38個字節(jié),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. //下面這個函數構造一個發(fā)送的數據格式,請看數據格式文檔,完全可以用結構體完成,這里采用數據,從上到下描述這個數據包
  320. //發(fā)送的數據包,目前只有登錄數據包,和上報溫度數據包,這兩個基本的數據包,上報數據包可以充當心跳包,第一個參數決定著,是發(fā)送登錄包還是溫度包
  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)                                                                                         //根據入口參數判斷是發(fā)送登錄鏈路操作,還是發(fā)送數據包云平臺
  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         //代表本數據包的狀態(tài),是發(fā)送還是應答成功還是失敗

  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個字節(jié)


  346.   for(i=0;i<8;i++)
  347.   send_buf[O_TOKE_START+i]=*(toke_id+i);//8個字節(jié)令牌包,初始令牌包為00 后續(xù)服務器會分配一個令牌包給這個設備,設備每次通訊要攜帶這個令牌包


  348.   for(i=0;i<use_data_len;i++)
  349.   send_buf[O_DATAS_START+i]=*(use_data+i); // 客戶的數據區(qū),登錄的時候放數據密碼文本
  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;        //至此構造出了需要發(fā)送的全部數據 包括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)//發(fā)送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)//發(fā)送數據緩沖區(qū)的非字符串信息,數據流信息到串口
  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)           //開機的時候發(fā)現按鍵1也就是MCU_P1.3 被按下,那么清除單片機中EEPROM存的數據
  498.         {
  499.                 IapEraseSector(IAP_ADDRESS);  //擦除客戶EEPROM扇區(qū) 512字節(jié)
  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;                          //出現指定的字串,并動態(tài)過濾到指定的字符后 置1
  515.         ceng=0;                   //最多 多少字節(jié)內 會出現指定字串,靜態(tài)變量,
  516.         str_len_limt=22;          //設置一個限定參考數值,在這個參考個數內必定出現指定字符串
  517.         str_len_num=13;           //要過濾連續(xù)字符個數
  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);         //發(fā)送進入SMARTLINK AT指令
  525.                 Delay2(2000);
  526.                 }
  527.                 else
  528.                 have_smartlink=1;                                 //否則設置已經進入過SMARTLINK 狀態(tài)

  529.                 do                                                                 //此循環(huán)完成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];                                  //拷貝串口緩沖區(qū)中的用戶路由器名字
  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];                               //拷貝串口緩沖區(qū)中的用戶路由器密碼
  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;                //清空臨時緩沖區(qū)

  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); //此循環(huán)完成SMARTLINK 的配置

  591.                 LED1=1;
  592.                 LED2=1;
  593.                 LED3=1;
  594.             //////////////////////////////////////////////////////////下面的語句獲得模塊的設備ID/////////////////////////////////////////////////////////////
  595.         a_vec=0;                          //出現指定的字串,并動態(tài)過濾到指定的字符后 置1
  596.         ceng=0;                   //最多 多少字節(jié)內 會出現指定字串,靜態(tài)變量,
  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個字節(jié)的字符最總得到四個字節(jié)的16進制數據 比如字符串"A2345678"最終變成0XA2,0X34,0X56,0X78 四個字節(jié)存放
  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進制數據四個字節(jié)存放到對應內存中
  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個字節(jié)的字符最總得到四個字節(jié)的16進制數據 比如字符串"A2345678"最終變成0XA2,0X34,0X56,0X78 四個字節(jié)存放
  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進制數據四個字節(jié)存放到對應內存中
  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個字節(jié)的)換成16進制 存放到內存中,在登錄服務器的時候的兩個必要參數。
  649.                 //////////////////////////////////////////////////////////上面的語句獲得模塊的設備ID和KEY/////////////////////////////////////////////////////////////
  650.                 }
  651.                 //while(1);
  652.                 //////////////////////////////////////////////////////////下面的語句發(fā)送AT指令加入內網,并鏈接到安信可物聯網服務器/////////////////////

  653.                 a_vec=0;                          //出現指定的字串,并動態(tài)過濾到指定的字符后 置1
  654.         ceng=0;                   //最多 多少字節(jié)內 會出現指定字串,靜態(tài)變量,
  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安信可云服務,順便監(jiān)聽 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發(fā)給手機,手機把這個合法ID上報給服務器,從而綁定!
  670.                 {                                                   //過程是手機在和模塊同一個局域網后,手機發(fā)送UDP到2468端口,而上一步,模塊在監(jiān)聽2468端口!手機發(fā)送的UDP包內容是RPL:"192.168.1.10","48008"
  671.                 do                                                   //其實手機是把自己現在的IP地址192.168.1.10 和即將監(jiān)聽的端口48008 告訴模塊,然后模塊就可以把自己的芯片ID 和KEY授權 各四個字節(jié) 回送給手機
  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);        //監(jiān)聽局域網內手機向2468端口(2468端口和連接4綁定) 發(fā)出的UDP掃描信息,獲得RPL:"192.168.1.10","48008"  手機透露自己的IP和端口
  687.                  
  688.                  make_AT_CIP3();                                    //根據上邊 在2468 端口監(jiān)聽到手機透露的IP地址和端口 構造一條建立連接指令如右邊示意:AT+CIPSTART=3,"UDP","192.168.1.10",48008,2469,0
  689.                  at_uart_send_str(temp_buf);         //發(fā)送出上面構造的連接到AT指令,模塊得以執(zhí)行上面構造的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); //發(fā)送AT指令,告訴模塊即將經過路由器發(fā)給手機的數據長度,  code unsigned char CIP3SEND_LEN[]="AT+CIPSEND=3,63";
  693.                  Delay2(1000);
  694.                  at_uart_send_str(temp_buf);         //發(fā)送構造好的UDP數據!
  695.                  Delay2(2000);
  696.                  }                                                                 //根據上面的幾個步驟,手機獲取到了模塊的芯片ID 和 KEY ID,手機得到后會利用這個信息讓服務器綁定它們兩個

  697.                 //////////////////////////////////////////////////////////上面面的語句發(fā)送AT指令加入內網,并鏈接到安信可物聯網服務器/////////////////////
  698.                 at_uart_send_str(AT_MODE);
  699.                 a_vec=0;                          //出現指定的字串,并動態(tài)過濾到指定的字符后 置1
  700.         ceng=0;                   //最多 多少字節(jié)內 會出現指定字串,靜態(tài)變量,
  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發(fā)送的總字節(jié)數變成10進制,動態(tài)生成發(fā)送數據AT指令
  707.                 two_lab=0;                                                                                                ////////////////////////////////////////////////////////////////////兩個55計數!有可能錯亂
  708.         at_uart_send_str(at_send_len_ox);                       //將構造好的AT發(fā)送數據到互聯網的動態(tài)發(fā)送數據長度
  709.                 Delay2(2000);
  710.                 at_uart_send_buf(temp_buf,need_seed_len);                                //經過WIFI模塊發(fā)送構造好的登錄包
  711.                 Delay2(4000);

  712.                 //while(1);

  713.                 while(1)
  714.                 {                                                                                                         //主循環(huán)體中,每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);                                          //動態(tài)構造發(fā)送AT指令
  722.                         at_uart_send_str(at_send_len_ox);                //發(fā)送構造好的發(fā)送指令
  723.                     Delay2(2000);
  724.                     at_uart_send_buf(temp_buf,need_seed_len);             //經過WIFI發(fā)送數據

  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;                          //出現指定的字串,并動態(tài)過濾到指定的字符后 置1
  742. unsigned char ceng=0;         //最多 多少字節(jié)內 會出現指定字串,靜態(tài)變量,
  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)              //根據系統的狀態(tài),決定過濾哪個字符
  785.                  {
  786.                   case uart_rec_tcp_udp_data: //串口進入正常的UDP TCP 數據收發(fā)
  787.                   fit_stb(PIPD_code);                  //過濾數據接收頭
  788.                   break;
  789.                   case  uart_rec_csysid:          //串口進入獲得模塊內部ID 和KEY 狀態(tài)
  790.                   fit_stb(CYSYS_code);              //過濾指定的頭部
  791.                   break;
  792.                   case uart_rec_smartlink:          //串口進入獲得客戶的路由器賬戶密碼狀態(tài)
  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;                //保存一個字節(jié)
  803.                  if(recd_buf[RX1_Cnt]==0X55)    //記錄0X55的個數,出現兩次后,代表一個有數據包結束
  804.                  two_lab++;
  805.                  if(RX1_Cnt<62)        /////////////////////防止64字節(jié)的緩沖區(qū)溢出
  806.                  RX1_Cnt++;
  807.                  else                        ///////每次收到的指令超過64字節(jié),就把數據清空,接收指針指向開頭
  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;                //清除發(fā)送忙標志
  875.         }
  876. }
復制代碼
  1. /*
  2.   注意:變量初始化成0,否者隨機  數組注意溢出問題  0X55 在其他數據中有可能出現,并造成混亂,主要是計數  過濾數據,根據網絡環(huán)境不同,返回有可能變化,注意通用性
  3.   內部 ID KEY 輸出格式已經固定為8個字節(jié)模式
  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;        //發(fā)送計數
  15. u8        RX1_Cnt;        //接收計數
  16. bit        B_TX1_Busy;        //發(fā)送忙標志
  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. /////這是安信可云平臺數據包的全部組成結構,細節(jié)可參照安信可的云平臺V1.0版本規(guī)格書,包結構章節(jié)
  29. #define O_PF    0X00  //包頭1字節(jié)固定0X55
  30. #define O_LEN_L 0X01  //整個包長低字節(jié)
  31. #define O_LEN_H 0X02  //整個包長高字節(jié) 注意轉義碼 兩個這里只計算一個數據處理!
  32. #define O_CMD_T 0X03  //命令類型
  33. #define O_CMD_C 0X04  //具體命令
  34. #define O_CIX_L 0X05  //本命令序列編號低字節(jié)
  35. #define O_CIX_H 0X06  //本命令序列編號高字節(jié)
  36. #define O_EXMSH 0X07  //擴展信息高字節(jié)
  37. #define O_EXMSL 0X08  //擴展信息低字節(jié)
  38. #define O_RESTA 0X09  //數據包狀態(tài)信息,成功 失敗 請求 未知
  39. #define O_DEVID_START 0x0A  //8字節(jié)設備識別  低字節(jié)在前
  40. #define O_DEVID 0x0A  //8字節(jié)設備識別
  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 低字節(jié)
  46. //CRC_H    1BYTE          //CRC16 高字節(jié)
  47. //PACK_END 1BYTE          //包尾1字節(jié)固定0X55

  48. ////////////////////////////////////////////////////////////////////////以上定義了包中的各參數的絕對位置//////////////////////////////////
  49. #define uart_rec_tcp_udp_data 0        //系統進入正常網絡數據收發(fā)狀態(tài)
  50. #define uart_rec_csysid       1        //系統獲取ESP8266WIFI模塊的許可號狀態(tài),獲取四個字節(jié)的芯片ID 和 4個字節(jié)的授權碼
  51. #define uart_rec_smartlink    2        //系統進入獲取上網賬號密碼狀態(tài)
  52. #define uart_rec_bander       3        //系統進入將本WIFI設備 和APP 手機綁定控制狀態(tài)
  53. //////////////////////////////////////////////////////////////////////以上部分定義了系統的幾種狀態(tài)///////////////////////////////////////
  54. bit have_tok=0;
  55. bit have_data=0;
  56. unsigned char rec_len=0;
  57. bit                   a_vec=0;                   //設置一個標志位,串口程序 出現指定的字串,并動態(tài)過濾到指定的字符后 置1
  58. unsigned char          ceng=0;         //最多 多少字節(jié)內 會出現指定字串,靜態(tài)變量,
  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;// 串口目前所處于的狀態(tài),比如進入正常數據接收,或者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. /////////////////////////////////////////////////////////////////////以上字串是單片機發(fā)給串口模塊的AT語句有的是直接給WIFI模塊的指令,有些是用來拷貝字符串用/////////////

  82. xdata unsigned char at_send_len_ox[20];               
  83. idata unsigned char send_buf[64]="jisifsfhello:99999;oop";                             //發(fā)送緩沖區(qū)
  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};                                                 //接收緩沖區(qū)
  85. data unsigned char temp_buf[72];                                 //加工緩沖區(qū)
  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個字節(jié)的器件ID號,可在服務器數據庫中查到,唯一標示一個器件,登錄過程需要一個器件ID,和數據區(qū)放一個數據密碼,這么簡單登錄
  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};         //    客戶的凈數據負荷區(qū),可以很大,因為本款單片機有限,并且一般控制信號,定義幾個字節(jié)夠了!注意在登錄的時候,這里是器件密碼!
  90. unsigned char temp_cd[]="TEMP:123;";                                                 //    一個數據包,前面是包格式定義,后面是客戶數據區(qū),這里定義一個即將要發(fā)送的溫度數據
  91. unsigned char need_seed_len=0;                                                                 //    全局變量,本次總共需要發(fā)到串口的數據
  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發(fā)來的請求信息

  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 端口監(jiān)聽到的 廣播內容 用廣播內容的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. ////制作 向手機發(fā)送如下格式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是發(fā)送的數量
  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,比如發(fā)送38個字節(jié),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. //下面這個函數構造一個發(fā)送的數據格式,請看數據格式文檔,完全可以用結構體完成,這里采用數據,從上到下描述這個數據包
  342. //發(fā)送的數據包,目前只有登錄數據包,和上報溫度數據包,這兩個基本的數據包,上報數據包可以充當心跳包,第一個參數決定著,是發(fā)送登錄包還是溫度包
  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)                                                                                         //根據入口參數判斷是發(fā)送登錄鏈路操作,還是發(fā)送數據包云平臺
  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         //代表本數據包的狀態(tài),是發(fā)送還是應答成功還是失敗

  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個字節(jié)


  368.   for(i=0;i<8;i++)
  369.   send_buf[O_TOKE_START+i]=*(toke_id+i);//8個字節(jié)令牌包,初始令牌包為00 后續(xù)服務器會分配一個令牌包給這個設備,設備每次通訊要攜帶這個令牌包


  370.   for(i=0;i<use_data_len;i++)
  371.   send_buf[O_DATAS_START+i]=*(use_data+i); // 客戶的數據區(qū),登錄的時候放數據密碼文本
  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;        //至此構造出了需要發(fā)送的全部數據 包括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)//發(fā)送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)//發(fā)送數據緩沖區(qū)的非字符串信息,數據流信息到串口
  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;                          //出現指定的字串,并動態(tài)過濾到指定的字符后 置1
  525.         ceng=0;                   //最多 多少字節(jié)內 會出現指定字串,靜態(tài)變量,
  526.         str_len_limt=22;          //設置一個限定參考數值,在這個參考個數內必定出現指定字符串
  527.         str_len_num=13;           //要過濾連續(xù)字符個數
  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);         //發(fā)送進入SMARTLINK AT指令
  533.                                          //PASSWORD:zty0012001       
  534.                 Delay2(2000);
  535.                 do                                                                 //此循環(huán)完成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];                                  //拷貝串口緩沖區(qū)中的用戶路由器名字
  551.                         }
  552.                         for(i=0;recd_buf[ssid_len+11+i]!='\r';i++)
  553.                         {
  554.                                 password[i]=recd_buf[ssid_len+11+i];          //拷貝串口緩沖區(qū)中的用戶路由器密碼
  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;                //清空臨時緩沖區(qū)

  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); //此循環(huán)完成SMARTLINK 的配置

  576.                 LED1=1;
  577.                 LED2=1;
  578.                 LED3=1;
  579.             //////////////////////////////////////////////////////////下面的語句獲得模塊的設備ID/////////////////////////////////////////////////////////////
  580.         a_vec=0;                          //出現指定的字串,并動態(tài)過濾到指定的字符后 置1
  581.         ceng=0;                   //最多 多少字節(jié)內 會出現指定字串,靜態(tài)變量,
  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個字節(jié)的字符最總得到四個字節(jié)的16進制數據 比如字符串"A2345678"最終變成0XA2,0X34,0X56,0X78 四個字節(jié)存放
  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進制數據四個字節(jié)存放到對應內存中
  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個字節(jié)的字符最總得到四個字節(jié)的16進制數據 比如字符串"A2345678"最終變成0XA2,0X34,0X56,0X78 四個字節(jié)存放
  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進制數據四個字節(jié)存放到對應內存中
  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個字節(jié)的)換成16進制 存放到內存中,在登錄服務器的時候的兩個必要參數。
  634.                 //////////////////////////////////////////////////////////上面的語句獲得模塊的設備ID和KEY/////////////////////////////////////////////////////////////
  635.                 }
  636.                 //while(1);
  637.                 //////////////////////////////////////////////////////////下面的語句發(fā)送AT指令加入內網,并鏈接到安信可物聯網服務器/////////////////////

  638.                 a_vec=0;                          //出現指定的字串,并動態(tài)過濾到指定的字符后 置1
  639.         ceng=0;                   //最多 多少字節(jié)內 會出現指定字串,靜態(tài)變量,
  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安信可云服務,順便監(jiān)聽 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);        //監(jiān)聽局域網內手機向2468端口(2468端口和連接4綁定) 發(fā)出的UDP掃描信息,獲得RPL:"192.168.1.10","48008"  手機透露自己的IP和端口
  670.                  
  671.                  make_AT_CIP3();                                   //根據上邊 在2468 端口監(jiān)聽到的 廣播內容 新建一個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();                    //從綁定手機和設備關系的處理中,在串口輸出緩沖區(qū)得到
  675.                  at_uart_send_str(CIP3SEND_LEN);
  676.                  Delay2(1000);
  677.                  at_uart_send_str(temp_buf);
  678.                  Delay2(2000);
  679.                 //////////////////////////////////////////////////////////上面面的語句發(fā)送AT指令加入內網,并鏈接到安信可物聯網服務器/////////////////////
  680.                 at_uart_send_str(AT_MODE);
  681.                 a_vec=0;                          //出現指定的字串,并動態(tài)過濾到指定的字符后 置1
  682.         ceng=0;                   //最多 多少字節(jié)內 會出現指定字串,靜態(tài)變量,
  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發(fā)送的總字節(jié)數變成10進制,動態(tài)生成發(fā)送數據AT指令
  689.                 two_lab=0;                                                                                                ////////////////////////////////////////////////////////////////////兩個55計數!有可能錯亂
  690.         at_uart_send_str(at_send_len_ox);                       //將構造好的AT發(fā)送數據到互聯網的動態(tài)發(fā)送數據長度
  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模塊發(fā)送構造好的登錄包
  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);                                          //動態(tài)構造發(fā)送AT指令
  744.                         at_uart_send_str(at_send_len_ox);                //發(fā)送構造好的發(fā)送指令
  745.                     Delay2(2000);
  746.                     at_uart_send_buf(temp_buf,need_seed_len);             //經過WIFI發(fā)送數據

  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;                          //出現指定的字串,并動態(tài)過濾到指定的字符后 置1
  764. unsigned char ceng=0;         //最多 多少字節(jié)內 會出現指定字串,靜態(tài)變量,
  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)              //根據系統的狀態(tài),決定過濾哪個字符
  807.                  {
  808.                   case uart_rec_tcp_udp_data: //串口進入正常的UDP TCP 數據收發(fā)
  809.                   fit_stb(PIPD_code);                  //過濾數據接收頭
  810.                   break;
  811.                   case  uart_rec_csysid:          //串口進入獲得模塊內部ID 和KEY 狀態(tài)
  812.                   fit_stb(CYSYS_code);              //過濾指定的頭部
  813.                   break;
  814.                   case uart_rec_smartlink:          //串口進入獲得客戶的路由器賬戶密碼狀態(tài)
  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;                //保存一個字節(jié)
  825.                  if(recd_buf[RX1_Cnt]==0X55)    //記錄0X55的個數,出現兩次后,代表一個有數據包結束
  826.                  two_lab++;
  827.                  if(RX1_Cnt<62)        /////////////////////防止64字節(jié)的緩沖區(qū)溢出
  828.                  RX1_Cnt++;
  829.                  else                        ///////每次收到的指令超過64字節(jié),就把數據清空,接收指針指向開頭
  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;                //清除發(fā)送忙標志
  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;        //發(fā)送計數
  11. u8        RX1_Cnt;        //接收計數
  12. bit        B_TX1_Busy;        //發(fā)送忙標志
  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字節(jié)固定0X55
  24. #define O_LEN_L 0X01  //整個包長低字節(jié)
  25. #define O_LEN_H 0X02  //整個包長高字節(jié) 注意轉義碼 兩個這里只計算一個數據處理!
  26. #define O_CMD_T 0X03  //命令類型
  27. #define O_CMD_C 0X04  //具體命令
  28. #define O_CIX_L 0X05  //本命令序列編號低字節(jié)
  29. #define O_CIX_H 0X06  //本命令序列編號高字節(jié)
  30. #define O_EXMSH 0X07  //擴展信息高字節(jié)
  31. #define O_EXMSL 0X08  //擴展信息低字節(jié)
  32. #define O_RESTA 0X09  //數據包狀態(tài)信息,成功 失敗 請求 未知
  33. #define O_DEVID 0x0A  //8字節(jié)設備識別
  34.    //1 BYTS TL_LEN          //獲得的設備臨時通訊令牌長度
  35.    //N BYTS TK                   //TL_LEN個通訊令牌串
  36.    //N BYTS DATAS          //客戶的數據包串
  37.    //CRC_L    1BYTE          //CRC16 低字節(jié)
  38.    //CRC_H    1BYTE          //CRC16 高字節(jié)
  39.    //PACK_END 1BYTE          //包尾1字節(jié)固定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字節(jié)固定0X55
  130. #define O_LEN_L 0X01  //整個包長低字節(jié)
  131. #define O_LEN_H 0X02  //整個包長高字節(jié) 注意轉義碼 兩個這里只計算一個數據處理!
  132. #define O_CMD_T 0X03  //命令類型
  133. #define O_CMD_C 0X04  //具體命令
  134. #define O_CIX_L 0X05  //本命令序列編號低字節(jié)
  135. #define O_CIX_H 0X06  //本命令序列編號高字節(jié)
  136. #define O_EXMSH 0X07  //擴展信息高字節(jié)
  137. #define O_EXMSL 0X08  //擴展信息低字節(jié)
  138. #define O_RESTA 0X09  //數據包狀態(tài)信息,成功 失敗 請求 未知
  139. #define O_DEVID_START 0x0A  //8字節(jié)設備識別  低字節(jié)在前
  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 低字節(jié)
  145.    //CRC_H    1BYTE          //CRC16 高字節(jié)
  146.    //PACK_END 1BYTE          //包尾1字節(jié)固定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); // 數據區(qū),登錄的時候放數據密碼文本

  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);                     //將要發(fā)送的總字節(jié)數變成10進制動態(tài)修改AT發(fā)送指令           at_uart_send_str(at_send_len_ox);
  288.         at_uart_send_str(at_send_len_ox);                //動態(tài)發(fā)送數據長度
  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;                //保存一個字節(jié)
  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;                //清除發(fā)送忙標志
  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;        //發(fā)送計數
  11. u8        RX1_Cnt;        //接收計數
  12. bit        B_TX1_Busy;        //發(fā)送忙標志
  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字節(jié)固定0X55
  25. #define O_LEN_L 0X01  //整個包長低字節(jié)
  26. #define O_LEN_H 0X02  //整個包長高字節(jié) 注意轉義碼 兩個這里只計算一個數據處理!
  27. #define O_CMD_T 0X03  //命令類型
  28. #define O_CMD_C 0X04  //具體命令
  29. #define O_CIX_L 0X05  //本命令序列編號低字節(jié)
  30. #define O_CIX_H 0X06  //本命令序列編號高字節(jié)
  31. #define O_EXMSH 0X07  //擴展信息高字節(jié)
  32. #define O_EXMSL 0X08  //擴展信息低字節(jié)
  33. #define O_RESTA 0X09  //數據包狀態(tài)信息,成功 失敗 請求 未知
  34. #define O_DEVID 0x0A  //8字節(jié)設備識別
  35.    //1 BYTS TL_LEN          //獲得的設備臨時通訊令牌長度
  36.    //N BYTS TK                   //TL_LEN個通訊令牌串
  37.    //N BYTS DATAS          //客戶的數據包串
  38.    //CRC_L    1BYTE          //CRC16 低字節(jié)
  39.    //CRC_H    1BYTE          //CRC16 高字節(jié)
  40.    //PACK_END 1BYTE          //包尾1字節(jié)固定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. //////////////////////////////////////////////////////////////////////以上部分發(fā)送指令讓單片機連入內部網絡////////////////////////////////
  48. code unsigned char CIPSEND_LEN[]="AT+CIPSEND=38";//AT指令發(fā)送數據38字節(jié)的數據到網絡上//////////////////////
  49. unsigned char at_send_len_ox[16];                //上面一條指令只能發(fā)送38的靜態(tài)包長,這里用個RAM存儲上邊CODE的AT指令"AT+CIPSEND=38"可以修改后面的38,為任意數
  50. unsigned char send_buf[64];                             //發(fā)送緩沖區(qū)
  51. unsigned char recd_buf[64];                                                 //接收緩沖區(qū)
  52. data unsigned char temp_buf[64];                                 //加工緩沖區(qū)
  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,比如發(fā)送38個字節(jié),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字節(jié)固定0X55
  134. #define O_LEN_L 0X01  //整個包長低字節(jié)
  135. #define O_LEN_H 0X02  //整個包長高字節(jié) 注意轉義碼 兩個這里只計算一個數據處理!
  136. #define O_CMD_T 0X03  //命令類型
  137. #define O_CMD_C 0X04  //具體命令
  138. #define O_CIX_L 0X05  //本命令序列編號低字節(jié)
  139. #define O_CIX_H 0X06  //本命令序列編號高字節(jié)
  140. #define O_EXMSH 0X07  //擴展信息高字節(jié)
  141. #define O_EXMSL 0X08  //擴展信息低字節(jié)
  142. #define O_RESTA 0X09  //數據包狀態(tài)信息,成功 失敗 請求 未知
  143. #define O_DEVID_START 0x0A  //8字節(jié)設備識別  低字節(jié)在前
  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 低字節(jié)
  149.    //CRC_H    1BYTE          //CRC16 高字節(jié)
  150.    //PACK_END 1BYTE          //包尾1字節(jié)固定0X55

  151. unsigned char esp_dev_id[8]={0,0,0,0,0,0,0X1E,0XE6};         //    8266的8個字節(jié)的器件ID號,可在服務器數據庫中查到,唯一標示一個器件,登錄過程需要一個器件ID,和數據區(qū)放一個數據密碼,這么簡單登錄
  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};         //    客戶的凈數據負荷區(qū),可以很大,因為本款單片機有限,并且一般控制信號,定義幾個字節(jié)夠了!注意在登錄的時候,這里是器件密碼!
  154. unsigned char temp_cd[]="TEMP:123;";                                                 //    一個數據包,前面是包格式定義,后面是客戶數據區(qū),這里定義一個即將要發(fā)送的溫度數據
  155. unsigned char need_seed_len=0;                                                                 //    全局變量,本次總共需要發(fā)到串口的數據


  156. //下面這個函數構造一個發(fā)送的數據格式,請看數據格式文檔,完全可以用結構體完成,這里采用數據,從上到下描述這個數據包
  157. //發(fā)送的數據包,目前只有登錄數據包,和上報溫度數據包,這兩個基本的數據包,上報數據包可以充當心跳包,第一個參數決定著,是發(fā)送登錄包還是溫度包
  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)                                                                                         //根據入口參數判斷是發(fā)送登錄鏈路操作,還是發(fā)送數據包云平臺
  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         //代表本數據包的狀態(tài),是發(fā)送還是應答成功還是失敗

  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個字節(jié)


  183.   for(i=0;i<8;i++)
  184.   send_buf[O_TOKE_START+i]=*(toke_id+i);//8個字節(jié)令牌包,初始令牌包為00 后續(xù)服務器會分配一個令牌包給這個設備,設備每次通訊要攜帶這個令牌包


  185.   for(i=0;i<use_data_len;i++)
  186.   send_buf[O_DATAS_START+i]=*(use_data+i); // 客戶的數據區(qū),登錄的時候放數據密碼文本
  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;        //至此構造出了需要發(fā)送的全部數據 包括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)//發(fā)送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)//發(fā)送數據緩沖區(qū)的非字符串信息,數據流信息到串口
  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.         {        //////////////////////////////////////////////////////////下面的語句發(fā)送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.                 //////////////////////////////////////////////////////////上面面的語句發(fā)送AT指令加入內網,并鏈接到安信可物聯網服務器/////////////////////
  312.                 make_send_pack(0,esp_dev_id,esp_TOK_id,esp_user_data,8);//構造登錄數據包
  313.                 make_AT_SEND(need_seed_len);                            //將要進過WIFI發(fā)送的總字節(jié)數變成10進制,動態(tài)生成發(fā)送數據AT指令
  314.         at_uart_send_str(at_send_len_ox);                       //將構造好的AT發(fā)送數據到互聯網的動態(tài)發(fā)送數據長度
  315.                 Delay2(2000);
  316.                 at_uart_send_buf(temp_buf,need_seed_len);                                //經過WIFI模塊發(fā)送構造好的登錄包
  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);                                          //動態(tài)構造發(fā)送AT指令
  326.                         at_uart_send_str(at_send_len_ox);                //發(fā)送構造好的發(fā)送指令
  327.                     Delay2(2000);
  328.                     at_uart_send_buf(temp_buf,need_seed_len);             //經過WIFI發(fā)送數據

  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;                //保存一個字節(jié)
  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];             //////////////郁悶的是模塊是令牌包,是登錄服務器的時候,只發(fā)送一次! 這個時候串口處于未知狀態(tài),因此經常把第一個包丟了
  373.                           toke[6]=recd_buf[20];                 //////////////串口接收到的第一個數據包就是服務器回復的令牌包,本單片機第一恰好丟掉,但是一旦登錄上服務器,只要手機發(fā)
  374.                           toke[5]=recd_buf[21];                 //////////////一個控制開關指令到模塊,在這個指令的固定位置,比如19位置處,放的就是可能丟的令牌包!
  375.                           toke[4]=recd_buf[22];                 //////////////保留好這個令牌包,以后模塊發(fā)送到云平臺的數據,到要用到這個令牌包
  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;                //清除發(fā)送忙標志
  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位和當前字節(jié)相加后再查表求的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 很給力!

查看全部評分

回復

使用道具 舉報

ID:71423 發(fā)表于 2016-4-10 21:46 | 顯示全部樓層
非常感謝樓主分享
回復

使用道具 舉報

ID:114158 發(fā)表于 2016-4-14 11:42 | 顯示全部樓層
感謝樓主分享
回復

使用道具 舉報

ID:126573 發(fā)表于 2016-6-23 11:21 | 顯示全部樓層
謝謝樓主分享,學習學習。。。。。
回復

使用道具 舉報

ID:129989 發(fā)表于 2016-7-11 11:17 | 顯示全部樓層
樓主好棒
回復

使用道具 舉報

ID:129989 發(fā)表于 2016-7-11 11:20 | 顯示全部樓層
用什么軟件打開呢
回復

使用道具 舉報

ID:79544 發(fā)表于 2016-7-11 19:41 | 顯示全部樓層
很好的資料謝謝分享。
回復

使用道具 舉報

ID:79544 發(fā)表于 2016-7-11 19:42 | 顯示全部樓層
樓主你好:手機AAP在哪里下載,謝謝請指教!
回復

使用道具 舉報

ID:79544 發(fā)表于 2016-7-11 19:43 | 顯示全部樓層

kiluv4
回復

使用道具 舉報

ID:102293 發(fā)表于 2016-7-11 22:33 | 顯示全部樓層
學習學習,非常感謝樓主分享
回復

使用道具 舉報

ID:129868 發(fā)表于 2016-7-12 10:36 | 顯示全部樓層
來學習學習
回復

使用道具 舉報

ID:130791 發(fā)表于 2016-7-17 13:49 | 顯示全部樓層
過來學習。!
回復

使用道具 舉報

ID:134757 發(fā)表于 2016-7-23 21:20 | 顯示全部樓層

學習學習,非常感謝樓主分享
回復

使用道具 舉報

ID:136422 發(fā)表于 2016-8-10 12:54 | 顯示全部樓層
學習一下
回復

使用道具 舉報

ID:136422 發(fā)表于 2016-8-10 12:55 | 顯示全部樓層
學習學習,非常感謝樓主分享
回復

使用道具 舉報

ID:137635 發(fā)表于 2016-8-26 09:42 | 顯示全部樓層
先收藏了,謝謝樓主
回復

使用道具 舉報

ID:128463 發(fā)表于 2016-8-29 17:40 | 顯示全部樓層
很好的資料謝謝分享!!!!
回復

使用道具 舉報

ID:138902 發(fā)表于 2016-9-8 23:51 | 顯示全部樓層
謝謝分享。!
回復

使用道具 舉報

ID:121470 發(fā)表于 2016-9-28 14:17 | 顯示全部樓層
看得不是很多,學習一下
回復

使用道具 舉報

ID:149037 發(fā)表于 2016-12-17 14:37 | 顯示全部樓層

學習學習,非常感謝樓主分享
回復

使用道具 舉報

ID:75062 發(fā)表于 2017-1-3 22:24 | 顯示全部樓層
謝謝樓主分享
回復

使用道具 舉報

ID:162349 發(fā)表于 2017-1-18 21:34 | 顯示全部樓層
感謝樓主
回復

使用道具 舉報

ID:166195 發(fā)表于 2017-2-23 15:45 | 顯示全部樓層
已收藏,非常感謝樓主,學習中
回復

使用道具 舉報

ID:166347 發(fā)表于 2017-2-24 10:24 | 顯示全部樓層
 非常感謝樓主分享
回復

使用道具 舉報

ID:169508 發(fā)表于 2017-3-9 21:57 | 顯示全部樓層
其實我想知道發(fā)送原理是什么,既然PC可以通過串口向單片機發(fā)送信息,能否直接改為由單片機先模塊發(fā)送信息,不過失敗了,實在弄不清原理
回復

使用道具 舉報

ID:47286 發(fā)表于 2017-3-10 14:13 | 顯示全部樓層
感謝樓主分享 學習了
回復

使用道具 舉報

ID:166895 發(fā)表于 2017-3-27 20:49 | 顯示全部樓層
感謝樓主分享
回復

使用道具 舉報

ID:185256 發(fā)表于 2017-4-13 01:13 | 顯示全部樓層
能直接移植到 STM8 上面嗎? 怎么做呢?
回復

使用道具 舉報

ID:185256 發(fā)表于 2017-4-13 16:54 | 顯示全部樓層
很好的資料謝謝分享!!!!
回復

使用道具 舉報

ID:186249 發(fā)表于 2017-4-14 15:22 | 顯示全部樓層
這個不錯,我看看
回復

使用道具 舉報

ID:110687 發(fā)表于 2017-4-24 13:03 | 顯示全部樓層
謝謝摟住,謝謝你的共享!在學習中。。。。。。
回復

使用道具 舉報

ID:196946 發(fā)表于 2017-5-5 15:19 | 顯示全部樓層
感謝分享
回復

使用道具 舉報

ID:25518 發(fā)表于 2017-5-29 15:12 | 顯示全部樓層
真心感謝分享。
回復

使用道具 舉報

ID:209407 發(fā)表于 2017-6-9 02:31 | 顯示全部樓層
這個看看,謝謝分享
回復

使用道具 舉報

ID:104683 發(fā)表于 2017-6-10 19:42 | 顯示全部樓層
正好學到 謝謝分享
回復

使用道具 舉報

ID:211931 發(fā)表于 2017-6-16 18:46 | 顯示全部樓層
非常感謝樓主的分享
回復

使用道具 舉報

ID:215781 發(fā)表于 2017-6-29 12:59 | 顯示全部樓層
很棒,學習了
回復

使用道具 舉報

ID:218517 發(fā)表于 2017-7-10 15:13 | 顯示全部樓層
感謝樓主的分享!
回復

使用道具 舉報

ID:227029 發(fā)表于 2017-8-11 17:36 | 顯示全部樓層
很給力qqdqdq
回復

使用道具 舉報

ID:210861 發(fā)表于 2017-9-6 15:11 | 顯示全部樓層
謝謝樓主的無私分享!
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表