esp8266模块是串口通讯,通讯的协议是AT指令,要正确的配置对应的AT指令模块才可以工作,这里就需要知道AT指令有没有配置成功,这个比较容易实现,一般发送AT指令配置成功的话,芯片都会返回至少一个OK,当然还有其它数据,我们只需要去解析有没有接收到OK就知道指令发送是否成功了。我这里是作为TCP客服端,所以只需要以下一些指令即可:
1>> 发送 AT\r\n 返回 "OK"
以上操作确保芯片连接正常,工作正常
2>> 发送 ATE0\r\n 返回 "OK"
关闭回显
3>> 发送 AT+CWMODE=1\r\n 返回 "OK"
设置成客服端模式
4>> 发送 AT+CIPSTATUS 返回 "2 3 4 5" 2 3为连接
确保连接到路由器
5>> 发送 AT+CWJAP="HES_WIFI","wifi_pass" 返回 "OK"
返回 "FAIL"
连接到路由器
6>> 发送 AT+CWAUTOCONN=1 返回 "OK"
开机自动连接
7>> 发送 AT+CIPSTART="TCP","192.168.0.105",8888 返回 "OK"
连接到服务器
8>> 发送 AT+CIPCLOSE 返回 "OK"
关闭服务器连接
8>> 发送 AT+CIPMODE=1 返回 "OK"
设置透传模式1
9>> 发送 AT+CIPSEND 返回 ">"
进入透传
10>> 发送 +++ 返回 无
程序驱动也会按照这个流程来实现;
大概框架如下
esp8266wifi.c文件主要是AT指令配置
serial_config.c文件主要用于解析返回的数据,例如OK,>等
uart.c是串口的应用协议
1-先看看esp8266wifi的内容
#define FANHUI_V "OK" //普通指令返回值
extern u8 wifi_name[20]; //路由器名字
extern u8 wifi_pass[20]; //路由器密码
extern u8 wifi_ip[32]; //服务器ip
extern u8 wifi_port[6]; //服务器端口
static u8 wifi_work_mode; //wifi模块的工作模式,1为配置模式,2为透传模式
#define _WIFI_TRAN_MODE 2
#define _WIFI_CONFIG_MODE 1
/*模块初始化
1.测试AT命令,保证芯片工作正常
2.关闭回显
3.设置成客服端模式
4.连接到路由器
5.连接到服务器
6.设置透传模式1
7.开始透传
8.关闭透传
*/
u8 esp8266_init(void);
//测试AT指令,确保连接和芯片正常
u8 test_at(void);
//关闭回显
u8 close_huixian(void);
//设置成客户端
u8 set_client(void);
//判断是否连接路由器
u8 is_connect_ap(void);
//连接到路由器
u8 connect_ap(void);
//设置自动连接路由器
u8 aotu_connect_ap(void);
//连接到服务器
u8 connect_server(void);
//断开服务器
u8 disconnect_server(void);
//设置透传模式
u8 set_mode1(void);
//开始透传
u8 start_tran(void);
//关闭透传
u8 close_tran(void);
//设置为透传模式
void set_tran_mode(void);
//设置成配置模式
void set_config_mode(void);
//获取工作模式
u8 get_work_mode(void);
//发送命令和等待时间
u8 send_cmd_wait(u8 *str,u8 len,u32 d_ms);
#endif
这里主要介绍一下
//发送命令和等待时间
u8 send_cmd_wait(u8 *str,u8 len,u32 d_ms);
这个函数比较重要,主要功能还是发生一个AT指令,等待nms后检测是否收到OK,下面是实现
//发送命令和等待时间
u8 send_cmd_wait(u8 *str,u8 len,u32 d_ms)
{
serial2_sned_buff(str,len);
delay_ms(d_ms);
if(find_quq_del(OK)) //查找串口数据缓存是否OK
{
return 1;
}
return 0;
}
关闭透传也比较特殊,实现如下
//关闭透传
u8 close_tran()
{
serial2_sned_buff((u8*)"+++",3);
delay_ms(20);
serial2_sned_buff((u8*)"+++",3);
delay_ms(20);
serial2_sned_buff((u8*)"\r\n",2);
delay_ms(20);
return 1;
}
所有函数太多,只介绍几个关键的,其它的可以在后面下载源码。
接下来是serial_config文件
这个文件主要实现1-串口缓冲区添加数据(数据要在串口中断添加),2-解析是否存在相应指令
#define MES_LEN 200
//command
#define OK (char*)"OK"
#define AP2 (char*)"2\r\n"
#define AP3 (char*)"3\r\n"
#define OFF (char*)"off"
#define ON (char*)"on"
#define STATE (char*)"state"
//Log Switch
#define ERIAL_CONFIG_LOG 0
static int num;
static char mes_buf[MES_LEN]; //串口队列长度
//寻找子并移除子串
int find_str_del(char *mes,char *str);
//寻找命令
//参数:命令
//查找到命令返回1,否则0
int find_quq_del(char *str);
//添加数据到队列
void add_mes_buf(char ch);
#endif
uart.c应用协议是自己定义的,和模块没有关系,其实以上2个文件已经看正常的初始化esp8266了。
初始化函数:
u8 esp8266_init()
{
//设置成配置模式
set_config_mode();
//测试AT
if(test_at())
{
#if ESP8266_LOG
printf("esp8266硬件 正常\r\n");
#endif
}
else
{
#if ESP8266_LOG
printf("esp8266硬件 异常\r\n");
printf("尝试关闭透传...\r\n");
#endif
close_tran();
}
//关回显
if(close_huixian())
{
#if ESP8266_LOG
printf("关闭esp8266回显 正常\r\n");
#endif
}
else
{
#if ESP8266_LOG
printf("关闭esp8266回显 异常\r\n");
#endif
}
//设置成客户端
if(set_client())
{
#if ESP8266_LOG
printf("设置成客户端 正常\r\n");
#endif
}
else
{
#if ESP8266_LOG
printf("设置成客户端 异常\r\n");
#endif
}
//判断是否连接到路由器 is_connect_ap
if(is_connect_ap())
{
#if ESP8266_LOG
printf("连接路由器 正常\r\n");
#endif
}
else //如果没有连接路由器,则去连接
{
#if ESP8266_LOG
printf("连接路由器 异常\r\n");
printf("尝试连接路由器...\r\n");
#endif
if(connect_ap())
{
#if ESP8266_LOG
printf("连接路由器 正常\r\n");
#endif
aotu_connect_ap();
}
else
{
#if ESP8266_LOG
printf("连接路由器 异常\r\n");
#endif
}
}
//连接到服务器
if(connect_server())
{
#if ESP8266_LOG
printf("连接服务器 正常\r\n");
#endif
}
else
{
#if ESP8266_LOG
printf("连接服务器 异常\r\n");
printf("尝试关闭连接服务器,重新连接...\r\n");
#endif
if(disconnect_server())
{
#if ESP8266_LOG
printf("关闭连接服务器 正常\r\n");
#endif
//连接到服务器
if(connect_server())
{
#if ESP8266_LOG
printf("重新连接服务器 正常\r\n");
#endif
}
else
{
#if ESP8266_LOG
printf("连接服务器 异常\r\n");
#endif
}
}
else
{
#if ESP8266_LOG
printf("关闭连接服务器 异常\r\n");
#endif
}
}
//设置透传模式1
if(set_mode1())
{
#if ESP8266_LOG
printf("设置透传模式1 正常\r\n");
#endif
}
else
{
#if ESP8266_LOG
printf("设置透传模式1 异常\r\n");
#endif
}
//开始透传
if(start_tran())
{
#if ESP8266_LOG
printf("开始透传 正常\r\n");
#endif
//设置成配置模式
set_tran_mode();
}
else
{
#if ESP8266_LOG
printf("开始透传 异常\r\n");
#endif
return 0;
}
return 1;
}
整体使用的过程。
1,主函数必须初始化串口,esp8266_init()
2,while(1)里面实现如下,
//任务2函数
void task2_func(void *param)
{
u8 data_count_time=0;
int j=1;
while(1)
{
if(get_work_mode()==_WIFI_TRAN_MODE) //判断是否是透传模式
{
//检查wifi数据
check_wifi_data();
if(wifi_mes.recv_len>0)
{
printf("%dwifi:%s\r\n",j++,wifi_mes.recv_data);
}
else
{
data_count_time++;
if(data_count_time==5) //如果很久没有接到数据
{
clear_wifi_buf(); //清空缓存
}
}
//serial2_sned_buff((u8*)"hello world\r\n",13);
}
task_delay(1);
}
}
串口中断实现如下:如果是配置模式,把数据放到命令解析的缓存里,如果是透传模式,把数据放到应用协议的缓存里
void USART2_IRQHandler(void)
{
USART_ClearFlag(USART2,USART_FLAG_TC);
if(USART_GetITStatus(USART2,USART_IT_RXNE)!=Bit_RESET)//检查指定的USART中断发生与否
{
u8 k=USART_ReceiveData(USART2);
if(get_work_mode()==_WIFI_CONFIG_MODE) //如果是配置模式
{
add_mes_buf(k);
}else
{
wifi_buf_add(k);
//printf("%x ",k);
}
}
}
整体测试下来,效果还是很不错的,一晚上通讯没有死机掉线。用的是TCP工具,没有自己写socket
代码量还是比较多的,不能一一讲解,可以下载源码学习,看部分代码可以知道注释是很足的。