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);		// 释放内存
}



  • 77
    点赞
  • 774
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 73
    评论
### 回答1: STM32F103ESP8266是常用的嵌入式系统开发模块STM32F103是一款具有高性能、低功耗的ARM Cortex-M3内核的微控制器,而ESP8266则是一款低成本、高集成度的WiFi模块。下面是一个关于这两个模块的源码的简要说明。 STM32F103的源码: 在STM32F103的源码中,开发者可以使用Keil或者CubeMX等开发工具进行开发。开发者需要编写C语言代码,通过使用相应的库函数和寄存器配置,实现所需的功能。通常情况下,首先需要设置GPIO引脚,然后选择合适的外设进行配置,例如串口、定时器、ADC等等。源码中也包含了中断处理函数,用于处理外部事件的中断请求。开发者可以根据自己的需求,编写相应的源码来实现自己的功能。 ESP8266的源码: ESP8266的源码通常使用C语言进行开发。开发者可以使用Arduino IDE或者ESP-IDF等开发工具进行开发。ESP8266提供了丰富的库函数和API接口,开发者可以通过这些函数和接口,实现与WiFi相关的功能,例如连接到无线网络、发送和接收数据等。开发者还可以通过AT指令与模块进行通信,以完成一些底层的配置,例如WiFi模式切换、网络的连接和断开等。开发者可以根据自己的需求,编写相应的源码来实现自己的功能。 总结: STM32F103ESP8266都是广泛应用嵌入式系统开发的模块STM32F103的源码开发主要是基于ARM Cortex-M3内核的微控制器,而ESP8266的源码开发则主要是针对WiFi模块。开发者可以根据自己的需求,选择相应的开发工具和编程方法来进行开发。无论是STM32F103还是ESP8266,都提供了丰富的库函数和API接口,开发者可以通过合理编写源码来实现各种复杂的功能。 ### 回答2: STM32F103是一款32位ARM Cortex-M3内核的微控制器,而ESP8266是一款低成本且高性能的Wi-Fi模块。在使用STM32F103ESP8266进行开发时,一般是将它们连接在一起,实现Wi-Fi功能。 STM32F103的源码可以使用Keil MDK等开发工具来编写和烧录,可以通过引脚连接将STM32F103ESP8266进行通信,完成数据的收发功能。通过编写源码,我们可以利用STM32F103的丰富外设资源,如GPIO、UART、SPI等功能,控制ESP8266模块的连接和数据传输。 在源码中,我们可以设置STM32F103的引脚,将其与ESP8266的引脚连接,确保相互之间能够正常通信。通过串口通信,可以与ESP8266模块进行命令交互,例如发送AT指令来配置Wi-Fi网络和连接服务器。同时,也可以通过SPI或者I2C等接口与ESP8266模块进行数据的收发,实现与其他设备的通信。 此外,在源码中我们还可以设置STM32F103的定时器和中断,以实现网络连接的超时判断和数据的定时发送。通过编写合适的源码,我们可以灵活地控制和利用STM32F103ESP8266的功能,并实现复杂的应用,如远程控制、物联网等等。 综上所述,STM32F103ESP8266结合使用,通过编写源码实现数据的收发控制。这样的组合可以在嵌入式系统中实现Wi-Fi功能,为应用带来更多的便利和可能性。
评论 73
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Love丶伊卡洛斯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值