用ESP8266编写TCP/IP协议的STA(Client)程序

前一章已经搭建了ESP8266的编译环境,接下来就是编写控制代码啦~

写在编写程序的前面

1、ESP8266作为一款物联网模块,必定是要联网的,所以,首先把微软的防火墙关掉!

2、下载程序的时候注意,如果提示“错误”,那么请查看,下载的波特率是不是过高了!

3、在编译前,一定要先保存,再clean project,最后再build project !

4、编写执行周期很长(>500ms)的用户程序时,记得经常喂狗!

如果注意以上几点的话,相信,码代码的过程是会很顺利滴!好了,切入正题。

导入工程后,首先进入application文件夹,双击user后打开user_main.c,从上到下,,并没有熟悉的while大循环,没错,这是一种“内核回调”的机制,即一个方法的指针传递给事件源,当某一事件发生时用来调用这个方法。具体请移步这里

因为我用的板子是不带有外围电路的,所以调试的时候都需要串口打印一些东西来辅助我调试,晶振26MHz,芯片上电初始化会自动打印到串口一些信息,注意,此时的波特率是74880;如果我们用的串口是115200的话,在调试信息出来之前会有一段乱码,这是正常的!

一切准备妥当之后,我们就可以写程序了,记住,用户入口在这里:

void ICACHE_FLASH_ATTR
user_init(void)
{
	uart_init(115200,115200);//初始化串口0和串口1的波特率
	os_delay_us(1000);//等待稳定
	os_printf("\r\n-----------------------------\r\n");
	os_printf("SDK version:%s\r\n",system_get_sdk_version());//打印SDK版本
	os_printf("I am a coder\r\n");
	uart0_sendStr("\r\nHello world\r\n");
	os_printf("\r\n-----------------------------\r\n");

	ESP8266_STA_Init();

	OS_Timer_1_Init(1000,1);//1s重复定时
    //输入输出配置函数
	/*PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO4_U,FUNC_GPIO4);//GPIO4设为IO口
	GPIO_OUTPUT_SET(GPIO_ID_PIN(4),1);//IO4 = 1

	PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U,FUNC_GPIO0);
	GPIO_DIS_OUTPUT(GPIO_ID_PIN(0));//失能输出
	PIN_PULLUP_DIS(PERIPHS_IO_MUX_GPIO0_U);//失能内部上拉
	PIN_PULLUP_EN(PERIPHS_IO_MUX_GPIO0_U);//使能内部上拉
	if(GPIO_INPUT_GET(GPIO_ID_PIN(0)) == 0)
	{
		;
	}*/
	//GPIO中断设置
	/*
	 ETS_GPIO_INTR_DISABLE();//关闭GPIO中断功能
	 WTS_GPIO_INTR_ATTACH((ets_isr_t)GPIO_INTERRUPT,NULL);//注册中断回调函数
	 gpio_pin_intr_state_set(GPIO_ID_PIN(0),GPIO_PIN_INTR_NEGEDGE);//GPIO下降沿中断
	 ETS_GPIO_INTR_ENABLE();//打开GPIO中断功能
	 */
	/*while(1)//测试用
	{
		 system_soft_wdt_feed();//喂狗

		 os_printf("Please think\r\n");

		 delay_ms(1000);
	}*/
}

我们只调用库函数就可以啦,记住,在写回调函数之前,要注册回调函数(下文再叙)!

上文中的毫秒延时函数,是要自己编写的,不过要注意,这里的延时,并不是非常精准:

void ICACHE_FLASH_ATTR delay_ms(u32 C_time)
{
	for(;C_time >0;C_time--)
	{
		os_delay_us(1000);
	}
}

因为这个例程是要将esp8266作为是sta连接路由器作为客户端,所以ESP8266_STA_Init()这个函数就是功能初始化函数了(ctrl键+鼠标左键能直接跳转到函数定义的位置哦~):

void ICACHE_FLASH_ATTR ESP8266_STA_Init()
{
	struct station_config STA_Config;//STA参数结构体
	struct ip_info ST_ESP8266_IP; //STA信息结构体

	wifi_set_opmode(0x01);//设置为station模式并保存到flash
/*
	wifi_station_dhcp_stop();
	IP4_ADDR(&ST_ESP8266_IP.ip,192.168.1.2);
	IP4_ADDR(&ST_ESP8266_IP.netmask,255.255.255.0);
	IP4_ADDR(&ST_ESP8266_IP.gw,192.168.1.1);
	wifi_set_ip_info(STATION_IF,&ST_ESP8266_IP);
	*/
	os_memset(&STA_Config,0,sizeof(struct station_config));//ap参数结构体初始化为0
	os_strcpy(STA_Config.ssid,ESP8266_STA_SSID);
	os_strcpy(STA_Config.password,ESP8266_STA_PASS);

	  wifi_station_set_config(&STA_Config);
}

