https://www.cnblogs.com/yangfengwu/p/11456667.html

由于上一节的源码长时间以后会自动断开,所以再做这一版非RTOS版的,咱直接用lua源码里面别人写的(站在巨人的肩膀上)

咱再细细的看下lua怎么实现的源码

首先确定lua都调用了什么函数

https://www.cnblogs.com/yangfengwu/p/7533302.html    lua写的TCP 客户端

用到的部分程序

Client = net.createConnection(net.TCP, ) 


        Client:connect(,"192.168.1.103")

        Client:on("receive", function(Client, data)
uart.write(,data)
end) Client:on("connection", function(sck, c)
ClientConnectedFlage =
TcpConnect = Client
print("Link OK")
tmr.stop() Client:on("disconnection", function(sck, c)
ClientConnectedFlage =
TcpConnect = nil
tmr.start()
end)
end)

https://nodemcu.readthedocs.io/en/master/modules/net/    用到的函数都在net里面

注意:lua源码里面为了使用户操作起来便捷,所以封装的很灵活(代码更复杂些,咱只提取咱用到的部分)

源码实际处理部分

就是返回的那个结构体变量,后面的话肯定就是调用结构体变量里面的成员变量

大家知道lwip提供了两种实现网络通信的方式

第一种是 :RAW模式   就是不需要操作系统参与,所有的都是靠回调函数实现

第二种是:跑任务的

其实lua源码里面是使用的RAW模式的

大家可以自行百度LWIP  RAW实现TCP客户端,然后呢,大家大可不必深究lua的每一句代码了,现在应该提炼人家实现的思想,把人家提供的源码当做自己的参考

烂程序员关心的是代码,好程序员关心的是数据结构和它们之间的关系!

实际上实现连接很简单

