STM32F103+ESP8266(WiFi)模块 简单应用之远程控制LED、蜂鸣器和步进电机、读取温湿度

前言

前期准备可以参考我的这篇文章 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

工程下载:

码云 GitHub
在这里插入图片描述

效果图

STA模式 TCP服务器 控制LED1的亮灭

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连接
在这里插入图片描述

AP模式 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端口。
在这里插入图片描述
在这里插入图片描述
等待主动连接
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

AP模式 TCP服务器 读取温湿度

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

STA模式 TCP客户端 连接手机热点 与云服务器建立通信 实现云端控制

1、云服务器的测试环境 搭建配置

编写程序 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端口!

运行环境,进行测试。
在这里插入图片描述

2、源程序修改 烧写

修改wifista.c中的ipbuf,改为服务器公网IP地址

u8 ipbuf[16] = "139.198.169.41"; 	// IP缓存

3、STM32相关功能配置和测试

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

核心代码

下载:码云 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);		// 释放内存
}



版权声明:本文为CSDN博主「Love丶伊卡洛斯」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Ikaros_521/article/details/116232001

生成海报
点赞 0

Love丶伊卡洛斯

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

STM32智能家居项目设计

前言 该项目是嵌入式课程学习最后的一个项目设计,做的不是很好(大佬勿喷…),特别是STM32数据处理部分,因为刚学的STM32,并且对C语言的指针等的使用也有