因为这里设置了dhcp,所以就不用指定IP地址了,ESP8266_STA_PASS和ESP8266_STA_SSID都是需要用字符串宏定义的!两行代码,这里就不写啦。wifi_station_set_config()是初始化以上参数,在1s的重复定时函数里:

void ICACHE_FLASH_ATTR OS_Timer_1_Init(u32 time_ms,u8 time_repetitive)
{
	os_timer_disarm(&OS_Timer_1);//关闭软件定时器
	os_timer_setfn(&OS_Timer_1,(os_timer_func_t *)OS_Timer_1_cb,NULL);//设置回调函数
	os_timer_arm(&OS_Timer_1,time_ms,time_repetitive);//设置定时器参数并使能
}

打开定时器回调函数,即在定时时间到达后要执行的函数:

void ICACHE_FLASH_ATTR OS_Timer_1_cb(void)//回调函数
{
	u8 S_WIFI_STA_Connect;
	struct ip_info ST_ESP8266_IP;//IP信息结构体
	u8 ESP8266_IP[4];

	S_WIFI_STA_Connect = wifi_station_get_connect_status();
	switch(S_WIFI_STA_Connect)
	{
		case 0:		os_printf("\r\nStation_Idle\r\n");							break;
		case 1:		os_printf("\r\nStation_Connecting\r\n");				break;
		case 2:		os_printf("\r\nStation_Wrong_Password\r\n");	break;
		case 3:		os_printf("\r\nStation_No_Ap_Found\r\n");		break;
		case 4:		os_printf("\r\nStation_Connect_Fail\r\n");			break;
		case 5:		os_printf("\r\nStation_Got_IP\r\n");						break;
	}
	if(S_WIFI_STA_Connect == STATION_GOT_IP)
	{
		wifi_get_ip_info(STATION_IF,&ST_ESP8266_IP);

		ESP8266_IP[0] = ST_ESP8266_IP.ip.addr;//点分表示
		ESP8266_IP[1] = ST_ESP8266_IP.ip.addr>>8;
		ESP8266_IP[2] = ST_ESP8266_IP.ip.addr>>16;
		ESP8266_IP[3] = ST_ESP8266_IP.ip.addr>>24;
		os_printf("ESP8266_IP = %d.%d.%d.%d.\r\n",ESP8266_IP[0],ESP8266_IP[1],ESP8266_IP[2],ESP8266_IP[3]);
		os_timer_disarm(&OS_Timer_1);
		ESP8266_NetCon_Init();
	}
}

以上,获取模块的地址并打印到串口,然后,进入这个函数:

void ICACHE_FLASH_ATTR ESP8266_NetCon_Init()
{
	ST_NetCon.type = ESPCONN_TCP;//设置为TCP协议
	ST_NetCon.proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp));//开辟内存

	ST_NetCon.proto.tcp ->local_port = 8266;//设置socket
	ST_NetCon.proto.tcp ->remote_port = 8888;
	ST_NetCon.proto.tcp ->remote_ip[0] = 192;
	ST_NetCon.proto.tcp ->remote_ip[1] = 168;
	ST_NetCon.proto.tcp ->remote_ip[2] = 1;
	ST_NetCon.proto.tcp ->remote_ip[3] = 10;

	espconn_regist_connectcb(&ST_NetCon,ESP8266_TCP_Connect_Cb);//注册回调函数
	espconn_regist_reconcb(&ST_NetCon,ESP8266_TCP_Break_Cb);

	espconn_connect(&ST_NetCon);//连接TCP-Server
}

以上就是连接服务器啦,设置协议,本地通信端口和服务的的IP+Port,设置完成后就进入连接请求函数,这里,就直接调用啦,在这个函数中还注册了异常断开和正常断开的回调函数,这样,再编写指定的函数,就可以建立断线重连机制了!

这是文件头:

#include "ets_sys.h"
#include "c_types.h"//变量类型
#include "user_config.h"//用户配置
#include "osapi.h"//os_xxx、软件定时器
#include "user_interface.h"//系统接口、system_param_xxx接口、WIFI等
#include "eagle_soc.h"//GPIO函数、宏定义
#include "driver/uart.h"//串口初始化文件
#include "ets_sys.h"//回调函数
#include "os_type.h"//os_xxx
#include "ip_addr.h"
#include "espconn.h"
#include "mem.h"

struct espconn ST_NetCon;
os_timer_t OS_Timer_1;//定义软件定时器

至此,保存,清理工程,编译工程,就可以上手啦!

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值