编写时间:2018年9月2日
#define ATCMDLEN 20
extern uint8_t usart3RecvEndFlag;
extern UART_HandleTypeDef huart3;
extern uint16_t dmaUsart3RxLen;
extern uint8_t dmaUsart3RxBuf[DATA_BUFFER_SIZE];
uint8_t wifi_config = 0;
typedef enum dataType
{
WIFI_AT, //检测wifi模组是否在线
WIFI_CWMODE_DEF, //配置WIFI模组为Station模式并保存到flash
WIFI_RST, //重启WIFI模块
WIFI_CWAUTOCONN, //使能上电自动连接AP(路由)
WIFI_CWSTARTSMART, //CWSTARTSMART
WIFI_CWSTOPSMART, //释放内存
WIFI_CIPSTATUS_TWO, //查询网络连接状态,STATUS:2,获得 IP
WIFI_CIPSTATUS_THREE, //查询网络连接状态,已连接
WIFI_CIPSTATUS_FOUR, //查询网络连接状态,断开连接
WIFI_CIPSTATUS_FIVE, //查询网络连接状态,未连接到 WiFi
WIFI_CWJAP_DEF, //查看wifi信号强度
WIFI_CIPMUX, //开启多连接
WIFI_CIPSTART_ZERO, //创建0号路由器AP
WIFI_CIPSTART_ONE, //连接1号路由器AP
WIFI_CIPSTART_TWO, //连接2号路由器AP
WIFI_CIPSTART_THREE, //连接3号路由器AP
WIFI_CIPCLOSE_ZERO, //关闭esp8266模组与0号服务器的连接
WIFI_CIPCLOSE_ONE, //关闭esp8266模组与1号服务器的连接
WIFI_CIPCLOSE_TWO, //关闭esp8266模组与2号服务器的连接
WIFI_CIPCLOSE_THREE //关闭esp8266模组与3号服务器的连接
}dataCmd; //此处的dataCmd为枚举型enum dataType的别名
typedef struct WIFICONFIGCMD
{
uint8_t* wifiCmd; //wifi模组AT指令
uint8_t cmdLen; //wifi模组AT指令数据长度
uint8_t* wifiAsk; //wifi模组应答
}wifiCmdType;
wifiCmdType wificmd[ATCMDLEN]={
{(uint8_t*)"AT\r\n",DATALEN("AT\r\n")-1,(uint8_t*)"OK"}, //0
{(uint8_t*)"AT+CWMODE_DEF=1\r\n",DATALEN("AT+CWMODE_DEF=1\r\n")-1,(uint8_t*)"OK"}, //1
{(uint8_t*)"AT+RST\r\n",DATALEN("AT+RST\r\n")-1,(uint8_t*)"OK"}, //2
{(uint8_t*)"AT+CWAUTOCONN=1\r\n",DATALEN("AT+CWAUTOCONN=1\r\n")-1,(uint8_t*)"OK"}, //3
{(uint8_t*)"AT+CWSTARTSMART\r\n",DATALEN("AT+CWSTARTSMART\r\n")-1,(uint8_t*)"OK"}, //4
{(uint8_t*)"AT+CWSTOPSMART\r\n",DATALEN("AT+CWSTOPSMART\r\n")-1,(uint8_t*)"OK"}, //5
{(uint8_t*)"AT+CIPSTATUS\r\n",DATALEN("AT+CIPSTATUS\r\n")-1,(uint8_t*)"STATUS:2"}, //6
{(uint8_t*)"AT+CIPSTATUS\r\n",DATALEN("AT+CIPSTATUS\r\n")-1,(uint8_t*)"STATUS:3"}, //7
{(uint8_t*)"AT+CIPSTATUS\r\n",DATALEN("AT+CIPSTATUS\r\n")-1,(uint8_t*)"STATUS:4"}, //8
{(uint8_t*)"AT+CIPSTATUS\r\n",DATALEN("AT+CIPSTATUS\r\n")-1,(uint8_t*)"STATUS:5"}, //9
{(uint8_t*)"AT+CWJAP_DEF?\r\n",DATALEN("AT+CWJAP_DEF?\r\n")-1,(uint8_t*)"OK"}, //10
{(uint8_t*)"AT+CIPMUX=1\r\n",DATALEN("AT+CIPMUX=1\r\n")-1,(uint8_t*)"OK"}, //11
{(uint8_t*)"AT+CIPSTART=0,\"UDP\",\"192.168.1.117\",8000\r\n",DATALEN("AT+CIPSTART=0,\"UDP\",\"192.168.1.117\",8000\r\n")-1,(uint8_t*)"0,CONNECT"},//12
{(uint8_t*)"AT+CIPSTART=1,\"UDP\",\"192.168.1.117\",8888\r\n",DATALEN("AT+CIPSTART=1,\"UDP\",\"192.168.1.117\",8888\r\n")-1,(uint8_t*)"1,CONNECT"},//13
{(uint8_t*)"AT+CIPSTART=2,\"UDP\",\"192.168.1.117\",9000\r\n",DATALEN("AT+CIPSTART=2,\"UDP\",\"192.168.1.117\",9000\r\n")-1,(uint8_t*)"2,CONNECT"},//14
{(uint8_t*)"AT+CIPSTART=3,\"UDP\",\"192.168.1.117\",9999\r\n",DATALEN("AT+CIPSTART=3,\"UDP\",\"192.168.1.117\",9999\r\n")-1,(uint8_t*)"3,CONNECT"},//15
{(uint8_t*)"AT+CIPCLOSE=0\r\n",DATALEN("AT+CIPCLOSE=0\r\n")-1,(uint8_t*)"OK"},//16
{(uint8_t*)"AT+CIPCLOSE=1\r\n",DATALEN("AT+CIPCLOSE=1\r\n")-1,(uint8_t*)"OK"},//17
{(uint8_t*)"AT+CIPCLOSE=2\r\n",DATALEN("AT+CIPCLOSE=2\r\n")-1,(uint8_t*)"OK"},//18
{(uint8_t*)"AT+CIPCLOSE=3\r\n",DATALEN("AT+CIPCLOSE=3\r\n")-1,(uint8_t*)"OK"} //19
};
/*
*********************************************************************************************************
* 函 数 名: wifi_ack_check
* 功能说明: wifi模组应答检测函数
* 形 参: ack
* 返 回 值: TRUE\FALSE
*********************************************************************************************************
*/
uint8_t wifiAtAckCmp(uint8_t* ack)
{
uint8_t usart3RxBuf[200];
uint16_t len;
len = dma_Usart3_Receiv(usart3RxBuf,DATALEN(usart3RxBuf));
if(strstr((const char *)usart3RxBuf,(const char*)ack)){
rs485Send(usart3RxBuf,len);
memset(usart3RxBuf,0,DATALEN(usart3RxBuf));
return TRUE; //返回TRUE说明wifi模组已有应答
}
return FALSE; //返回FALSE说明wifi模组没有应答
}
/*
*********************************************************************************************************
* 函 数 名: sendWifiCmd
* 功能说明: wifi模组发送函数
* 形 参: cmd,ack,waittime
* 返 回 值: TRUE\FALSE
*********************************************************************************************************
*/
uint8_t sendWifiCmd(uint8_t *cmd,uint8_t len,uint8_t *ack,uint16_t waittime) //单片机给wifi模组发送AT指令
{
DMA_usart3_send(cmd,len);
delay_ms(waittime);
if(wifiAtAckCmp(ack)){
return TRUE; //返回TRUE说明wifi模组已有应答
}
return FALSE; //返回FALSE说明wifi模组没有应答
}
/*
*********************************************************************************************************
* 函 数 名: wifiCheakAsk
* 功能说明: 检测esp8266 wifi是否在线函数
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void wifiCheakAsk(void)
{
uint8_t i = 3; //检测3次esp8266是否在线应答
delay_ms(200);
do{
//检测ESP8266模组是否在线
if(sendWifiCmd(wificmd[WIFI_AT].wifiCmd,wificmd[WIFI_AT].cmdLen,wificmd[WIFI_AT].wifiAsk,80))
{
printf("检测ESP8266模组成功,,在进行启动配置,请稍等......\r\n\r\n");
break;
}else{
if(i == 1){
printf("检测ESP8266模组失败!\r\n\r\n");
}
continue;
}
}while(--i);
}
/*
*********************************************************************************************************
* 函 数 名: ipConnectConfig
* 功能说明: esp8266绑定IP地址函数
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void ipConnectConfig(void) //连接路由器绑定IP地址函数
{
uint8_t i = 3,j = 5;
printf("ESP8266模组重启中,请稍等......\r\n");
delay_ms(200); //延时等待wifi模组启动成功
do{
//第一次重启不成功,进行第二次重启
if(sendWifiCmd(wificmd[WIFI_RST].wifiCmd,wificmd[WIFI_RST].cmdLen,wificmd[WIFI_RST].wifiAsk,80))
{
printf("ESP8266模组重启成功!\r\n\r\n");
wifiCheakAsk(); //检测ESP8266模组是否在线
break;
}else{
if(i == 1){
printf("ESP8266模组重启未成功,请再次重启设备!\r\n\r\n");
}
continue;
}
}while(i--);
delay_xs(6); //延时6秒,确保重启成功!
/* 2:获得 IP 3:已连接
4:断开连接 5:未连接到 WiFi
需要注意的是:wifi信号不好的时候,也检测不出网络状态,如网络不好时,检测到的STATUS状态为5,而不是2*/
do{
if(sendWifiCmd(wificmd[WIFI_CIPSTATUS_TWO].wifiCmd,wificmd[WIFI_CIPSTATUS_TWO].cmdLen,wificmd[WIFI_CIPSTATUS_TWO].wifiAsk,80))//第一次发送确认是否连接已连接IP,如果没有确认(没有收到已连接到路由状态),可能是wifi模组正忙于其它操作
{
wifi_config = 1; //智能配置标志,1为已经配置过,下次设备重启不需要进行再进行配置
printf("ESP8266模组已获得路由器IP!\r\n\r\n");
break;
}else{
if(j == 1){ //最后一次检测都连不上网络,则打印连不上网络的情况和网络所处的状态
delay_ms(200);
/*获取esp8266 wifi模组的连接状态*/
if(sendWifiCmd(wificmd[WIFI_CIPSTATUS_THREE].wifiCmd,wificmd[WIFI_CIPSTATUS_THREE].cmdLen,wificmd[WIFI_CIPSTATUS_THREE].wifiAsk,80)){
printf("ESP8266模组已与路由器连接!\r\n");
printf("重启ESP8266模组:\r\n");
if(sendWifiCmd(wificmd[WIFI_RST].wifiCmd,wificmd[WIFI_RST].cmdLen,wificmd[WIFI_RST].wifiAsk,50))
{
printf("ESP8266模组重启成功!\r\n\r\n");
}else{
printf("ESP8266模组重启未成功!\r\n\r\n");
}
delay_ms(500);
}else if(sendWifiCmd(wificmd[WIFI_CIPSTATUS_FOUR].wifiCmd,wificmd[WIFI_CIPSTATUS_FOUR].cmdLen,wificmd[WIFI_CIPSTATUS_FOUR].wifiAsk,60)){
printf("ESP8266模组已与路由器断开连接!\r\n");
printf("重启ESP8266模组:\r\n");
if(sendWifiCmd(wificmd[WIFI_RST].wifiCmd,wificmd[WIFI_RST].cmdLen,wificmd[WIFI_RST].wifiAsk,50))
{
printf("ESP8266模组重启成功!\r\n\r\n");
}else{
printf("ESP8266模组重启未成功!\r\n\r\n");
}
delay_xs(4); //延时4秒
}else{
printf("WIFI信号不好,请检查WIFI信号强弱,或ESP8266模组第一次连接网络,需要进行配网!\r\n");
printf("重启ESP8266模组:\r\n");
if(sendWifiCmd(wificmd[WIFI_RST].wifiCmd,wificmd[WIFI_RST].cmdLen,wificmd[WIFI_RST].wifiAsk,50))
{
printf("ESP8266模组重启成功!\r\n\r\n");
}else{
printf("ESP8266模组重启未成功!\r\n\r\n");
}
delay_ms(500);
}
}
continue;
}
}while(j--);
if(wifi_config == 0){ //wifi_config = 0,说明是第一次配网,下次重启wifi模组不需要进行配网
printf("配置ESP8266模组为Station模式并保存到flash:\r\n");
if(sendWifiCmd(wificmd[WIFI_CWMODE_DEF].wifiCmd,wificmd[WIFI_CWMODE_DEF].cmdLen,wificmd[WIFI_CWMODE_DEF].wifiAsk,80))
{
printf("配置ESP8266模组为Station模式成功!\r\n\r\n");
}else{
printf("配置ESP8266模组为Station模式未成功!\r\n\r\n");
}
delay_ms(200);
printf("重启ESP8266模组:\r\n");
if(sendWifiCmd(wificmd[WIFI_RST].wifiCmd,wificmd[WIFI_RST].cmdLen,wificmd[WIFI_RST].wifiAsk,80))//重启wifi模组,使设置生效
{
printf("ESP8266模组重启成功!\r\n\r\n");
}else{
printf("ESP8266模组重启未成功!\r\n\r\n");
}
delay_ms(800);
if(sendWifiCmd(wificmd[WIFI_CWAUTOCONN].wifiCmd,wificmd[WIFI_CWAUTOCONN].cmdLen,wificmd[WIFI_CWAUTOCONN].wifiAsk,80))
{
printf("使能ESP8266模组上电自动连接路由器!\r\n\r\n");
}else{
printf("未成功使能ESP8266模组上电自动连接路由器!\r\n\r\n");
}
delay_ms(500);
if(sendWifiCmd(wificmd[WIFI_CWSTARTSMART].wifiCmd,wificmd[WIFI_CWSTARTSMART].cmdLen,wificmd[WIFI_CWSTARTSMART].wifiAsk,80))
{
printf("成功配置ESP8266模组智能配网命令!\r\n\r\n");
}else{
printf("未能成功配置ESP8266模组智能配网命令!\r\n\r\n");
}
printf("请打开您的手机进行网络配置连接......\r\n\r\n\r\n\r\n\r\n\r\n");
do{
if(usart3RecvEndFlag == 1){
usart3RecvEndFlag = 0;
dmaUsart3RxLen = 0;
memset(dmaUsart3RxBuf,0,DATA_BUFFER_SIZE);
delay_xs(10); //延时10秒
if(sendWifiCmd(wificmd[WIFI_CWSTOPSMART].wifiCmd,wificmd[WIFI_CWSTOPSMART].cmdLen,wificmd[WIFI_CWSTOPSMART].wifiAsk,80))
{
printf("ESP8266模组释放内存!\r\n\r\n");
delay_xs(3);//延时3秒
if(sendWifiCmd(wificmd[WIFI_CIPSTATUS_TWO].wifiCmd,wificmd[WIFI_CIPSTATUS_TWO].cmdLen,wificmd[WIFI_CIPSTATUS_TWO].wifiAsk,60)){
printf("一键配网成功!\r\n\r\n");
wifi_config = 1;//wifi_config = 1,说明第一次配网成功,下次重启wifi模组不需要进行配网
break;
}else{
printf("一键配网失败!\r\n\r\n");
break;
}
}
}
}while(1);
delay_ms(200);
printf("检测ESP8266模组的信号强度!\r\n");
DMA_usart3_send(wificmd[WIFI_CWJAP_DEF].wifiCmd,wificmd[WIFI_CWJAP_DEF].cmdLen);
delay_ms(200);
if(usart3RecvEndFlag == 1){
usart3RecvEndFlag = 0;
rs485Send(dmaUsart3RxBuf,dmaUsart3RxLen);
dmaUsart3RxLen = 0;
memset(dmaUsart3RxBuf,0,DATA_BUFFER_SIZE);
}
}
}
/*
*********************************************************************************************************
* 函 数 名: serversConnectConfig
* 功能说明: esp8266 wifi连接服务器函数
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void serversConnectConfig(void) //绑定IP地址成功后,进行连接服务器
{
if(sendWifiCmd(wificmd[WIFI_CIPSTATUS_TWO].wifiCmd,wificmd[WIFI_CIPSTATUS_TWO].cmdLen,wificmd[WIFI_CIPSTATUS_TWO].wifiAsk,60))
{
printf("ESP8266模组已绑定IP地址,请进行往下配置!\r\n\r\n");
delay_ms(200);
printf("ESP8266模组开启多连接模式:\r\n");
if(sendWifiCmd(wificmd[WIFI_CIPMUX].wifiCmd,wificmd[WIFI_CIPMUX].cmdLen,wificmd[WIFI_CIPMUX].wifiAsk,80))
{
printf("ESP8266模组成功开启多连接模式!\r\n\r\n");
}else{
printf("ESP8266模组开启多连接模式失败!\r\n\r\n");
}
delay_ms(200);
printf("连接IP地址为:192.168.1.117,端口号为8000的服务器:\r\n");
if(sendWifiCmd(wificmd[WIFI_CIPSTART_ZERO].wifiCmd,wificmd[WIFI_CIPSTART_ZERO].cmdLen,wificmd[WIFI_CIPSTART_ZERO].wifiAsk,80))
{
printf("成功连接IP地址为:192.168.1.117,端口号为8000的服务器!\r\n\r\n");
}else{
printf("连接IP地址为:192.168.1.117,端口号为8000的服务器失败!\r\n\r\n");
}
}
}
/*
*********************************************************************************************************
* 函 数 名: esp8266SendData
* 功能说明: esp8266 wifi注册函数
* 形 参: databuf,len
* 返 回 值: 无
*********************************************************************************************************
*/
void esp8266SendData(uint8_t *databuf,uint8_t len) //连接好服务器,开始往服务器发注册包进行注册
{
uint8_t str[50];
sprintf((char *)str,"AT+CIPSEND=0,%d\r\n",len); //把数组的数据长度数字改为字符串加到AT指令里面
printf("数据发送预先配置:\r\n");
if(sendWifiCmd(str,strlen((char*)str),(uint8_t*)"OK",80))
{
printf("数据发送预先配置成功!\r\n\r\n");
}else{
printf("数据发送预先配置失败!\r\n\r\n");
}
delay_ms(20);
//if(sendWifiCmd((uint8_t*)"我是心跳包!\r\n",DATALEN("我是心跳包!\r\n")-1,(uint8_t*)"OK",80))
if(sendWifiCmd(databuf,len,(uint8_t*)"OK",80))
{
printf("数据发送成功!\r\n\r\n");
}else{
printf("数据发送失败!\r\n\r\n");
}
// if(sendWifiCmd((uint8_t*)"AT+CIPCLOSE=0\r\n",DATALEN("AT+CIPCLOSE=0\r\n")-1,(uint8_t*)"OK",80))
// {
// printf("ESP8266模组解绑IP地址成功!\r\n\r\n");
// }else{
// printf("ESP8266模组解绑IP地址失败!\r\n\r\n");
// }
}
void wifiDataReceiv(void)
{
printf("数据发送预先配置:\r\n");
if(sendWifiCmd((uint8_t*)"AT+CIPSEND=0,24\r\n",DATALEN("AT+CIPSEND=0,24\r\n")-1,(uint8_t*)"OK",80))
{
printf("数据发送预先配置成功!\r\n\r\n");
}else{
printf("数据发送预先配置失败!\r\n\r\n");
}
delay_ms(20);
if(sendWifiCmd((uint8_t*)"我是心跳包,请求注册!\r\n",DATALEN("我是心跳包,请求注册!\r\n")-1,(uint8_t*)"OK",80))
{
printf("心跳包发送成功!\r\n\r\n");
}else{
printf("心跳包发送失败!\r\n\r\n");
}
while(1){
if(usart3RecvEndFlag == 1){
usart3RecvEndFlag = 0;
rs485Send(dmaUsart3RxBuf,dmaUsart3RxLen);
dmaUsart3RxLen = 0;
memset(dmaUsart3RxBuf,0,DATA_BUFFER_SIZE);
}
}
}
实现功能
esp8266 wifi模组手机一键配网(接收到wifi模组的AT指令应答后,单片机进行做出判断,并在串口调试助手上把wifi的AT指令应答和单片机执行的动作打印出来),配网成功,单片机通过esp8266 wifi模组透传发数据到网络调试助手上的模拟服务器。配置一次,下次重启设备后不需再进行配网,除非设备换了地方,或者换了路由器才需要再进行手机配网。
第一次ESP8266进行手机配网
由于在调程序过程中,让esp8266自动连接到了网络。现在只能连接到一个路由器(还是蹭别人的,嘻嘻),为了能实现上面的功能,现在先让esp8266恢复出厂设置,然后进行手机配网。
esp8266恢复出厂设置
esp8266波特率设置
esp8266恢复出厂设置后波特率为默认的115200,此处的波特率为9600,故设置波特率为9600。
初始化成功后,等待手机智能配网
esp8266配置(连接路由器的路由器,esp8266和路由器是绑定不同的IP地址,但在同一个网段)成功后,再连接到服务器。
连接到服务器后,往服务器发送数据,连续发送三次数据,服务器也接收到三次esp8266发来的数据。
第二次重启,不需要手机配网
esp8266重启后进行初始化,自动绑定IP地址,直接连接到服务器,然后往服务器发送数据。
服务器接收到esp8266透传上发的数据