作者:xyy840948307 | 更新時間:2016-08-02 | 瀏覽量:4305
#include "common.h" #include "HC74HC.h" #include "24cxx.h" /////////////////////////////////////////////////////////////////////////////////////////////////////////// //本程序只供學習使用,未經作者許可,不得用于其它任何用途 //ALIENTEK STM32開發板 //ATK-ESP8266 WIFI模塊 公用驅動代碼 //正點原子@ALIENTEK //技術論壇:www.openedv.com //修改日期:2014/4/3 //版本:V1.0 //版權所有,盜版必究。 //Copyright(C) 廣州市星翼電子科技有限公司 2009-2019 //All rights reserved /////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////// //用戶配置區 const u8* reply0="無法識別的指令"; const u8* reply1="屏幕已開"; const u8* reply2="屏幕已關"; const u8* reply3="燈已打開"; const u8* reply4="燈已關閉"; const u8* reply9="燈已打開10s"; const u8* reply10="蜂鳴器開啟1s"; //用戶配置區 //const u8* esp8266_="{\"M\":\"say\",\"ID\":\"U397\",\"C\":\"LED OK\\u6536\\u5230\\u6570\\u636e\",\"SIGN\":\"123\"}";//路由器SSID號 const u8* esp8266_="{\"M\":\"say\",\"ID\":\"U397\",\"C\":\"LED OK收到數據\",\"SIGN\":\"123\"}";//路由器SSID號 //連接端口號:8086,可自行修改為其他端口.apiKey _ESP8266 ESP8266; //連接端口號:8086,可自行修改為其他端口.apiKey const u8* portnum="8086"; //bigiod_ip和端口 const u8* bigiod_ip="www.eqytg.org";//路由器SSID號device const u8* bigiod_portnum="8181";//wpa/wpa2 aes加密方式 //bigiod登錄指令 const u8* bigiod_ID="398";//wpa/wpa2 aes加密方式 const u8* bigiod_apiKey="d12a86c9d";//wpa/wpa2 aes加密方式 //WIFI STA模式,設置要去連接的路由器無線參數,請根據你自己的路由器設置,自行修改. const u8* wifista_ssid="cengnimabi";//路由器SSID號 const u8* wifista_encryption="wpawpa2_aes";//wpa/wpa2 aes加密方式 const u8* wifista_password="Jang@Luo?515@Zhou"; //連接密碼 //WIFI AP模式,模塊對外的無線參數,可自行修改. const u8* wifiap_ssid="XYY-ESP8266";//對外SSID號 const u8* wifiap_encryption="wpawpa2_aes";//wpa/wpa2 aes加密方式 const u8* wifiap_password="12345678"; //連接密碼 /////////////////////////////////////////////////////////////////////////////////////////////////////////// //4個網絡模式 const u8 *ATK_ESP8266_CWMODE_TBL[3]={"STA模式 ","AP模式 ","AP&STA模式 "};//ATK-ESP8266,3種網絡模式,默認為路由器(ROUTER)模式 //4種工作模式 const u8 *ATK_ESP8266_WORKMODE_TBL[3]={"TCP服務器","TCP客戶端"," UDP 模式"};//ATK-ESP8266,4種工作模式 //5種加密方式 const u8 *ATK_ESP8266_ECN_TBL[5]={"OPEN","WEP","WPA_PSK","WPA2_PSK","WPA_WAP2_PSK"}; /////////////////////////////////////////////////////////////////////////////////////////////////////////// //usmart支持部分 //將收到的AT指令應答數據返回給電腦串口 //mode:0,不清零USART2_RX_STA; // 1,清零USART2_RX_STA; void atk_8266_at_response(u8 mode) { if(USART2_RX_STA&0X8000)//接收到一次數據了 { USART2_RX_BUF[USART2_RX_STA&0X7FFF]=0;//添加結束符 printf("%s\r\n\r\n",USART2_RX_BUF);//發送到串口 if(mode)USART2_RX_STA=0; } } //ATK-ESP8266?????? //???:0,????; // 1,???? u8 atk_8266_quit_trans(void) { while((USART2->SR&0X40)==0);//????? USART2->DR='+'; delay_ms(15);//????????(10ms) while((USART2->SR&0X40)==0);//????? USART2->DR='+'; delay_ms(15);//????????(10ms) while((USART2->SR&0X40)==0);//????? USART2->DR='+'; delay_ms(500);//??500ms return atk_8266_send_cmd("AT","OK",20);//??????. } //ATK-ESP8266發送命令后,檢測接收到的應答 //str:期待的應答結果 //返回值:0,沒有得到期待的應答結果 // 其他,期待應答結果的位置(str的位置) u8* atk_8266_check_cmd(u8 *str) { char *strx=0; if(USART2_RX_STA&0X8000)//接收到一次數據了 { USART2_RX_BUF[USART2_RX_STA&0X7FFF]=0;//添加結束符 strx=strstr((const char*)USART2_RX_BUF,(const char*)str); } return (u8*)strx; } //向ATK-ESP8266發送命令 //cmd:發送的命令字符串 //ack:期待的應答結果,如果為空,則表示不需要等待應答 //waittime:等待時間(單位:10ms) //返回值:0,發送成功(得到了期待的應答結果) // 1,發送失敗 u8 atk_8266_send_cmd(u8 *cmd,u8 *ack,u16 waittime) { u8 res=0; USART2_RX_STA=0; u2_printf("%s\r\n",cmd);//發送命令 if(ack&&waittime)//需要等待應答 { while(--waittime)//等待倒計時 { delay_ms(10); if(USART2_RX_STA&0X8000)//接收到期待的應答結果 { if(atk_8266_check_cmd(ack)) { //printf("ack:%s\r\n",(u8*)ack); break;//得到有效數據 } USART2_RX_STA=0; } } if(waittime==0)res=1; } return res; } //向ATK-ESP8266發送指定數據 //data:發送的數據(不需要添加回車了) //ack:期待的應答結果,如果為空,則表示不需要等待應答 //waittime:等待時間(單位:10ms) //返回值:0,發送成功(得到了期待的應答結果)luojian u8 atk_8266_send_data(u8 *data,u8 *ack,u16 waittime) { u8 res=0; USART2_RX_STA=0; u2_printf("%s",data);//發送命令 if(ack&&waittime)//需要等待應答 { while(--waittime)//等待倒計時 { delay_ms(10); if(USART2_RX_STA&0X8000)//接收到期待的應答結果 { if(atk_8266_check_cmd(ack))break;//得到有效數據 USART2_RX_STA=0; } } if(waittime==0)res=1; } return res; } ////wifi帳號密碼設置 u8 ESP8266_init(void) { u8 *p,*wifi_ssid,*wifi_password; u8 k=0; wifi_ssid=mymalloc(SRAMIN,50);//申請32字節內存 wifi_password=mymalloc(SRAMIN,50);//申請32字節內存 AT24CXX_Read(400,wifi_ssid,50); AT24CXX_Read(450,wifi_password,50); LCD_ShowString(5,285,240,16,16,wifi_ssid,0); LCD_ShowString(5,305,240,16,16,wifi_password,0); //ESP8266.wifista_ssid=(u8* )wifista_ssid, ESP8266.wifista_password=(u8* )wifista_password; ESP8266.wifista_ssid=(u8* )wifi_ssid; ESP8266.wifista_password=(u8* )wifi_password; while(atk_8266_send_cmd("AT","OK",20))//檢查WIFI模塊是否在線 { atk_8266_quit_trans();//退出透傳 atk_8266_send_cmd("AT+CIPMODE=0","OK",200); //關閉透傳模式 delay_ms(10); } while(atk_8266_send_cmd("ATE0","OK",20));//關閉回顯 p=mymalloc(SRAMIN,64);//申請32字節內存 atk_8266_send_cmd("AT+CWMODE=1","OK",50);//設置WIFI STA模式 atk_8266_send_cmd("AT+RST","OK",20);//DHCP服務器關閉(僅AP模式有效) delay_ms(3000); //延時3S等待重啟成功 printf("正在獲取IP\r\n"); sprintf((char*)p,"AT+CWJAP=\"%s\",\"%s\"",ESP8266.wifista_ssid,ESP8266.wifista_password);//設置無線參數:ssid,密碼 if(atk_8266_send_cmd(p,"WIFI CONNECTED",500)==0)goto AA25;//連接目標路由器,并且獲得IP// if(atk_8266_send_cmd(p,"WIFI GOT IP",500)==0) goto AA25;//連接目標路由器,并且獲得IP// k=1, printf("獲取IP失敗\r\n"); goto AA24; AA25://WIFI獲得IP printf("獲取IP成功\r\n"); delay_ms(1000); atk_8266_send_cmd("AT+CIPMUX=0","OK",200); //0:單連接,1:多連接 printf("正在連接!\r\n"); sprintf((char*)p,"AT+CIPSTART=\"TCP\",\"%s\",%s",(u8*)bigiod_ip,(u8*)bigiod_portnum); //配置目標TCP服務器 if(atk_8266_send_cmd(p,"WELCOME TO BIGIOT",200)==0) goto AA26; //得到有效數據 if(atk_8266_send_cmd(p,"ALREADY CONNECTED",200)==0) goto AA26; //得到有效數據 k=1; printf("連接失敗!\r\n"); goto AA24;//連接失敗跳轉到末尾 AA26: printf("連接成功!\r\n"); atk_8266_send_cmd("AT+CIPMODE=1","OK",20); //傳輸模式為:透傳 atk_8266_send_cmd("AT+CIPSEND",">",20); //開始透傳 delay_ms(500); k=ESP8266_login(); AA24: myfree(SRAMIN,wifi_password); //釋放32字節內存 myfree(SRAMIN,wifi_ssid); //釋放32字節內存 myfree(SRAMIN,p); //釋放32字節內存 if(k==0) ESP8266.DISCONNECT_T=0; return k ; } //ATK-ESP8266初始化函數 u8 ESP8266_connect(void) { u8 *ser; u8 k; while(atk_8266_send_cmd("AT","OK",20))//檢查WIFI模塊是否在線 { atk_8266_quit_trans();//退出透傳 delay_ms(10); } ser=mymalloc(SRAMIN,64); //申請32字節內存 atk_8266_send_cmd("AT+CWMODE=1","OK",50);//設置WIFI STA模式 atk_8266_send_cmd("AT+RST","OK",20); //DHCP服務器關閉(僅AP模式有效) delay_ms(5000); //延時3S等待重啟成功 k=1,printf("正在連接!!!\r\n"); sprintf((char*)ser,"AT+CIPSTART=\"TCP\",\"%s\",%s",(u8*)bigiod_ip,(u8*)bigiod_portnum); //配置目標TCP服務器 if(atk_8266_send_cmd(ser,"CONNECT",200)==0) goto AA22; //得到有效數據 if(atk_8266_send_cmd(ser,"ALREADY CONNECTED",200)==0) goto AA22; //得到有效數據 if(atk_8266_send_cmd(ser,"WELCOME TO BIGIOT",200)==0) goto AA22; //得到有效數據 if(atk_8266_send_cmd(ser,"no ip",100)==0) ESP8266.enforce=5,k=2; //無IP需要立即進行初始化操作,強制初始化 printf("連接失敗!!!\r\n"); goto AA21;//連接失敗跳轉到末尾 AA22: k=0,printf("連接成功!!!\r\n"); atk_8266_send_cmd("AT+CIPMODE=1","OK",20); //傳輸模式為:透傳 atk_8266_send_cmd("AT+CIPSEND",">",20); //開始透傳 delay_ms(500); k=ESP8266_login(); //登錄 AA21: myfree(SRAMIN,ser); //釋放32字節內存connected if(k==0) ESP8266.DISCONNECT_T=0; return k ; } //登錄貝殼服務器函數 u8 ESP8266_login(void) { u8 *p,*str; u8 k=0,n; p=mymalloc(SRAMIN,64); //申請32字節內存 str=mymalloc(SRAMIN,32); //申請32字節內存 sprintf((char*)p,"{\"M\":\"checkin\",\"ID\":\"%s\",\"K\":\"%s\"}",bigiod_ID,(u8*)bigiod_apiKey);//登錄指令 sprintf((char*)str,"\"ID\":\"D%s\"",bigiod_ID);//登錄指令 AA27: n=12; printf("登錄\r\n"); while(n) { if(atk_8266_send_cmd(p,str,200)==0) break; n--; } if(n==0) { k=1,printf("登錄失敗???\r\n"); if(ESP8266_check("connected")==0) goto AA27; } else k=0,printf("登錄成功!!!\r\n"); myfree(SRAMIN,str); //釋放32字節內存connected myfree(SRAMIN,p); //釋放32字節內存connected if(k==0) ESP8266.DISCONNECT_T=0; return k ; } //ATK-ESP8266初始化函數 void SetWifi_IdPass(u8 *wifiId,u8 *Pass) { u8 *wifitemp; u8 n=0; wifitemp=wifiId; while(*wifitemp) { n++; wifitemp++; if(n>=49) { *wifitemp=0; //超過最大計數強制添加結束符號 break; } } AT24CXX_Write(400,wifiId,n+1); //結束符號同時存入AT24,方便讀取結束符號 n=0; wifitemp=Pass; while(*wifitemp) { n++; wifitemp++; if(n>=49) { *wifitemp=0; //超過最大計數強制添加結束符號 break; } } AT24CXX_Write(450,Pass,n+1); //結束符號同時存入AT24,方便讀取結束符號 ESP8266.enforce=5; //強制ESP8266進行初始化 } //ATK-ESP8266初始化函數 u8 ESP8266_check(u8* str) { u8 k; k=atk_8266_send_cmd("{\"M\":\"status\"}",(u8*)str,200);//檢測心跳 return k ; } //ESP8266檢查保持在線函數,單位S,內部已經延時45s,未登錄內部循環10s。 void ESP8266_hold(void) { u8 k; AA18: ESP8266.status=8;//默認有心跳 k=ESP8266_check("checked");//檢測心跳 if(k==0) ESP8266.DISCONNECT_T=0; //有心跳 if((k!=0)&&(ESP8266.DISCONNECT_T==0)) { ESP8266.DISCONNECT_T++; //無心跳計時 ESP8266.DISCONNECT_C++; //掉線次數+1 } if(ESP8266.DISCONNECT_T>60) ESP8266.status=7;//無心跳需要重新登錄 if(ESP8266.DISCONNECT_T>300) ESP8266.status=6;//無心跳需要重新連接 if(ESP8266.DISCONNECT_T>600) ESP8266.status=5;//無心跳需要重新初始化 if(ESP8266.enforce) ESP8266.status=ESP8266.enforce;//強制選項條件 if(ESP8266.enforce) ESP8266.DISCONNECT_T++; //無心跳計時 if(ESP8266.enforce) ESP8266.enforce=0;//強制選項條件清空 //選擇操作內容 switch(ESP8266.status) { case 5: while(ESP8266_init()) { delay_ms(30000); if(ESP8266_check("checked")==0) goto AA18 ;//檢測心跳 delay_ms(30000); } goto AA18 ; case 6: ESP8266_connect();// 超過300s重新連接服務器 delay_ms(10000); goto AA18 ; case 7: if(ESP8266_login()==0) ESP8266.status=8;//檢查不在線,重新登錄deng delay_ms(5000); break; case 8: delay_ms(45000); break; default: break; } if(ESP8266.status!=8) { delay_ms(3000); goto AA18 ; } } //ESP8266接收數據后, //str:期待的應答結果 //返回值:0,返回相應的結果 // 其他,期待應答結果的位置(str的位置) u16 ESP8266_search(void) { u8 res=0,strN; u8 *p,*p2,*strA,*strB,*reply; p=mymalloc(SRAMIN,100); //申請100字節內存 p2=mymalloc(SRAMIN,100); //申請100字節內存 if(USART2_RX_STA&0X8000)//接收到期待的應答結果 { //判斷指令類型 if(atk_8266_check_cmd("\"M\":\"login\"")) res=login; //檢查上線 if(atk_8266_check_cmd("\"M\":\"logout\"")) res=logout; //檢查下線 if(atk_8266_check_cmd("\"M\":\"say\"")) res=say; //檢查對話 //跳轉類型操作 switch(res) { case login: res=0; if(atk_8266_check_cmd("\"xyy840948307(web)\"")) ESP8266.xyy_web_login=1; //檢查上線 if(atk_8266_check_cmd("\"xyy840948307(wx)\"")) ESP8266.xyy_wx_login=1; //檢查上線 if(atk_8266_check_cmd("\"guest\"")) ESP8266.guest_login=1; //檢查上線 break; case logout: res=0; if(atk_8266_check_cmd("\"xyy840948307(web)\"")) ESP8266.xyy_web_logout=1; //檢查下線 if(atk_8266_check_cmd("\"xyy840948307(wx)\"")) ESP8266.xyy_wx_logout=1; //檢查下線 if(atk_8266_check_cmd("\"guest\"")) ESP8266.guest_logout=1; //檢查下線 break; case say: res=0; if(atk_8266_check_cmd("\"xyy840948307(wx)\"")) res=xyy840948307wx;//檢查下線 if(atk_8266_check_cmd("\"xyy840948307(web)\"")) res=xyy840948307web; //檢查下線 if(atk_8266_check_cmd("\"guest\"")) res=guest; //檢查下線 res=1; //強制 goto AA10; default: res=0; break; } goto AA20; //無命令,跳轉到文末 AA10://say對話操作 reply=(u8*)reply0; switch(res) { case xyy840948307wx://微信對話,命令字符在“C” 和“T” 之間 res=0; strA=atk_8266_check_cmd("\"C\"")+5 ; //檢查命令字符第一個字符位置, 向右偏移5個字節 strB=atk_8266_check_cmd("\"T\"")-3 ; //檢查命令字符最后一個個字符位置, 向左偏移3個字節 strN=strB-strA+1; //加1是防止最后一個字符丟失 memcpy(p,strA,strN); //復制字符串 p[strN]=0; //添加結束符 order2str(p); printf("%s\r\n",(u8*) p);//發送到串口 "\u52a0\u6cb9" strN=0; if(strstr((const char*)p,(const char*)"開燈")) strN=1; if(strstr((const char*)p,(const char*)"開燈1")) strN=1; if(strstr((const char*)p,(const char*)"繼電器開")) strN=1; if(strN) K0.DO=1,reply=(u8*)reply3; strN=0; if(strstr((const char*)p,(const char*)"關燈")) strN=1; if(strstr((const char*)p,(const char*)"關燈1")) strN=1; if(strstr((const char*)p,(const char*)"繼電器關")) strN=1; if(strN) K0.DO=0,reply=(u8*)reply4; strN=0; if(strstr((const char*)p,(const char*)"屏幕開")) strN=1; if(strstr((const char*)p,(const char*)"up")) strN=1; if(strN) LCD_ON,LCD_ONT=30000,reply=(u8*)reply1; strN=0; if(strstr((const char*)p,(const char*)"屏幕關")) strN=1; if(strstr((const char*)p,(const char*)"down")) strN=1; if(strN) LCD_OFF,reply=(u8*)reply2; strN=0; if(strstr((const char*)p,(const char*)"喇叭")) strN=1; if(strstr((const char*)p,(const char*)"蜂鳴器")) strN=1; if(strstr((const char*)p,(const char*)"報警")) strN=1; if(strN) Beep_T=2000 ,reply=(u8*)reply10; if(strstr((const char*)p,(const char*)"offOn")) K0.DO=!K0.DO, K0.TN=10000 ,reply=(u8*)reply9; if(strstr((const char*)p,(const char*)"play")) Beep_T=1000 ,reply=(u8*)reply10; sprintf((char*)p2,"{\"M\":\"say\",\"ID\":\"U397\",\"C\":\"%s\",\"SIGN\":\"123\"}",(char*)reply); str2order(p2); atk_8266_send_cmd((u8*)p2,0,0); break; case xyy840948307web://web對話 res=0; break; case guest://guest對話 R?? res=0; break; default: res=0; break; } AA20: USART2_RX_STA=0; } myfree(SRAMIN,p); //釋放100字節內存 myfree(SRAMIN,p2); //釋放100字節內存 return 0; } void order2str(u8* str) { u16 j=0,n=0,res; while(str[j]) //判斷索檢到末尾 { if((str[j]=='\\')&&(str[j+1]=='u')) { if(str[j+2]<58) str[j+2]-=48; else str[j+2]-=87; if(str[j+3]<58) str[j+3]-=48; else str[j+3]-=87; if(str[j+4]<58) str[j+4]-=48; else str[j+4]-=87; if(str[j+5]<58) str[j+5]-=48; else str[j+5]-=87; str[n]=str[j+2]*16+str[j+3]; str[n+1]=str[j+4]*16+str[j+5]; res=(str[n]*256)+str[n+1]; //編碼求和 res=ff_convert(res,0); /* Converted code, 0 means conversion error */ if(res<0x0100) res=0x3f3f; //漢字編碼不能小于這個數 str[n]=res>>8,str[n+1]=res; //編碼分解 n+=2,j+=6; }else { str[n]=str[j]; n++,j++; } } str[n]=0; //索檢到末尾,添加結束符 } //p; j{"M":"say","ID":"U397","C":"LED OK收到數據","SIGN":"123"} //str;n{"M":"say","ID":"U397","C":"LED OK\u6536\u5230\u6570\u636e","SIGN":"123"} void str2order(u8* str) { u16 j=0,n=0,res; u8 *p; p=mymalloc(SRAMIN,100); //申請100字節內存 strcpy((char*)p,(char*)str); while(p[j]) //判斷索檢到末尾 { if((p[j]&0x80)>0) { str[n]='\\'; str[n+1]='u'; n+=2; res=(p[j]*256)+p[j+1]; res=ff_convert(res,1); /* Converted code, 0 means conversion error */ p[j]=res>>8,p[j+1]=res; str[n]=p[j]>>4,str[n+1]=p[j]&0x0f; str[n+2]=p[j+1]>>4,str[n+3]=p[j+1]&0x0f; if(str[n]<10) str[n]+=48; else str[n]+=87; if(str[n+1]<10) str[n+1]+=48; else str[n+1]+=87; if(str[n+2]<10) str[n+2]+=48; else str[n+2]+=87; if(str[n+3]<10) str[n+3]+=48; else str[n+3]+=87; n+=4,j+=2; }else { str[n]=p[j]; n++,j++; } } str[n]=0; //索檢到末尾,添加結束符 myfree(SRAMIN,p); //釋放100字節內存 } //UCOS2主程序調用任務//ESP8266 void ESP8266_hold_task(void *pdata) { u8 *p; u8 n=0; ESP8266.DISCONNECT_T=1; //開機認為已經失聯,設置超時狀態強制重連,需要讓其連接但不需要初始化。 if(ESP8266_check("checked")==0) { ESP8266.DISCONNECT_T=0; goto AA16; } while(ESP8266_connect()) //開機連接一次 { n++; //延時 if(n>=3) break; } AA16: delay_ms(12000); //查詢不得小于10秒 while(1) { ESP8266_hold(); //內部集成延時45s,保持在線 p=mymalloc(SRAMIN,40); //申請32字節內存 Get_Temprate(); sprintf((char*)p,"{\"M\":\"update\",\"ID\":\"393\",\"V\":{\"400\":\"%.2f\",\"401\":\"223\"}}",chip_Temprate);//登錄指令(float)chip_Temprate atk_8266_send_cmd(p,0,0); myfree(SRAMIN,p); //內存釋放(外部調用) } } //ESP8266//獲取微信或者貝殼APP發送的控制命令 void ESP8266_task(void *pdata) { while(1) { ESP8266_search(); delay_ms(100); } }
工程文件: STM32F4跑ucosii ,配合AT指令保持在線并控制設備。.7z
(用Keil 5打開)