#include "esp_common.h"
#include "gpio.h"
#include "uart.h"
#include "esp_timer.h"
#include "hw_timer.h"
#include "pwm.h"
#include "data_dispose.h"
#include "espconn.h"
#include "esp_wifi.h"
#include "lwip/api.h" #include "crc.h"
#include "smart_config.h" #include "lwip/err.h"
#include "lwip/ip_addr.h"
#include "lwip/dns.h"
#include "lwip/igmp.h"
#include "lwip/tcp.h" LOCAL os_timer_t public_timer;//定时器
u32 public_timer_cnt=;//累加
u32 public_timer_state=;//状态
u32 public_timer_out=;//超时
u32 public_timer_cnt1=;//累加 extern u8 Usart1ReadBuff[Usart1ReadLen];//接收数据的数组
extern u32 Usart1ReadCnt;//串口1接收到的数据个数
extern u32 Usart1ReadCntCopy;//串口1接收到的数据个数拷贝
extern u8 Usart1ReadFlage;//串口1接收到一条完整数据 #define SSID "Learn8266" //无线名称
#define PWD "11223344" //密码
struct softap_config soft_ap_Config;//AP模式配置 //连接的路由器信息
#define APssid "qqqqq"
#define APpassword "11223344"
struct station_config stationConf; //TCP客户端
struct tcp_pcb *TcpClient;
ip_addr_t addr;//创建连接的服务器地址用 ResolveData ResolveDataTest;//解析数据IEEE754
//uint32 pin_info_list[1][3]={PERIPHS_IO_MUX_GPIO5_U,FUNC_GPIO5,5};//配置GPIO5作为PWM输出
//int duty[1]={0};//高电平时间是0us /******************************************************************************
* FunctionName : user_rf_cal_sector_set
* Description : SDK just reversed 4 sectors, used for rf init data and paramters.
* We add this function to force users to set rf cal sector, since
* we don't know which sector is free in user's application.
* sector map for last several sectors : ABCCC
* A : rf cal
* B : rf init data
* C : sdk parameters
* Parameters : none
* Returns : rf cal sector
*******************************************************************************/
uint32 user_rf_cal_sector_set(void)
{
flash_size_map size_map = system_get_flash_size_map();
uint32 rf_cal_sec = ; switch (size_map) {
case FLASH_SIZE_4M_MAP_256_256:
rf_cal_sec = - ;
break; case FLASH_SIZE_8M_MAP_512_512:
rf_cal_sec = - ;
break; case FLASH_SIZE_16M_MAP_512_512:
case FLASH_SIZE_16M_MAP_1024_1024:
rf_cal_sec = - ;
break; case FLASH_SIZE_32M_MAP_512_512:
case FLASH_SIZE_32M_MAP_1024_1024:
rf_cal_sec = - ;
break; default:
rf_cal_sec = ;
break;
} return rf_cal_sec;
} //串口调用此函数就说明接收到了一条完整的数据,就可以去处理了
void UartReadCallback()//定义一个函数
{ } //网络接收到数据
void TcpClientRecv(void *arg, char *pdata, unsigned short len)
{
while(len--)
{
uart0_write_char(*(pdata++));//发送到串口
}
} //断开了连接
void TcpClientDisCon(void *arg)
{
dbg_printf("\nTcpClientDisCon\n"); } //连接上服务器
err_t TcpConnected(void *arg, struct tcp_pcb *tpcb, err_t err)
{
if (TcpClient != tpcb || err != ERR_OK){
TcpClient = NULL;
dbg_printf("\nConnection aborted\n");
}
dbg_printf("\nTcpConnected\n");
return ERR_OK;
} //连接出错
void TcpConnectErr(void *arg, sint8 err)
{
dbg_printf("\nTcpConnectErr=%d\n",err);
} //监听WiFi状态改变
void wifi_event_monitor_handle_event_cb(System_Event_t *evt)
{
switch (evt->event_id)
{
case EVENT_STAMODE_CONNECTED://连接上路由器
dbg_printf("\n\tSTAMODE_CONNECTED\n"); dbg_printf("\tConnected to SSID %s, Channel %d\n",
evt->event_info.connected.ssid,
evt->event_info.connected.channel);
break; case EVENT_STAMODE_DISCONNECTED://和路由器断开
dbg_printf("\n\tSTAMODE_DISCONNECTED\n"); dbg_printf("\tDisconnect from SSID %s, reason %d\n",
evt->event_info.disconnected.ssid,
evt->event_info.disconnected.reason);
break; case EVENT_STAMODE_AUTHMODE_CHANGE://这个是 啥..
dbg_printf("\n\tSTAMODE_AUTHMODE_CHANGE\n"); dbg_printf("\tAuthmode: %u -> %u\n",
evt->event_info.auth_change.old_mode,
evt->event_info.auth_change.new_mode);
break; case EVENT_STAMODE_GOT_IP://连接上路由器,并获取了IP
dbg_printf("\n\tGOT_IP\n"); dbg_printf("\tIP:" IPSTR ",Mask:" IPSTR ",GW:" IPSTR "\n",
IP2STR(&evt->event_info.got_ip.ip),
IP2STR(&evt->event_info.got_ip.mask),
IP2STR(&evt->event_info.got_ip.gw)); if(public_timer_state == )//正常运行下连接的路由器
{
TcpClient = tcp_new();//创建TCP,咱需要这个
IP4_ADDR(&addr,,,,);//设置连接的IP地址
tcp_connect(TcpClient, &addr,, TcpConnected);//连接
} break; case EVENT_STAMODE_DHCP_TIMEOUT://连接上路由器,但是路由器给WIFI模块分配IP等信息超时了
dbg_printf("\n\tSTAMODE_DHCP_TIMEOUT\n");
break; case EVENT_SOFTAPMODE_STACONNECTED://AP模式下,有设备连接WIFI模块的无线
dbg_printf("\n\tSOFTAPMODE_STACONNECTED\n"); dbg_printf("\tStation: " MACSTR "join, AID = %d\n",
MAC2STR(evt->event_info.sta_connected.mac),
evt->event_info.sta_connected.aid);
break; case EVENT_SOFTAPMODE_STADISCONNECTED://AP模式下,有设备断开和WIFI模块的无线连接
dbg_printf("\n\tSOFTAPMODE_STADISCONNECTED\n"); dbg_printf("\tstation: " MACSTR "leave, AID = %d\n",
MAC2STR(evt->event_info.sta_disconnected.mac),
evt->event_info.sta_disconnected.aid);
break; case EVENT_SOFTAPMODE_PROBEREQRECVED://这是啥??,,,信号强度改变了
dbg_printf("\n\tSOFTAPMODE_PROBEREQRECVED\n"); dbg_printf("Station PROBEREQ: " MACSTR " RSSI = %d\n",
MAC2STR(evt->event_info.ap_probereqrecved.mac),
evt->event_info.ap_probereqrecved.rssi);
break; default://其它错误
dbg_printf("\n\tswitch/case default\n");
break;
}
} //所有需要定时操作的函数在此函数中执行
LOCAL void ICACHE_FLASH_ATTR
public_timer_callback(void)
{
if(GPIO_INPUT_GET() == )//按键按下
{
public_timer_cnt++;
if(public_timer_cnt>= && public_timer_state==)//3S
{
dbg_printf("\nstartsmart\n");
public_timer_state=;
wifi_station_disconnect();
wifi_set_opmode(STATION_MODE);
smartconfig_set_type(SC_TYPE_ESPTOUCH_AIRKISS);//SmartConfig + AirKiss
xTaskCreate(smartconfig_task, "smartconfig_task", , NULL, , NULL);
}
}
else
{
if(public_timer_state!= && public_timer_cnt> && public_timer_cnt<)//短按复位
{
dbg_printf("\nsystem_restart\n");
system_restart();//复位
}
public_timer_cnt=;
} switch(public_timer_state)
{
case :break;
case :
public_timer_out++;
public_timer_cnt1++;
if(public_timer_out>=)//60S
{
dbg_printf("\nsmartconfig_timeout\n");
system_restart();//复位
}
if(public_timer_cnt1>)//LED快闪
{
public_timer_cnt1=;
GPIO_OUTPUT_SET(, -GPIO_INPUT_GET());//LED快闪
}
break;
default:break;
}
} /******************************************************************************
* FunctionName : user_init
* Description : entry of user application, init user function here
* Parameters : none
* Returns : none
*******************************************************************************/
void user_init(void)
{
GPIO_OUTPUT_SET(, );
GPIO_OUTPUT_SET(, );//让两个灯初始的状态一样,GOIO2是反接的,0的时候是亮
GPIO_OUTPUT_SET(, );
uart_init_new();
printf("SDK version:%s\n", system_get_sdk_version()); wifi_set_opmode(STATIONAP_MODE);//配置WiFi的模式STATION + AP AP--连接WIFI自身的无线实现通信 STATION--wifi连接路由器,手机或者电脑也连接路由器,实现通信
soft_ap_Config.ssid_len = strlen(SSID);//热点名称长度,与你实际的名称长度一致就好
memcpy(soft_ap_Config.ssid,SSID,soft_ap_Config.ssid_len);//实际热点名称设置,可以根据你的需要来
memcpy(soft_ap_Config.password,PWD,strlen(PWD));//热点密码设置
soft_ap_Config.authmode = AUTH_WPA2_PSK;//加密模式
soft_ap_Config.channel = ;//信道,共支持1~13个信道
soft_ap_Config.max_connection = ;//最大连接数量,最大支持四个,默认四个 wifi_softap_set_config_current(&soft_ap_Config);//设置 Wi-Fi SoftAP 接口配置,不保存到 Flash
// wifi_softap_set_config(&soft_ap_Config);//设置 Wi-Fi SoftAP 接口配置,保存到 Flash
UartCallbackRegister(UartReadCallback);//把 UartReadCallback 函数地址传过去,在串口里面调用 os_timer_disarm(&public_timer);
os_timer_setfn(&public_timer, (os_timer_func_t *)public_timer_callback, NULL);
os_timer_arm(&public_timer, , );//10ms //设置连接的路由器,如果想直接测试不想配网,请去掉屏蔽
stationConf.bssid_set = ;
memcpy(stationConf.ssid,APssid,strlen(APssid));//路由器名称
memcpy(stationConf.password,APpassword,strlen(APpassword));//路由器密码
wifi_station_disconnect();
wifi_station_set_config(&stationConf); wifi_set_event_handler_cb(wifi_event_monitor_handle_event_cb);//监听WiFi状态改变 }

下载进去测试下

我先整体说完哈,最后说一下细节问题

现在呢加几个回调函数

lua里面封装了以后 ,所有的信息都记录在 ud那个结构体里面

tcp_arg()的第二个参数是ud

其实下面的每一个回调函数都有个参数,上面设置以后,传递给回调函数的参数就是ud了,lua做法是直接判断和控制ud的成员变量

可以随意看个回调

其实所有的链接信息都保存在ud里面,做这个程序的人需要 获取 和 操作 这个变量,所以需要把ud传给每一个回调函数.

咱呢不需要

所以

直接上源码吧!(实现的也是透传)

#include "esp_common.h"
#include "gpio.h"
#include "uart.h"
#include "esp_timer.h"
#include "hw_timer.h"
#include "pwm.h"
#include "data_dispose.h"
#include "espconn.h"
#include "esp_wifi.h"
#include "lwip/api.h" #include "crc.h"
#include "smart_config.h" #include "lwip/err.h"
#include "lwip/ip_addr.h"
#include "lwip/dns.h"
#include "lwip/igmp.h"
#include "lwip/tcp.h" LOCAL os_timer_t public_timer;//定时器
u32 public_timer_cnt=;//累加
u32 public_timer_state=;//状态
u32 public_timer_out=;//超时
u32 public_timer_cnt1=;//累加 extern u8 Usart1ReadBuff[Usart1ReadLen];//接收数据的数组
extern u32 Usart1ReadCnt;//串口1接收到的数据个数
extern u32 Usart1ReadCntCopy;//串口1接收到的数据个数拷贝
extern u8 Usart1ReadFlage;//串口1接收到一条完整数据 #define SSID "Learn8266" //无线名称
#define PWD "11223344" //密码
struct softap_config soft_ap_Config;//AP模式配置 //连接的路由器信息
#define APssid "qqqqq"
#define APpassword "11223344"
struct station_config stationConf; //TCP客户端
struct tcp_pcb *TcpClient;
ip_addr_t addr;//创建连接的服务器地址用 #define TcpReadLen 2048
unsigned char TcpRead[TcpReadLen]={};//接收数据缓存的数组,最大接收1024字节 ResolveData ResolveDataTest;//解析数据IEEE754
//uint32 pin_info_list[1][3]={PERIPHS_IO_MUX_GPIO5_U,FUNC_GPIO5,5};//配置GPIO5作为PWM输出
//int duty[1]={0};//高电平时间是0us /******************************************************************************
* FunctionName : user_rf_cal_sector_set
* Description : SDK just reversed 4 sectors, used for rf init data and paramters.
* We add this function to force users to set rf cal sector, since
* we don't know which sector is free in user's application.
* sector map for last several sectors : ABCCC
* A : rf cal
* B : rf init data
* C : sdk parameters
* Parameters : none
* Returns : rf cal sector
*******************************************************************************/
uint32 user_rf_cal_sector_set(void)
{
flash_size_map size_map = system_get_flash_size_map();
uint32 rf_cal_sec = ; switch (size_map) {
case FLASH_SIZE_4M_MAP_256_256:
rf_cal_sec = - ;
break; case FLASH_SIZE_8M_MAP_512_512:
rf_cal_sec = - ;
break; case FLASH_SIZE_16M_MAP_512_512:
case FLASH_SIZE_16M_MAP_1024_1024:
rf_cal_sec = - ;
break; case FLASH_SIZE_32M_MAP_512_512:
case FLASH_SIZE_32M_MAP_1024_1024:
rf_cal_sec = - ;
break; default:
rf_cal_sec = ;
break;
} return rf_cal_sec;
} //串口调用此函数就说明接收到了一条完整的数据,就可以去处理了
void UartReadCallback()
{
tcp_write(TcpClient, Usart1ReadBuff, Usart1ReadCntCopy, TCP_WRITE_FLAG_COPY);//存放到发送对列(默认延时一会组合起来所有数据再发送)
tcp_output(TcpClient);//立即发送
} //网络接收到数据
err_t TcpClientRecv(void *arg, struct tcp_pcb *tpcb,struct pbuf *p, err_t err)
{
int len = p->len;
int cnt = ;
tcp_recved(tpcb,len);//获取数据 if(len > TcpReadLen){//接收的数据大于了数组大小
len= TcpReadLen;
} memcpy(TcpRead,p->payload,len);//拷贝数据到数组 while(len--)
{
uart0_write_char(TcpRead[cnt]);//串口输出
cnt++;
}
pbuf_free(p);
return ERR_OK;
} //连接上服务器
err_t TcpConnected(void *arg, struct tcp_pcb *tpcb, err_t err)
{
if (TcpClient != tpcb || err != ERR_OK){
TcpClient = NULL;
dbg_printf("\nConnection aborted\n");
}
dbg_printf("\nTcpConnected\n");
return ERR_OK;
} //成功发送数据
err_t TcpClientSendOk(void *arg, struct tcp_pcb *tpcb,u16_t len)
{ return ERR_OK;
} //客户端有错误
void TcpClientErr(void *arg, err_t err)
{ } //监听WiFi状态改变
void wifi_event_monitor_handle_event_cb(System_Event_t *evt)
{
switch (evt->event_id)
{
case EVENT_STAMODE_CONNECTED://连接上路由器
dbg_printf("\n\tSTAMODE_CONNECTED\n"); dbg_printf("\tConnected to SSID %s, Channel %d\n",
evt->event_info.connected.ssid,
evt->event_info.connected.channel);
break; case EVENT_STAMODE_DISCONNECTED://和路由器断开
dbg_printf("\n\tSTAMODE_DISCONNECTED\n"); dbg_printf("\tDisconnect from SSID %s, reason %d\n",
evt->event_info.disconnected.ssid,
evt->event_info.disconnected.reason);
break; case EVENT_STAMODE_AUTHMODE_CHANGE://这个是 啥..
dbg_printf("\n\tSTAMODE_AUTHMODE_CHANGE\n"); dbg_printf("\tAuthmode: %u -> %u\n",
evt->event_info.auth_change.old_mode,
evt->event_info.auth_change.new_mode);
break; case EVENT_STAMODE_GOT_IP://连接上路由器,并获取了IP
dbg_printf("\n\tGOT_IP\n"); dbg_printf("\tIP:" IPSTR ",Mask:" IPSTR ",GW:" IPSTR "\n",
IP2STR(&evt->event_info.got_ip.ip),
IP2STR(&evt->event_info.got_ip.mask),
IP2STR(&evt->event_info.got_ip.gw)); if(public_timer_state == )//正常运行下连接的路由器
{
TcpClient = tcp_new();//创建TCP,咱需要这个
IP4_ADDR(&addr,,,,);//设置连接的IP地址 tcp_err(TcpClient, TcpClientErr);//有错误回调函数
tcp_recv(TcpClient, TcpClientRecv);//接收到数据回调函数
tcp_sent(TcpClient, TcpClientSendOk);//成功发送了数据回调函数 tcp_connect(TcpClient, &addr,, TcpConnected);//连接 } break; case EVENT_STAMODE_DHCP_TIMEOUT://连接上路由器,但是路由器给WIFI模块分配IP等信息超时了
dbg_printf("\n\tSTAMODE_DHCP_TIMEOUT\n");
break; case EVENT_SOFTAPMODE_STACONNECTED://AP模式下,有设备连接WIFI模块的无线
dbg_printf("\n\tSOFTAPMODE_STACONNECTED\n"); dbg_printf("\tStation: " MACSTR "join, AID = %d\n",
MAC2STR(evt->event_info.sta_connected.mac),
evt->event_info.sta_connected.aid);
break; case EVENT_SOFTAPMODE_STADISCONNECTED://AP模式下,有设备断开和WIFI模块的无线连接
dbg_printf("\n\tSOFTAPMODE_STADISCONNECTED\n"); dbg_printf("\tstation: " MACSTR "leave, AID = %d\n",
MAC2STR(evt->event_info.sta_disconnected.mac),
evt->event_info.sta_disconnected.aid);
break; case EVENT_SOFTAPMODE_PROBEREQRECVED://这是啥??,,,信号强度改变了
dbg_printf("\n\tSOFTAPMODE_PROBEREQRECVED\n"); dbg_printf("Station PROBEREQ: " MACSTR " RSSI = %d\n",
MAC2STR(evt->event_info.ap_probereqrecved.mac),
evt->event_info.ap_probereqrecved.rssi);
break; default://其它错误
dbg_printf("\n\tswitch/case default\n");
break;
}
} //所有需要定时操作的函数在此函数中执行
LOCAL void ICACHE_FLASH_ATTR
public_timer_callback(void)
{
if(GPIO_INPUT_GET() == )//按键按下
{
public_timer_cnt++;
if(public_timer_cnt>= && public_timer_state==)//3S
{
dbg_printf("\nstartsmart\n");
public_timer_state=;
wifi_station_disconnect();
wifi_set_opmode(STATION_MODE);
smartconfig_set_type(SC_TYPE_ESPTOUCH_AIRKISS);//SmartConfig + AirKiss
xTaskCreate(smartconfig_task, "smartconfig_task", , NULL, , NULL);
}
}
else
{
if(public_timer_state!= && public_timer_cnt> && public_timer_cnt<)//短按复位
{
dbg_printf("\nsystem_restart\n");
system_restart();//复位
}
public_timer_cnt=;
} switch(public_timer_state)
{
case :break;
case :
public_timer_out++;
public_timer_cnt1++;
if(public_timer_out>=)//60S
{
dbg_printf("\nsmartconfig_timeout\n");
system_restart();//复位
}
if(public_timer_cnt1>)//LED快闪
{
public_timer_cnt1=;
GPIO_OUTPUT_SET(, -GPIO_INPUT_GET());//LED快闪
}
break;
default:break;
}
} /******************************************************************************
* FunctionName : user_init
* Description : entry of user application, init user function here
* Parameters : none
* Returns : none
*******************************************************************************/
void user_init(void)
{
GPIO_OUTPUT_SET(, );
GPIO_OUTPUT_SET(, );//让两个灯初始的状态一样,GOIO2是反接的,0的时候是亮
GPIO_OUTPUT_SET(, );
uart_init_new();
printf("SDK version:%s\n", system_get_sdk_version()); wifi_set_opmode(STATIONAP_MODE);//配置WiFi的模式STATION + AP AP--连接WIFI自身的无线实现通信 STATION--wifi连接路由器,手机或者电脑也连接路由器,实现通信
soft_ap_Config.ssid_len = strlen(SSID);//热点名称长度,与你实际的名称长度一致就好
memcpy(soft_ap_Config.ssid,SSID,soft_ap_Config.ssid_len);//实际热点名称设置,可以根据你的需要来
memcpy(soft_ap_Config.password,PWD,strlen(PWD));//热点密码设置
soft_ap_Config.authmode = AUTH_WPA2_PSK;//加密模式
soft_ap_Config.channel = ;//信道,共支持1~13个信道
soft_ap_Config.max_connection = ;//最大连接数量,最大支持四个,默认四个 wifi_softap_set_config_current(&soft_ap_Config);//设置 Wi-Fi SoftAP 接口配置,不保存到 Flash
// wifi_softap_set_config(&soft_ap_Config);//设置 Wi-Fi SoftAP 接口配置,保存到 Flash
UartCallbackRegister(UartReadCallback);//把 UartReadCallback 函数地址传过去,在串口里面调用 os_timer_disarm(&public_timer);
os_timer_setfn(&public_timer, (os_timer_func_t *)public_timer_callback, NULL);
os_timer_arm(&public_timer, , );//10ms //设置连接的路由器,如果想直接测试不想配网,请去掉屏蔽
stationConf.bssid_set = ;
memcpy(stationConf.ssid,APssid,strlen(APssid));//路由器名称
memcpy(stationConf.password,APpassword,strlen(APpassword));//路由器密码
wifi_station_disconnect();
wifi_station_set_config(&stationConf); wifi_set_event_handler_cb(wifi_event_monitor_handle_event_cb);//监听WiFi状态改变 }

测试:

注:

这些回调函数的参数需要根据它内部规定的写,我只说一个

所以

其它的就是固定形式了,就是要那样做....

这节只当做个入门,只是简简单单的,下节接着优化,需要做上自动重连.

其实感觉挺有成就感的

29-ESP8266 SDK开发基础入门篇--编写TCP 客户端程序(Lwip RAW模式,非RTOS版,精简入门)的更多相关文章

  1. 19-ESP8266 SDK开发基础入门篇--C# TCP客户端编写 , 连接和断开

    https://www.cnblogs.com/yangfengwu/p/11130428.html 渐渐的看过去,,,好多节了... 这节做一个C# TCP客户端 新建项目啥子的就不详细截图写了,自 ...

  2. 24-ESP8266 SDK开发基础入门篇--Android TCP客户端.控制 Wi-Fi输出PWM的占空比,调节LED亮度

    https://www.cnblogs.com/yangfengwu/p/11204436.html 刚才有人说需要点鸡汤.... 我想想哈;我还没问关于哪方面的鸡汤呢!!! 我所一直走的路线 第一: ...

  3. 20-ESP8266 SDK开发基础入门篇--C# TCP客户端编写 , 加入数据通信

    https://www.cnblogs.com/yangfengwu/p/11192594.html 自行调整页面 连接上以后主动发个数据 namespace TCPClient { public p ...

  4. 21-ESP8266 SDK开发基础入门篇--C# TCP客户端 , 控制LED亮灭

    https://www.cnblogs.com/yangfengwu/p/11192603.html 由于是台式机,,没有插无线网卡...所以呢我就用调试助手监控下数据 后期让WIFI连接路由器的时候 ...

  5. C# Xamarin移动开发基础进修篇

    一.课程介绍 英文原文:C# is the best language for mobile app development. Anything you can do in Objective-C, ...

  6. 初识Modbus TCP/IP-------------C#编写Modbus TCP客户端程序(一)

    转自:http://blog.csdn.net/thebestleo/article/details/52269999 首先我要说明一下,本人新手一枚,本文仅为同样热爱学习的同学提供参考,有不 对的地 ...

  7. 28-ESP8266 SDK开发基础入门篇--编写wifi模块TCP 客户端程序(官方API版,非RTOS版)

    https://www.cnblogs.com/yangfengwu/p/11432795.html 注:这节实现的功能是WIFI模块作为TCP 客户端,连接咱的TCP服务器,然后实现透传 本来想着做 ...

  8. 1-ESP8266 SDK开发基础入门篇--开发环境搭建

    因为今天终于做好了自己的另一块工控板,所以我就开始写基础公开篇的内容,希望自己小小的努力能够帮到大家 自己做的另一块板子 https://www.cnblogs.com/yangfengwu/cate ...

  9. 25-ESP8266 SDK开发基础入门篇--控制WIFI连接路由器

    https://www.cnblogs.com/yangfengwu/p/11324411.html 说个事情,现在SDK的版本已经出到3.0了,但是我还是使用2.0 如果只是为了学习研究   选择3 ...

随机推荐

  1. git如何支持doc文档

    这个问题很容易解决,只要添加一个 .gitattributes 内容如下: ////////////////////////////////////////////////////////////// ...

  2. The five Day 水平翻转图像,然后反转图像并返回结果

    """ 给定一个二进制矩阵 A,我们想先水平翻转图像,然后反转图像并返回结果. 水平翻转图片就是将图片的每一行都进行翻转,即逆序.例如,水平翻转 [1, 1, 0] 的结 ...

  3. 小程序canvas绘制base64数据格式图片

    翻了微信小程序官方文档,看了看画板drawImage的用法,官方对所要绘制的图片资源路径并没有很详细,模棱两可,没说支持什么格式的路径.今天我就试一下支不支持base64格式的图片 随便找张图片从网上 ...

  4. Oracle数据库 常用的触发器命令

    创建自增序列,创建触发器(在触发时间中操纵序列,实现主键自增): Oracle数据库不支持自增方法 create sequence seq_userInfo_usid start with ;--创建 ...

  5. 防止用户重复提交表单数据,session方式,js方式

    1. 使用session的方式创建Token令牌解决 创建一个生成令牌的工具类,在该类中有返回类的对象,生成token的方法 public class TokenUtil { /* *单例设计模式(保 ...

  6. vue辅助函数mapStates与mapGetters

    状态管理器 <!-- store.js: --> import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export de ...

  7. 想知道使用OPC服务器时如何设置DCOM?看完本文就懂了(下)

    接上文...... “安全”选项卡“安全”选项卡上,有3个选项需要设置. 启动权限 选择“使用默认值”选项 访问权限 选择“使用默认值”选项 配置权限 选择“自定义”选项,然后单击“编辑” 将打开一个 ...

  8. 常见数据结构的 Python 实现(建议收藏)

    数据结构作为计算机基础的必修内容,也是很多大型互联网企业面试的必考题.可想而知,它在计算机领域的重要性. 然而很多计算机专业的同学,都仅仅是了解数据结构的相关理论,却无法用代码实现各种数据结构. 今日 ...

  9. composer的用法笔记

    一.到compose官网下载 composer.exe 的安装的文件,直接打开安装,在安装的目录的要选择到,你的开发环境中的 php.exe 的所在目录里..例如:D:\phpStudy\php\ph ...

  10. Jenkins服务器的安装

    Jenkins服务器的安装 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.安装jdk 详情请参考:https://www.cnblogs.com/yinzhengjie/p/1 ...