完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
实验内容
了解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已解决)。所以工程仅供学习交流,切勿用于生产。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1614 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1541 浏览 1 评论
970 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
682 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1592 浏览 2 评论
1863浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
644浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
515浏览 3评论
531浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
504浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 00:36 , Processed in 0.794374 second(s), Total 78, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号