STM32
直播中

李涛

7年用户 1353经验值
私信 关注
[问答]

WIFI热点和服务器是如何实现双向通信的

ESP8266的基本工作原理是什么?

WIFI热点和服务器是如何实现双向通信的?

回帖(1)

胡雄相

2021-11-16 14:10:00
  实验内容
  了解ESP8266的基本工作原理,使程序能够自行连接给定的WIFI热点和服务器并实现双向通信。
  整体思路
  通过直接控制wifi模块可以发现整个连接过程有几个指令是不可缺少的:
  AT测试、
  AT+CWMODE=1设置工作模式、
  AT+CWJAP=“热点名称”,“热点密码”
  AT+CIPSTART=“TCP”,“服务器地址”,端口号
  另外为了方便测试还有ATE1打开回显。
  根据以上命令编写wifi_init()函数,先向wifi模块发送“AT”,接收到OK后发送“AT+CWMODE=1”,接收到OK后一次发送3、4两条命令同时检测是否接收到OK。
  在上述任意环节超出超时时间后还没有检测到OK则认为连接失败,进行下一次连接,连续连接失败3次后返回错误信息。
  代码解析
  wifi模块参数配置:
  #define WIFI_NAME “hello_world” //需要连接的热点名
  #define WIFI_PWD “87654321” //热点密码
  #define SERVER_ADDR “192.168.43.73” //服务器IP地址
  #define SERVER_PORT “5656” //端口号
  此代码段在my_func.h中4-7行,将其中的参数改成自己的热点及服务器信息。
  wifi初始化程序:
  int wifi_init()
  {
  uint8_t ret=0;
  ret = Send_AT_commend(“AT”, “OK”, 100);
  if(!ret)
  return -1;
  #ifdef DEBUG
  Send_AT_commend(“ATE1”, “”, 100);
  #else
  Send_AT_commend(“ATE0”, “”, 100);
  #endif
  ret = Send_AT_commend(“AT+CWMODE=1”, “OK”, 100);
  if(!ret)
  return -2;
  wifi_str();
  ret = Send_AT_commend(temp, “OK”, 9000); //AT+CWJAP=“pxc002”,“?????”
  if(!ret)
  return -3;
  server_str();
  ret = Send_AT_commend(temp, “OK”, 3000); //AT+CIPSTART=“TCP”,“192.168.31.32”,3456
  if(!ret)
  return -4;
  return 1;
  }
  #ifdef到#endif之间的代码为开关AT指令回显,去掉后对程序功能无影响。
  发送AT指令函数:
  uint8_t Send_AT_commend(char *at_commend, char *re_commend, uint16_t time_out)
  {
  uint8_t i=0;
  for(i=0;i《3;i++)
  {
  clear_buf(); //清空接收数组
  HAL_UART_Transmit(&huart1, (uint8_t *)at_commend, strlen(at_commend), 0xFFFF);
  HAL_UART_Transmit(&huart1, (uint8_t *)“rn”, 2, 0xFFFF); //发送回车换行
  HAL_Delay(time_out);
  if(find_str(re_commend))
  return 1;
  i++;
  }
  return 0;
  }
  此函数接收三个参数,分别为需要发送的AT指令、期待的返回数据、超时时间。
  发送AT指令前先将my_re_buf1清空,防止对之前的数据误判,然后发送AT指令并发送回车换行,延时time_out,通过find_str()函数查找开发板是否接收到了wifi模块发来的OK,检测到则返回1,否则i++再发送一次,三次都没有检测到的话就返回0。
  定时器中断回调程序:
  while(send_buf[i])send_buf[i++]=0x00; //清空send_buf数组
  while(pt_r2《pt_w2 )
  {
  //HAL_UART_Transmit(&huart1,&my_re_buf2[pt_r2++],1,1000);
  while(pt_r2《pt_w2)
  send_buf[len++]=my_re_buf2[pt_r2++];
  wifi_send(send_buf,len);
  }
  将demo中的程序注释掉,改成自己的以便实现PC通过板子向服务器发送数据。当pt_r2《pt_w2时,将my_re_buf2中新接收到的数据拷贝到send_buf数组中,再调用wifi_send()函数发送数据。
  发送数据函数:
  void wifi_send(uint8_t *buf, int len)
  {
  char len_str[]=“”,temp1[256]=“”;
  itoa(len, len_str);
  strcat(temp1,“AT+CIPSEND=”);
  strcat(temp1,len_str);
  HAL_UART_Transmit(&huart2, (uint8_t *)“发送数据rn”, 10, 0xFFFF);
  if(Send_AT_commend(temp1, “》”, 300))
  if(Send_AT_commend((char *)buf, “SEND OK”, 300))
  HAL_UART_Transmit(&huart2, (uint8_t *)“发送成功!!!rn”, 16, 0xFFFF);
  }
  此函数接收两个参数,分别为需要发送的字符串数组、发送字节数。
  通过tioa()函数将整数len转换为字符串,并通过strcat将temp1拼接成AT+CIPSEND=len。Send_AT_commend()发送字符串temp1,在接收到“》”后发送字符串buf,接收到“SEND OK”则发送成功。
  踩到的坑
  strstr()函数:
  strstr(s1,s2)函数接收两个字符串参数,具体功能是检测s2是否是s1的子集,是的话返回s2首次出现的地址,否则返回NULL。但是这个函数里面有个硬性bug,如果s1[]={0x00, ‘a’, ‘b’, ‘c’} s1[]={‘a’},strstr(s1,s2)执行后返回NULL,也就是说strstr函数执行的结束标志是s1数组的0x00。这个bug坑了我两个多小时!!!
  指针传值问题:
  在C语言程序中需要计算字符串数组s的长度通常会用到sizeof或者strlen函数,但是如果char *p=s的话sizeof§和strlen§得到的数据都不是s的长度,具体解释是p虽然指向s数组的首地址,但是p不含有s数组后面的数据,因为以上两个函数无法通过指针p获取s的长度。
  总结
  C语言基础知识掌握的扎实真的很重要,否则会像我这样遇到许多很智障的bug。由于写此工程时利用的是零碎的空闲时间且比较仓促,没有做充足的实验验证,因此工程还有一些隐藏和没有解决的bug,比如发送数据时总是会丢失第一个字节(但是发送数据前加一个空格能够完美解决,至于为什么我也不知道,懒得解决了就这样吧) (此bug已解决)。所以工程仅供学习交流,切勿用于生产。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分