延时函数初始化,单片机指令执行速度过快,向8266发送AT指令时需要延时等待。
串口1使用PA9、PA10,串口1向电脑的串口助手发送信息,来反映AT指令的响应.
串口2使用PA2、PA3,向8266发送AT指令,用来控制8266。
WiFi_ResetIO_Init(); //初始化WiFi的复位IO
WiFi复位引脚为PA4,低电平WiFi复位
image.png

8266接收数据变量定义

image.png
串口2通过中断来接收数据,将其存放到char Usart2_RxBuff[USART2_RXBUFF_SIZE] 数组中
控制8266,依靠字符串的搜素和比较
image.png

wifi初始化大循环

wifi.c
image.png
WiFi_Reset()函数
if(strstr(WiFi_RX_BUF,”ready”)) //如果接收到ready表示复位成功
WiFi_RX_BUF是串口2的Usart2_RxBuff(接收数据缓存区)

单片机通过串口1向8266发送AT指令,82266与串口2相连,8266收到指令的响应存放在串口2的Usart2_RxBuff中。
image.png
char WiFi_InitServer_AP(void)
{
char temp[50];

u1_printf(“准备复位模块\r\n”); //串口提示数据
if(WiFi_Reset(50)){ //复位,100ms超时单位,总计5s超时时间
u1_printf(“复位失败,准备重启\r\n”); //返回非0值,进入if,串口提示数据
return 1; //返回1
}else u1_printf(“复位成功\r\n”); //串口提示数据

main.c
image.png
while(WiFi_InitServer_AP()){ //循环,初始化,建立服务器,直到成功
Delay_Ms(200); //延时
}

上面的循环嵌套在主函数循环中

  1. /*-------------------------------------------------*/
  2. /*函数名:建立服务器初始化 */
  3. /*参 数:无 */
  4. /*返回值:0:正确 其他:错误 */
  5. /*-------------------------------------------------*/
  6. char WiFi_InitServer_AP(void)
  7. {
  8. char temp[50];
  9. u1_printf("准备复位模块\r\n"); //串口提示数据
  10. if(WiFi_Reset(50)){ //复位,100ms超时单位,总计5s超时时间
  11. u1_printf("复位失败,准备重启\r\n"); //返回非0值,进入if,串口提示数据
  12. return 1; //返回1
  13. }else u1_printf("复位成功\r\n"); //串口提示数据
  14. u1_printf("准备设置AP模式\r\n"); //串口提示数据
  15. if(WiFi_SendCmd("AT+CWMODE=2",50)){ //设置AP模式,100ms超时单位,总计5s超时时间
  16. u1_printf("设置AP模式失败,准备重启\r\n"); //返回非0值,进入if,串口提示数据
  17. return 2; //返回2
  18. }else u1_printf("设置AP模式成功\r\n"); //串口提示数据
  19. u1_printf("准备设置AP参数\r\n"); //串口提示数据
  20. u1_printf("SSID:%s\r\n",SSID); //串口提示数据
  21. u1_printf("密码:%s\r\n",PASS); //串口提示数据
  22. u1_printf("AP热点IP:%s\r\n",AP_IP); //串口提示数据
  23. u1_printf("加密方式:WPA_WPA2_PSK\r\n"); //串口提示数据
  24. u1_printf("准备设置AP热点IP\r\n"); //串口提示数据
  25. memset(temp,0,50); //清除临时缓冲区
  26. sprintf(temp,"AT+CIPAP=\"%s\"",AP_IP); //构建命令
  27. if(WiFi_SendCmd(temp,50)){ //设置AP热点IP,100ms超时单位,总计5s超时时间
  28. u1_printf("设置AP热点IP失败,准备重启\r\n"); //返回非0值,进入if,串口提示数据
  29. return 3; //返回3
  30. }else u1_printf("设置AP热点IP成功\r\n"); //串口提示数据
  31. u1_printf("准备设置AP参数\r\n"); //串口提示数据
  32. if(WiFi_SET_AP(SSID,PASS,WPA_WPA2_PSK,50)){ //设置AP参数,100ms超时单位,总计5s超时时间
  33. u1_printf("设置AP参数失败,准备重启\r\n"); //返回非0值,进入if,串口提示数据
  34. return 4; //返回4
  35. }else u1_printf("设置AP参数成功\r\n"); //串口提示数据
  36. u1_printf("准备关闭透传\r\n"); //串口提示数据
  37. if(WiFi_SendCmd("AT+CIPMODE=0",50)){ //关闭透传,100ms超时单位,总计5s超时时间
  38. u1_printf("关闭透传失败,准备重启\r\n"); //返回非0值,进入if,串口提示数据
  39. return 5; //返回5
  40. }else u1_printf("关闭透传成功\r\n"); //串口提示数据
  41. u1_printf("准备开启多路连接\r\n"); //串口提示数据
  42. if(WiFi_SendCmd("AT+CIPMUX=1",50)){ //开启多路连接,100ms超时单位,总计5s超时时间
  43. u1_printf("开启多路连接失败,准备重启\r\n"); //返回非0值,进入if,串口提示数据
  44. return 6; //返回6
  45. }else u1_printf("开启多路连接成功\r\n"); //串口提示数据
  46. u1_printf("准备开启多路连接\r\n"); //串口提示数据
  47. if(WiFi_SendCmd("AT+CIPMUX=1",50)){ //开启多路连接,100ms超时单位,总计5s超时时间
  48. u1_printf("开启多路连接失败,准备重启\r\n"); //返回非0值,进入if,串口提示数据
  49. return 7; //返回7
  50. }else u1_printf("开启多路连接成功\r\n"); //串口提示数据
  51. u1_printf("准备开启服务器\r\n"); //串口提示数据
  52. if(WiFi_SendCmd("AT+CIPSERVER=1,5050",50)){ //准备开启服务器,端口号5050,100ms超时单位,总计5s超时时间
  53. u1_printf("开启服务器失败,准备重启\r\n"); //返回非0值,进入if,串口提示数据
  54. return 8; //返回8
  55. }else u1_printf("开启服务器成功,端口号5050\r\n"); //串口提示数据
  56. return 0; //正确返回0
  57. }

AT指令发送函数

wifi.c文件中
image.png
WiFi_SendCmd()函数

  1. /*-------------------------------------------------*/
  2. /*函数名:WiFi发送设置指令 */
  3. /*参 数:cmd:指令 */
  4. /*参 数:timeout:超时时间(100ms的倍数) */
  5. /*返回值:0:正确 其他:错误 */
  6. /*-------------------------------------------------*/
  7. char WiFi_SendCmd(char *cmd, int timeout)
  8. {
  9. WiFi_RxCounter=0; //WiFi接收数据量变量清零
  10. memset(WiFi_RX_BUF,0,WiFi_RXBUFF_SIZE); //清空WiFi接收缓冲区
  11. WiFi_printf("%s\r\n",cmd); //发送指令
  12. while(timeout--){ //等待超时时间到0
  13. Delay_Ms(100); //延时100ms
  14. if(strstr(WiFi_RX_BUF,"OK")) //如果接收到OK表示指令成功
  15. break; //主动跳出while循环
  16. u1_printf("%d ",timeout); //串口输出现在的超时时间
  17. }
  18. u1_printf("\r\n"); //串口输出信息
  19. if(timeout<=0)return 1; //如果timeout<=0,说明超时时间到了,也没能收到OK,返回1
  20. else return 0; //反之,表示正确,说明收到OK,通过break主动跳出while
  21. }

WiFi_RxCounter=0; //WiFi接收数据量变量清零
memset(WiFi_RX_BUF,0,WiFi_RXBUFF_SIZE); //清空WiFi接收缓冲区
WiFi_printf(“%s\r\n”,cmd); //发送指令

发送指令前必须清空串口2接收缓存区,
memset(WiFi_RX_BUF,0,WiFi_RXBUFF_SIZE); //清空WiFi接收缓冲区 ,
否则上一条指令的响应会影响后面的判断条件

AT指令

AT+CIPAP指令 设置AP的IP地址
image.png
image.png
image.png

传输模式(是否透传)

image.png
image.png
image.png

建立TCP服务器

image.png
image.png
image.png
服务器 被叫
客户端 主叫

数据收发(主函数)

main.c

  1. while(1) //主循环
  2. {
  3. WiFi_Get_LinkSta(); //检测有无客户端连接或是断开
  4. if(WiFi_Get_Data(Data_buff,Data_len,Data_id)){ //接收数据
  5. u1_printf("连接id:%s有%s字节数据到来\r\n",Data_id,Data_len); //串口显示信息
  6. u1_printf("数据:%s\r\n",Data_buff); //串口显示信息
  7. WiFi_SendData(Char_to_Hex(Data_id,strlen(Data_id)),Data_buff,strlen(Data_buff),500);//5s的发送超时时间,发送数据
  8. }

获取sta连接状态函数

  1. /*-------------------------------------------------*/
  2. /*函数名:获取连接状态 */
  3. /*参 数:无 */
  4. /*返回值:连接状态 */
  5. /* 0:无状态 */
  6. /* 1:有客户端接入 */
  7. /* 2:有客户端断开 */
  8. /*-------------------------------------------------*/
  9. char WiFi_Get_LinkSta(void)
  10. {
  11. char id_temp[10]={0}; //缓冲区,存放ID
  12. char sta_temp[10]={0}; //缓冲区,存放状态
  13. if(strstr(WiFi_RX_BUF,"CONNECT")){ //如果接受到CONNECT表示有客户端连接
  14. sscanf(WiFi_RX_BUF,"%[^,],%[^,]",id_temp,sta_temp);
  15. u1_printf("有客户端接入,ID=%s\r\n",id_temp); //串口显示信息
  16. WiFi_RxCounter=0; //WiFi接收数据量变量清零
  17. memset(WiFi_RX_BUF,0,WiFi_RXBUFF_SIZE); //清空WiFi接收缓冲区
  18. return 1; //有客户端接入
  19. }else if(strstr(WiFi_RX_BUF,"CLOSED")){ //如果接受到CLOSED表示有链接断开
  20. sscanf(WiFi_RX_BUF,"%[^,],%[^,]",id_temp,sta_temp);
  21. u1_printf("有客户端断开,ID=%s\r\n",id_temp); //串口显示信息
  22. WiFi_RxCounter=0; //WiFi接收数据量变量清零
  23. memset(WiFi_RX_BUF,0,WiFi_RXBUFF_SIZE); //清空WiFi接收缓冲区
  24. return 2; //有客户端断开
  25. }else return 0; //无状态改变
  26. }

image.png
image.png
当客户端连接到服务器时,响应为CONNECT。
image.png
sscanf(WiFi_RX_BUF,”%[^,],%[^,]”,id_temp,sta_temp);
通过sscanf函数,把响应分别存放到,id_temp,sta_temp中,并向串口2打印端口号

获取sta数据函数

  1. /*-------------------------------------------------*/
  2. /*函数名:获取客户端数据 */
  3. /* 两组回车换行符\r\n\r\n作为数据的结束符 */
  4. /*参 数:data:数据缓冲区 */
  5. /*参 数:len: 数据量 */
  6. /*参 数:id: 发来数据的客户端的连接ID */
  7. /*返回值:数据状态 */
  8. /* 0:无数据 */
  9. /* 1:有数据 */
  10. /*-------------------------------------------------*/
  11. char WiFi_Get_Data(char *data, char *len, char *id)
  12. {
  13. char temp[10]={0}; //缓冲区
  14. char *presult;
  15. if(strstr(WiFi_RX_BUF,"+IPD")){
  16. Delay_Ms(10); //延时
  17. sscanf(WiFi_RX_BUF,"%[^,],%[^,],%[^:]",temp,id,len);//截取各段数据,主要是id和数据长度
  18. presult = strstr(WiFi_RX_BUF,":"); //查找冒号。冒号后的是数据
  19. if( presult != NULL ) //找到冒号
  20. sprintf((char *)data,"%s",(presult+1)); //冒号后的数据,复制到data
  21. WiFi_RxCounter=0; //WiFi接收数据量变量清零
  22. memset(WiFi_RX_BUF,0,WiFi_RXBUFF_SIZE); //清空WiFi接收缓冲区
  23. return 1; //有数据到来
  24. } else return 0; //无数据到来
  25. }

image.png
ESP8266 接收到网络数据时向串口发送 +IPD 和数据。
格式为: +IPD,0,3:456(接收到的数据为456)
sscanf(WiFi_RX_BUF,”%[^,],%[^,],%[^:]”,temp,id,len);//截取各段数据,主要是id和数据长度

presult = strstr(WiFi_RX_BUF,”:”); //查找冒号。冒号后的是数据
if( presult != NULL ) //找到冒号
sprintf((char )data,”%s”,(presult+1)); //冒号后的数据,复制到data
*main.c

image.png
获取数据并串口2打印

收到数据后发送

  1. /*-------------------------------------------------*/
  2. /*函数名:服务器发送数据 */
  3. /*参 数:databuff:数据缓冲区<2048 */
  4. /*参 数:data_len:数据长度 */
  5. /*参 数:id: 客户端的连接ID */
  6. /*参 数:timeout: 超时时间(10ms的倍数) */
  7. /*返回值:错误值 */
  8. /* 0:无错误 */
  9. /* 1:等待发送数据超时 */
  10. /* 2:连接断开了 */
  11. /* 3:发送数据超时 */
  12. /*-------------------------------------------------*/
  13. char WiFi_SendData(char id, char *databuff, int data_len, int timeout)
  14. {
  15. int i;
  16. WiFi_RxCounter=0; //WiFi接收数据量变量清零
  17. memset(WiFi_RX_BUF,0,WiFi_RXBUFF_SIZE); //清空WiFi接收缓冲区
  18. WiFi_printf("AT+CIPSEND=%d,%d\r\n",id,data_len); //发送指令
  19. while(timeout--){ //等待超时与否
  20. Delay_Ms(10); //延时10ms
  21. if(strstr(WiFi_RX_BUF,">")) //如果接收到>表示成功
  22. break; //主动跳出while循环
  23. u1_printf("%d ",timeout); //串口输出现在的超时时间
  24. }
  25. if(timeout<=0)return 1; //超时错误,返回1
  26. else{ //没超时,正确
  27. WiFi_RxCounter=0; //WiFi接收数据量变量清零
  28. memset(WiFi_RX_BUF,0,WiFi_RXBUFF_SIZE); //清空WiFi接收缓冲区
  29. for(i=0;i<data_len;i++)WiFi_printf("%c",databuff[i]); //发送数据
  30. while(timeout--){ //等待超时与否
  31. Delay_Ms(10); //延时10ms
  32. if(strstr(WiFi_RX_BUF,"SEND OK")){ //如果接受SEND OK,表示发送成功
  33. WiFi_RxCounter=0; //WiFi接收数据量变量清零
  34. memset(WiFi_RX_BUF,0,WiFi_RXBUFF_SIZE); //清空WiFi接收缓冲区
  35. break; //跳出while循环
  36. }
  37. if(strstr(WiFi_RX_BUF,"link is not valid")){ //如果接受link is not valid,表示连接断开
  38. WiFi_RxCounter=0; //WiFi接收数据量变量清零
  39. memset(WiFi_RX_BUF,0,WiFi_RXBUFF_SIZE); //清空WiFi接收缓冲区
  40. return 2; //返回2
  41. }
  42. }
  43. if(timeout<=0)return 3; //超时错误,返回3
  44. else return 0; //正确,返回0
  45. }
  46. }

image.png
image.png
WiFi_printf(“AT+CIPSEND=%d,%d\r\n”,id,data_len); //发送指令

字符0和数字0

数据格式
字符串、十进制、十六进制

数字0代表0,字符串0是一个编码,代表0x30.
image.png
wifi.c

  1. /*-------------------------------------------------*/
  2. /*函数名:字符型数字转换成数字,0-9999 */
  3. /*参 数:char_data:字符型数字 */
  4. /*参 数:len: 位数 */
  5. /*返回值:转换后的数字 */
  6. /*-------------------------------------------------*/
  7. int Char_to_Hex(char *char_data, int len)
  8. {
  9. int temp;
  10. switch(len)
  11. {
  12. case 1 : temp=(char_data[0]-0x30)*1;
  13. break;
  14. case 2 : temp=(char_data[0]-0x30)*10;
  15. temp+=(char_data[1]-0x30)*1;
  16. break;
  17. case 3 : temp=(char_data[0]-0x30)*100;
  18. temp+=(char_data[2]-0x30)*10;
  19. temp+=(char_data[3]-0x30)*1;
  20. break;
  21. case 4 : temp=(char_data[0]-0x30)*1000;
  22. temp+=(char_data[1]-0x30)*100;
  23. temp+=(char_data[2]-0x30)*10;
  24. temp+=(char_data[3]-0x30)*1;
  25. break;
  26. }
  27. return temp;
  28. }