一、硬件连接

ESP8266 STM32
3V3 3.3
GND GND
RX PB10
TX PB11

然后STM32f103C8T6核心板自带了一个LED接的是PB13引脚。
在这里插入图片描述

这里值得一提的是,刚开始我把ESP8266的3V3引脚接到了USB转TTL的3V3上,用串口调试助手没反应,后来发现是供电的问题,换到STLINK的3.3V上就好了。
在这里插入图片描述

二、云平台

想要实现远程控制,需要一个数据转发的过程,所以,我们需要云平台来给我们转发数据。这里推荐一个物联平台: http://www.doit.am/

将手机以及其他设备(如ESP8266)接入云平台后,它们之间就可以进行远程通信了。

获取IP地址和端口号http://tcp.doit.am/,这个IP和端口号在后面的软件配置里需要用到
点进去之后是这样的
在这里插入图片描述

三、软件配置

1、LED的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//LED初始化
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); //使能PC端口时钟

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; //LED0-->PB.5 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOC, &GPIO_InitStructure); //根据设定参数初始化GPIOC13

GPIO_SetBits(GPIOC,GPIO_Pin_13); //PC13 输出高
}

2、串口3的配置

因为我们需要串口1来调试代码,所以用STM32的串口3也就是PB10、PB11与ESP8266连接,下面是串口3的配置代码以接收中断服务函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//串口接收缓存区 	
u8 USART3_RX_BUF[USART3_MAX_RECV_LEN]; //接收缓冲,最大USART3_MAX_RECV_LEN个字节.
u8 USART3_TX_BUF[USART3_MAX_SEND_LEN]; //发送缓冲,最大USART3_MAX_SEND_LEN字节

//接收到的数据状态
//[15]:0,没有接收到数据;1,接收到了一批数据.
//[14:0]:接收到的数据长度
vu16 USART3_RX_STA=0;

//串口3接收中断服务函数
void USART3_IRQHandler(void)
{
u8 res;
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)//接收到数据
{
res =USART_ReceiveData(USART3);
USART_SendData(DEBUG_USARTx,res); //这里是把ESP8266发送到串口3的消息发送到电脑端串口调试助手,便于调试

if(res != 'A') //以‘A’为结束位,收到‘A’表示一次接收消息完成
{
if((USART3_RX_STA&(1<<15))==0)//接收完的一批数据,还没有被处理,则不再接收其他数据
{
USART3_RX_BUF[USART3_RX_STA++]=res; //记录接收到的值
}
else
{
USART3_RX_STA|=1<<15; //没有收到结束符‘A’,收到的字节数>=0x80,强制标记接收完成
}
}
else
{
USART3_RX_STA|=1<<15; //接收消息完成
}
}
}


//初始化IO 串口3
//pclk1:PCLK1时钟频率(Mhz)
//bound:波特率
void usart3_init(u32 bound)
{
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // GPIOB时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); //串口3时钟使能

USART_DeInit(USART3); //复位串口3
//USART3_TX
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB10

//USART3_RX
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB11

USART_InitStructure.USART_BaudRate = bound;//波特率一般设置为9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式

USART_Init(USART3, &USART_InitStructure); //初始化串口 3

USART_Cmd(USART3, ENABLE); //使能串口

//使能接收中断
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启中断

//设置中断优先级
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器

USART3_RX_STA=0; //清零
}

//串口3,printf 函数
//确保一次发送数据不超过USART3_MAX_SEND_LEN字节
void u3_printf(char* fmt,...)
{
u16 i,j;
va_list ap;
va_start(ap,fmt);
vsprintf((char*)USART3_TX_BUF,fmt,ap);
va_end(ap);
i=strlen((const char*)USART3_TX_BUF); //此次发送数据的长度
for(j=0;j<i;j++) //循环发送数据
{
while(USART_GetFlagStatus(USART3,USART_FLAG_TC)==RESET); //循环发送,直到发送完毕
USART_SendData(USART3,USART3_TX_BUF[j]);
}
}

3、ESP8266的配置

这里需要注意的是,因为要发送 “ ,所以要加上转义字符 \

这里的IP地址与端口号填我们在云平台获取的,每发送一条命令都需要延时等待一下,可以按情况更改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
char a[]="AT+CWMODE=1";
char b[]="AT+RST";
char c[]="AT+CWJAP=\"WIFI名称\",\"WIFI密码\"";
char d[]="AT+CIPMUX=1";
char e[]="AT+CIPSTART=0,\"TCP\",\"IP地址\",端口号";

void delay_s(int sec)
{
for(int i=0;i<sec;i++)
{
delay_ms(1000);
}
}

void esp8266_start_trans(void)
{
//设置工作模式 1:station模式 2:AP模式 3:兼容 AP+station模式
esp8266_send_cmd1((u8 *)a);
delay_s(2);

//重启
esp8266_send_cmd1((u8 *)b);
delay_s(4);

//连接WIFI
esp8266_send_cmd1((u8 *)c);
delay_s(8);

esp8266_send_cmd1((u8 *)d);
delay_s(2);

//连接TCP服务端
esp8266_send_cmd1((u8 *)e);
delay_s(2);
}

void esp8266_send_cmd1(u8 *cmd)
{
u3_printf("%s\r\n",cmd); //发送命令,需要加换行符
}

4、main函数

收到”on”开灯,收到”off”灭灯

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
int main(void)
{
USART_Config();
delay_init();
LED_Init();

usart3_init(115200);

esp8266_start_trans();

printf("初始化完成\n");

USART3_RX_STA=0;
while(1)
{

if(USART3_RX_STA&0x8000) //如果消息接收完成,则处理
{
if(strstr((const char*)USART3_RX_BUF,"on")) //这里是看接收到的消息中有没有自己设置的命令“on”,strstr()函数不会用的可以搜一下
{
GPIO_ResetBits(GPIOC,GPIO_Pin_13);
}
if(strstr((const char*)USART3_RX_BUF,"off"))
{
GPIO_SetBits(GPIOC,GPIO_Pin_13);
}
USART3_RX_STA=0; //消息处理完成,开始重新接收
memset(USART3_RX_BUF,0,600); //将接收区清0
}

}
}

四、测试

打开电脑串口调试助手,用手机或电脑网络调试助手连接云平台,发送命令,记得加上结束符’A’,现象如下,同时LED的亮灭情况也随命令变化

手机端我用的是自己写的APP
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210603223725797.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzUwNTI3NjM1,size_16,color_FFFFFF,t_70#pic_center =300x533)

电脑串口调试助手
在这里插入图片描述

LED的变化我就不贴出来了

最后把我的工程文件以及APP分享出来,需要的自取,链接:https://pan.baidu.com/s/1cd3nMlHz6UTnPx74tv3TVA
提取码:0k0c