0%

stm32_note_21day

============================
2022-9-13
============================

一.温故知新

    短距无线通信模块->nRF24L01
    接口->SPI接口
    SPI一共有4条线
    (CSN<片选>\SCK<时钟线>\MOSI<主出从入>\MISO<主入从出>)
    全双工的工作模式
    nRF可以实现一对一的通信,也可以实现一对多的通信
    最多是一对六的通信->有6个接收数据的通道
    在不同的频道下可以实现多对多的通信

二.短距无线通信模块

    WiFi模块->使用的芯片型号是ESP8266(是乐鑫公司的芯片)
    本身也是一个32bit的单片机芯片
    只不过乐鑫公司在生产ESP8266芯片时在内部已经烧写了TCP/UDP的协议栈
    ESP8266的接口是USART/UART的接口需要连接到我们开发板的USART2上
    USART2_TX	PA2
    USART2_RX	PA3
需要通过STM32的USART2为ESP8266模块发送AT指令(WiFi\GPRS\NB-IoT)

AT指令集

AT指令使用示例

单连接 TCP Client

ESP8266单连接

        1.设置WiFi模式
            "AT+CWMODE=1\r\n"
            需要接收"OK"
        如果设置成单连接 TCP Client可以修改成=1
            注意 :
            =1	softAP模式
            =2	station模式
            =3	softAP+station模式
        
        2.连接路由
            "AT+CWJAP="SSID","password"\r\n"
            需要接收"OK"
            注意 :
            1)
            SSID	是路由器的名称
            password	是路由器的密码
            2)
            路由器的名称不能是中文,也不能有空格
            尽量是大小写英文字母
            3)
            路由器的密码必须要有
            4)
            在小范围之内WiFi信号会有干扰,有可能会影响实验

        3.查询设备 IP 地址
            "AT+CIFSR\r\n"
            注意 :
            1)只需要有查询的指令发送即可,不需要接收查询的结果

        4.ESP8266 作为 client 连接到 TCP server
            "AT+CIPSTART="TCP","IP",PORT\r\n"
            需要接收"OK"
            注意 :
            1)
            IP	指的是Server端的IP地址(PC机获取的IP)
            PORT	指的是Server端的端口号(可以自己设置)

        5.发送数据
            "AT+CIPSEND=4\r\n"
            首先需要接收"OK"
            然后需要接收'>'
            在'>'之后写上你要发送的数据
            发送完数据之后,需要接收"SEND OK"
            注意 :
            1)
            =4	代表将来要发送4bytes数据(不算'\0')
            2)
            如果算上'\0'
            =6	"Hello"会造成忙等

        6.接收数据
            "+IPD,n:xxxxxxxxxx"
            注意 : 
            1)
            n	代表的是接收到数据的字节数
            2)
            xxxx	代表的是接收到的数据

        7.断开 TCP 连接
            "AT+CIPCLOSE\r\n"
            注意 :
            1)只需要发送断开连接的指令,不需要接收应答

透传模式

ESP8266透传

        1.在连接完TCP Server端之后需要使能透传模式
            "AT+CIPMODE=1\r\n"
            需要接收"OK"
        
        2.发送数据
            "AT+CIPSEND\r\n"
            首先需要接收"OK"
            然后需要接收'>'
            在'>'之后写上你要发送的数据
            注意 : 
            1)在透传模式下不需要指定发送数据的字节数
        
        3.退出发送数据
            "+++"
            代表要退出发送数据

        4.断开 TCP 连接
            "AT+CIPCLOSE\r\n"
            注意 :
            1)只需要发送断开连接的指令,不需要接收应答

=============================
任务
1.把STM32F103开发板上的TCP client连接调通
2.组内找同学把STM32F103开发板上的固定远端的UDP通信调通
3.组内找同学把STM32F407开发板上的TCP client连接调通
=============================

esp8266.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#ifndef __ESP8266_H
#define __ESP8266_H
/*
ESP8266模块是WIFI无线通讯模块,该模块是串口接口
连接到了我们开发板上的USART2
*/
#include "stm32f10x_conf.h"//包含该头文件所有的外设头文件均已包含

typedef void (*wifi_recv_handler)(char *buf, int len);//通过typedef定义函数指针类型

extern void set_wifi_recv_handler(wifi_recv_handler h);//设置wifi接收到数据的回调函数
extern void esp8266_init(void);//初始化的函数(初始化串口)
extern void esp8266_link_wifi(char *ssid, char *passwd);//连接路由(需要路由的名称和路由的密码)
extern void esp8266_connect(char *ip, char *port);//连接TCP server
extern void esp8266_disconnect(void);//断开TCP连接
extern void esp8266_send(char *msg, char *len);//发送数据
extern void dataHandler(unsigned char c);//处理接收到的数据

#endif

