赞
踩
前期准备可以参考我的这篇文章 STM32F103+ESP8266(WiFi)模块 实现AP模式下的TCP C/S 和 UDP Client,重复部分不再赘述。
AP STA STA+AP 模式下,建立tcp/udp连接后,发送指定命令,控制LED1和蜂鸣器的开关,读取DHT11模块温湿度数据,控制步进电机正反转90度。
命令如下:(每行都是一条命令,不要有换行等)具体实现在common.c
中
LED1 ON
LED1 OFF
BEEP ON
BEEP OFF
GET T&H
MOTOR CW
MOTOR ACW
main.c
中调用atk_8266_test();
atk_8266_test(); //进入ATK_ESP8266测试
common.c
中 配置要连接wifi的信息
//WIFI STA模式,设置要去连接的路由器无线参数,请根据你自己的路由器设置,自行修改.
const u8* wifista_ssid="ikaros"; //路由器SSID号
const u8* wifista_encryption="wpawpa2_aes"; //wpa/wpa2 aes加密方式
const u8* wifista_password="12345678"; //连接密码
准备2个手机(有WiFi的电脑,接入路由器等都可以),一个打开热点,根据配置设置ssid、加密和密码。
串口调试打开,相关配置需要串口信息协助完成。
手机也连上同一个wifi,打开 网络调试工具,我用的是“网络测试”,创建tcp连接
复位,打开串口
手机连接wifi,查看分配的ip
修改代码wifiap.c
中的atk_8266_wifiap_test
函数中的ipbuf
u8 ipbuf[16] = "192.168.4.2"; // 改为手机分配到的ip
端口在common.c
中,我们保持不变
//连接端口号:8086,可自行修改为其他端口.
const u8* portnum="8086";
重新编译烧录。打开串口,重复刚才的操作
手机开启tcp server,监听8086端口。
等待主动连接
编写程序 server.c 监听 内网IP的8086端口,需要注意,此程序是一收一发的形式,程序如下:
#include <stdio.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <string.h> int main() { printf("服务器创建socket...\n"); int sockfd = socket(AF_INET,SOCK_STREAM,0); if(0 > sockfd) { perror("socket"); return -1; } printf("准备地址...\n"); struct sockaddr_in addr = {}; addr.sin_family = AF_INET; // 你的端口 addr.sin_port = htons(8086); // 你的内网IP addr.sin_addr.s_addr = inet_addr("10.130.4.89"); socklen_t len = sizeof(addr); printf("绑定socket与地址...\n"); if(bind(sockfd,(struct sockaddr*)&addr,len)) { perror("bind"); return -1; } printf("设置监听...\n"); if(listen(sockfd,5)) { perror("listen"); return -1; } printf("等待客户端连接...\n"); for(;;) { struct sockaddr_in addrcli = {}; int clifd = accept(sockfd,(struct sockaddr*)&addrcli,&len); if(0 > clifd) { perror("accept"); continue; } if(0 == fork()) { char buf[1024] = {}; for(;;) { printf("read:"); read(clifd,buf,sizeof(buf)); printf("%s\n",buf); if(0 == strcmp("quit",buf)) { close(clifd); return 0; } printf(">"); gets(buf); write(clifd,buf,strlen(buf)+1); } } } close(sockfd); }
服务器安全组放行8086端口!
运行环境,进行测试。
修改wifista.c
中的ipbuf,改为服务器公网IP地址
u8 ipbuf[16] = "139.198.169.41"; // IP缓存
下载:码云 GitHub
main.c
调用的atk_8266_test();
#include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" #include "lcd.h" #include "key.h" #include "usmart.h" #include "malloc.h" #include "usart3.h" #include "common.h" #include "beep.h" #include "dht11.h" #include "step.h" // AP模式测试 void ap_demo(void); int main(void) { delay_init(); //延时函数初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级 uart_init(115200); //串口初始化为115200 usmart_dev.init(72); //初始化USMART LED_Init(); //初始化与LED连接的硬件接口 KEY_Init(); //初始化按键 BEEP_Init(); //初始化蜂鸣器 //LCD_Init(); //初始化LCD usart3_init(115200); //初始化串口3 my_mem_init(SRAMIN); //初始化内部内存池 Step_Motor_GPIO_Init(); // 步进电机初始化 //LCD_Clear(BLACK); while(DHT11_Init()) //DHT11初始化 DATA -> PG11 { printf("DHT11 Error\r\n"); } delay_ms(1000); BEEP = 0; LED1 = 0; // ap_demo(); atk_8266_test(); //进入ATK_ESP8266测试 } // AP模式测试 void ap_demo(void) { u8 timex = 0; u8 netpro = 0; //网络模式 0,TCP服务器 1,TCP客户端 2,UDP模式 u8 key; u8 ipbuf[16] = "192.168.4.2"; //IP (根据你的设备连上模块后分配到的IP填写) u8 *p; u16 t = 999; //加速第一次获取链接状态 u16 rlen = 0; u8 constate = 0; //连接状态 while(atk_8266_send_cmd("AT","OK",20))//检查WIFI模块是否在线 { atk_8266_quit_trans();//退出透传 atk_8266_send_cmd("AT+CIPMODE=0","OK",200); //关闭透传模式 printf("未检测到模块!!!\r\n"); delay_ms(800); printf("尝试连接模块...\r\n"); } while(atk_8266_send_cmd("ATE0","OK",20));//关闭回显 printf("ATK_ESP8266 WIFI模块测试\r\n"); printf("WIFI AP\r\n"); atk_8266_msg_show(0, 0, 0); while(1) { delay_ms(10); atk_8266_at_response(1);//检查ATK-ESP8266模块发送过来的数据,及时上传给电脑 printf("ATK-ESP WIFI-AP 测试\r\n"); printf("正在配置ATK-ESP8266模块,请稍等...\r\n"); p=mymalloc(SRAMIN,32); //申请32字节内存 PRESTA: if(netpro&0X02) //UDP { printf("ATK-ESP WIFI-AP 测试\r\n"); printf("正在配置ATK-ESP模块,请稍等...\r\n"); sprintf((char*)p,"AT+CIPSTART=\"UDP\",\"%s\",%s",ipbuf,(u8*)portnum); //配置目标UDP服务器 atk_8266_send_cmd("AT+CIPMUX=0","OK",100); //单链接模式 while(atk_8266_send_cmd(p,"OK",500)); } else //TCP { if(netpro&0X01) //TCP Client 透传模式测试 { printf("ATK-ESP WIFI-AP 测试\r\n"); printf("正在配置ATK-ESP模块,请稍等...\r\n"); atk_8266_send_cmd("AT+CIPMUX=0","OK",20); //0:单连接,1:多连接 sprintf((char*)p,"AT+CIPSTART=\"TCP\",\"%s\",%s",ipbuf,(u8*)portnum); //配置目标TCP服务器 while(atk_8266_send_cmd(p,"OK",200)) { printf("WK_UP:返回重选"); printf("ATK-ESP 连接TCP Server失败"); //连接失败 key=KEY_Scan(0); if(key==WKUP_PRES)goto PRESTA; } atk_8266_send_cmd("AT+CIPMODE=1","OK",200); //传输模式为:透传 } else //TCP Server { printf("ATK-ESP WIFI-AP 测试\r\n"); printf("正在配置ATK-ESP模块,请稍等...\r\n"); atk_8266_send_cmd("AT+CIPMUX=1","OK",20); //0:单连接,1:多连接 sprintf((char*)p,"AT+CIPSERVER=1,%s",(u8*)portnum); atk_8266_send_cmd(p,"OK",20); //开启Server模式,端口号为8086 } } printf("配置ATK-ESP模块成功!\r\n"); delay_ms(200); printf("WK_UP:退出测试 KEY0:发送数据\r\n"); atk_8266_get_wanip(ipbuf);//服务器模式,获取WAN IP sprintf((char*)p,"IP地址:%s 端口:%s",ipbuf,(u8*)portnum); printf("%s\r\n",p); //显示IP地址和端口 atk_8266_wificonf_show(30,180,"请用设备连接WIFI热点:",(u8*)wifiap_ssid,(u8*)wifiap_encryption,(u8*)wifiap_password); printf("状态:%s\r\n",(u8*)ATK_ESP8266_WORKMODE_TBL[netpro]); //连接状态 USART3_RX_STA=0; while(1) { key=KEY_Scan(0); if(key==WKUP_PRES) //WK_UP 退出测试 { atk_8266_quit_trans(); //退出透传 atk_8266_send_cmd("AT+CIPMODE=0","OK",20); //关闭透传模式 myfree(SRAMIN,p); //释放内存 return; } else if(key==KEY0_PRES) //KEY0 发送数据 { if((netpro==3)||(netpro==2)) //UDP { sprintf((char*)p,"ATK-8266%s测试%02d\r\n",ATK_ESP8266_WORKMODE_TBL[netpro],t/10);//测试数据 printf("发送数据:%s\r\n",p); atk_8266_send_cmd("AT+CIPSEND=25","OK",200); //发送指定长度的数据 delay_ms(200); atk_8266_send_data(p,"OK",100); //发送指定长度的数据 timex=100; } else if((netpro==1)) //TCP Client { atk_8266_quit_trans(); atk_8266_send_cmd("AT+CIPSEND","OK",20); //开始透传 sprintf((char*)p,"ATK-8266%s测试%02d\r\n",ATK_ESP8266_WORKMODE_TBL[netpro],t/10);//测试数据 printf("发送数据:%s\r\n",p); u3_printf("%s",p); timex=100; } else //TCP Server { sprintf((char*)p,"ATK-8266%s测试%02d\r\n",ATK_ESP8266_WORKMODE_TBL[netpro],t/10);//测试数据 printf("发送数据:%s\r\n",p); atk_8266_send_cmd("AT+CIPSEND=0,25","OK",200); //发送指定长度的数据 delay_ms(200); atk_8266_send_data(p,"OK",100); //发送指定长度的数据 timex=100; } } if(timex)timex--; t++; delay_ms(5); if(USART3_RX_STA&0X8000) //接收到一次数据了 { rlen=USART3_RX_STA&0X7FFF; //得到本次接收到的数据长度 USART3_RX_BUF[rlen]=0; //添加结束符 sprintf((char*)p,"收到%d字节,内容如下",rlen);//接收到的字节数 printf("%s\r\n",p); //显示接收到的数据长度 printf("接收数据:%s\r\n",USART3_RX_BUF);//显示接收到的数据 USART3_RX_STA=0; // USART3收到的数据进行解析 recv_data_analysis(netpro, USART3_RX_BUF); if(constate!='+')t=1000; //状态为还未连接,立即更新连接状态 else t=0; //状态为已经连接了,10秒后再检查 } if(t==1000)//连续10秒钟没有收到任何数据,检查连接是不是还存在. { constate=atk_8266_consta_check();//得到连接状态 if(constate=='+')printf("连接成功\r\n"); //连接状态 else printf("连接失败\r\n"); t=0; } if((t%20)==0)LED0=!LED0; atk_8266_at_response(1); } } }
在 wifiap.c wifista.c apsta.c
中,在收到USART3数据时,调用recv_data_analysis
函数,传入当前模式和收到的数据,进行解析
// USART3收到的数据进行解析
recv_data_analysis(netpro, USART3_RX_BUF);
在common.c
中,recv_data_analysis
函数实现如下
// USART3收到的数据进行解析 void send_data_to_usart3(u8 netpro, char *data) { u8 len = 0; u8 buf[20] = {0}; len = strlen(data); if((netpro==3)||(netpro==2)) //UDP { sprintf((char*)buf, "AT+CIPSEND=%d", len); atk_8266_send_cmd(buf,"OK",200); //发送指定长度的数据 delay_ms(200); atk_8266_send_data((u8 *)data,"OK",100); //发送指定长度的数据 } else if((netpro==1)) //TCP Client { atk_8266_quit_trans(); atk_8266_send_cmd("AT+CIPSEND","OK",20); //开始透传 u3_printf("%s", data); } else // TCP server { sprintf((char*)buf, "AT+CIPSEND=0,%d", len); atk_8266_send_cmd(buf,"OK",200); //发送指定长度的数据 delay_ms(200); atk_8266_send_data((u8 *)data,"OK",100); //发送指定长度的数据 } } // USART3收到的数据进行解析 void recv_data_analysis(u8 netpro, u8 *USART3_RX_BUF) { char *ptr = NULL; char buf[100] = {0}; u8 temperature = 0; u8 humidity = 0; ptr = mymalloc(SRAMIN, 600); //申请600字节内存 if((netpro==1)) //TCP Client { sprintf(ptr, "%s", USART3_RX_BUF); } else //TCP Server { ptr = strstr((char *)USART3_RX_BUF, ":"); if(NULL != ptr) { // ptr指针后移一位 ptr++; printf("解析后的命令为(<>内):<%s>\r\n", ptr); } } // 接收到的数据进行处理 if(strcmp(ptr, "LED1 ON") == 0) { LED1 = 0; printf("打开LED1\r\n"); send_data_to_usart3(netpro, "打开LED1成功\r\n"); } else if(strcmp(ptr, "LED1 OFF") == 0) { LED1 = 1; printf("关闭LED1\r\n"); send_data_to_usart3(netpro, "关闭LED1成功\r\n"); } else if(strcmp(ptr, "BEEP OFF") == 0) { BEEP = 0; printf("关闭BEEP\r\n"); send_data_to_usart3(netpro, "关闭BEEP成功\r\n"); } else if(strcmp(ptr, "BEEP ON") == 0) { BEEP = 1; printf("开启BEEP\r\n"); send_data_to_usart3(netpro, "开启BEEP成功\r\n"); } else if(strcmp(ptr, "GET T&H") == 0) { DHT11_Read_Data(&temperature, &humidity); //读取温湿度值 sprintf(buf, "读取,温度:%d℃ 湿度:%d%%RH\r\n", temperature, humidity); printf("%s", buf); send_data_to_usart3(netpro, buf); } else if(strcmp(ptr, "MOTOR ACW") == 0) { motor_circle(16, 1, 2); printf("步进电机正转90度\r\n"); send_data_to_usart3(netpro, "步进电机正转90度成功\r\n"); } else if(strcmp(ptr, "MOTOR CW") == 0) { motor_circle(16, 2, 2); printf("步进电机反转90度\r\n"); send_data_to_usart3(netpro, "步进电机反转90度成功\r\n"); } myfree(SRAMIN, ptr); // 释放内存 }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。