esp8966.c

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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#include "esp8266.h"
#include "usart2.h"
#include "delay.h"
#include "stdio.h"
#include "stdlib.h"

#define O_F 1//O的状态
#define K_F 2//K的状态
static int flag = O_F;
static int ok_flag = 0;
static int len = 0;//保存数据长度的整数

//"+IPD,13:1234567890ABC"
#define ADD_S 0//+的状态
#define I_S 1//I的状态
#define P_S 2//P的状态
#define D_S 3//D的状态
#define H_S 4//,的状态
#define LEN_S 5//长度的状态
#define DATA_S 6//数据的状态
static int data_flag = ADD_S;//默认是+的状态
wifi_recv_handler wifi_handler = NULL;

void set_wifi_recv_handler(wifi_recv_handler h)//设置wifi接收到数据的回调函数
{
wifi_handler = h;
}

void dataHandler(unsigned char c)//处理接收到的数据
{
static char len_buf[5];//接收到数据的字节数
static int i = 0;//循环变量
static char data_buf[512];//存储接收到的数据

switch(data_flag)
{
case ADD_S :
if(c == '+')
data_flag = I_S;
break;
case I_S :
if(c == 'I')
data_flag = P_S;
else
data_flag = ADD_S;
break;
case P_S :
if(c == 'P')
data_flag = D_S;
else
data_flag = ADD_S;
break;
case D_S :
if(c == 'D')
data_flag = H_S;
else
data_flag = ADD_S;
break;
case H_S :
if(c == ',')
data_flag = LEN_S;
else
data_flag = ADD_S;
break;
case LEN_S ://+IPD,13:1234567890ABC
if(c == ':')
{
len_buf[i] = '\0';
len = atoi(len_buf);
data_flag = DATA_S;
i = 0;
break;
}
else
len_buf[i] = c;
i++;
break;
case DATA_S:
data_buf[i] = c;
i++;
if(i == len)
{
i = 0;
data_flag = ADD_S;
if(wifi_handler)
wifi_handler(data_buf, len);
break;
}
break;
}

if(c == '>')
ok_flag = 1;

if(ok_flag == 0)
{
switch(flag)
{
case O_F :
if(c == 'O')
flag = K_F;
break;
case K_F :
if(c == 'K')
{
flag = O_F;
ok_flag = 1;
}
else
flag = O_F;
break;
}
}
}

void esp8266_init(void)//初始化的函数(初始化串口)
{
usart_2_init();
}

void esp8266_link_wifi(char *ssid, char *passwd)//连接路由(需要路由的名称和路由的密码)
{
//AT+RST\r\n 重启无线模块
usart_2_send_data("AT+RST\r\n");
delay_ms(2000);//重启之后延时两秒

//AT+CWMODE=1\r\n 选择wifi模式
ok_flag = 0;
usart_2_send_data("AT+CWMODE=1\r\n");//选择模式
while(ok_flag == 0);//等待esp8266的OK

//AT+CWJAP="SSID","password"\r\n 连接路由
ok_flag = 0;
usart_2_send_data("AT+CWJAP=");
usart_2_send_byte('"');
usart_2_send_data(ssid);
usart_2_send_byte('"');
usart_2_send_byte(',');
usart_2_send_byte('"');
usart_2_send_data(passwd);
usart_2_send_byte('"');
usart_2_send_data("\r\n");
while(ok_flag == 0);

//AT+CIFSR\r\n 查询分配到的IP地址(必须要查一下,否则无法建立连接)
usart_2_send_data("AT+CIFSR\r\n");
}

void esp8266_connect(char *ip, char *port)//连接TCP server
{
//AT+CIPSTART="TCP","192.168.3.116",8080\r\n 建立TCP连接
ok_flag = 0;
usart_2_send_data("AT+CIPSTART=");
usart_2_send_byte('"');
usart_2_send_data("TCP");
usart_2_send_byte('"');
usart_2_send_byte(',');
usart_2_send_byte('"');
usart_2_send_data(ip);
usart_2_send_byte('"');
usart_2_send_byte(',');
usart_2_send_data(port);
usart_2_send_data("\r\n");
while(ok_flag == 0);
}

void esp8266_disconnect(void)//断开TCP连接
{
//AT+CIPCLOSE\r\n 断开TCP连接
usart_2_send_data("AT+CIPCLOSE\r\n");
//注意:有可能回复有可能不回复,所以不检测closed ok
}

void esp8266_send(char *msg, char *len)//发送数据
{
//AT+CIPSEND=4\r\n 发送数据
ok_flag = 0;
usart_2_send_data("AT+CIPSEND=");
usart_2_send_data(len);
usart_2_send_data("\r\n");
while(ok_flag == 0);//等待 OK

ok_flag = 0;
while(ok_flag == 0);//等待 >

ok_flag = 0;
usart_2_send_data(msg);
while(ok_flag == 0);//等待 SEND OK
}