文章介绍了ESP8266的特性以及连网模式(AP,station),使用串口(USART)接入STM32,实现连网功能。
esp8266 内置超低功耗 Tensilica L106 32 位 RISC 处理器,CPU 时钟速度最高可达 160 MHz,支持实时操作系统 (RTOS) 和 Wi-Fi 协议栈。标准数字外设接口、天线开关、射频 balun、功率放大器、低噪放大器、过滤器和电源管理模块等。低功耗
无线参数 | 值 |
---|---|
无线标准 | 802.11 b/g/n |
频率范围 | 2.4G-2.5G(2400M-2483.5M) |
发射功率 | 802.11 b: 20 dBm;802.11 g: 17 dBm;802.11 n: 14 dBm |
接收灵敏度 | 802.11 b: (11Mbps) -91db;802.11 g: (54Mbps) -75db;802.11 n: (MCS7) -72db |
硬件参数 | 值 |
---|---|
数据接口 | UART、PWM、 GPIO |
工作电压 | 3.3V |
工作电流 | 平均电流 80mA |
工作温度 | -40° ~125° |
软件参数 | 值 |
---|---|
无线网络模式 | station/softAP/SoftAP+station |
安全机制 | WPA/WPA2 |
加密类型 | WEP/TKIP/AES |
UART成帧
ESP8266 判断 UART 传来的数据时间间隔,若时间间隔大于 20ms, 则认为一帧结束;否则, 一直接收数据到上限值 2KB, 认为一帧结束。 ESP8266 模块判断UART 来的数据一帧结束后, 通过 WIFI 接口将数据转发出去。
成帧时间间隔为 20ms, 一帧上限值为 2KB。
ESP8266 支持 softAP 模式, station 模式, softAP + station 共存模式三种。
SoftAP: 即无线接入点, 是一个无线网络的中心节点,类似于无线路由器。手机 用户设备、 其他 ESP8266 station 接口等均可以作为 station 连入ESP8266, 组建成一个局域网。(透传)
Station:即无线终端, 是一个无线网络的终端。
通过连接路由器(AP) 连入 internet ,可向云端服务器上传、 下载数据。用户可随时使用移动终端(手机、 笔记本等) ,通过云端连接ESP8266。
网络相关的模块,比如4G、lora等模块都有AT指令,使用AT指令配置模块,ESP8266的AT指令如下
分类 | 指令格式 | 指令功能 |
---|---|---|
测试命令 | AT+=? | 该命令用于查询设置命令或内部程序设置的 |
查询命令 | AT+? | 该命令用于返回参数的当前值 |
设置命令 | AT+=<…> | 该命令用于设置用户自定义的参数值 |
执行命令 | AT+ | 该命令用于执行受模块内部程序控制的变参 |
基础指令
命令 | 说明 |
---|---|
AT | 测试 AT 启动 |
AT+RST | 重启模块 |
AT+GMR | 查看版本信息 |
wifi 功能指令
命令 | 说明 |
---|---|
AT+CWMODE | 选择 WIFI 应用模式 |
AT+CWJAP | 加入 AP |
AT+CWLAP | 列出当前可用 AP |
AT+CWQAP | 退出与 AP 的连接 |
AT+CWSAP | 设置 AP 模式下的参数 |
AT+ CWLIF | 查看已接入设备的 IP |
TCP/IP 指令
命令 | 说明 |
---|---|
AT+CIPSTATUS | 获得连接状态 |
AT+CIPSTART | 建立 TCP 连接或注册 UDP 端口号 |
AT+CIPSEND | 发送数据 |
AT+CIPCLOSE | 关闭 TCP 或 UDP |
AT+CIFSR | 获取本地 IP 地址 |
AT+CIPMUX | 启动多连接 |
AT+CIPSERVER | 配置为服务器 |
AT+CIPMODE | 设置模块传输模式 |
AT+CIPSTO | 设置服务器超时时间 |
RST复位引脚,与CH_PD片选引脚,在模式初始化阶段使用。RST拉高,CH_PD先复位 再置位,模块正常工作。采用串口方式与STM32进行通信,使用串口中断,有数据时,去读取数据。
// CH_PD引脚
// Enables or disables the High Speed APB (APB2) peripheral clock
#define macESP8266_CH_PD_APBxClock_FUN RCC_APB2PeriphClockCmd
//RCC_APB2Periph: specifies the APB2 peripheral to gates its clock
#define macESP8266_CH_PD_CLK RCC_APB2Periph_GPIOB
//PORT
#define macESP8266_CH_PD_PORT GPIOB
//PIN
#define macESP8266_CH_PD_PIN GPIO_Pin_8
RST引脚
#define macESP8266_RST_APBxClock_FUN RCC_APB2PeriphClockCmd
#define macESP8266_RST_CLK RCC_APB2Periph_GPIOB
#define macESP8266_RST_PORT GPIOB
#define macESP8266_RST_PIN GPIO_Pin_9
//
static void ESP8266_GPIO_Config ( void )
{
GPIO_InitTypeDef GPIO_InitStructure;
macESP8266_CH_PD_APBxClock_FUN ( macESP8266_CH_PD_CLK, ENABLE );
//CH_PD引脚
GPIO_InitStructure.GPIO_Pin = macESP8266_CH_PD_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init ( macESP8266_CH_PD_PORT, & GPIO_InitStructure );
//RST引脚
macESP8266_RST_APBxClock_FUN ( macESP8266_RST_CLK, ENABLE );
GPIO_InitStructure.GPIO_Pin = macESP8266_RST_PIN;
GPIO_Init ( macESP8266_RST_PORT, & GPIO_InitStructure );
}
#define macESP8266_USART_BAUD_RATE 115200
#define macESP8266_USARTx USART3
#define macESP8266_USART_APBxClock_FUN RCC_APB1PeriphClockCmd
#define macESP8266_USART_CLK RCC_APB1Periph_USART3
#define macESP8266_USART_GPIO_APBxClock_FUN RCC_APB2PeriphClockCmd
#define macESP8266_USART_GPIO_CLK RCC_APB2Periph_GPIOB
//发送TX
#define macESP8266_USART_TX_PORT GPIOB
#define macESP8266_USART_TX_PIN GPIO_Pin_10
//接受RX
#define macESP8266_USART_RX_PORT GPIOB
#define macESP8266_USART_RX_PIN GPIO_Pin_11
//中断
#define macESP8266_USART_IRQ USART3_IRQn
#define macESP8266_USART_INT_FUN USART3_IRQHandler
extern struct STRUCT_USARTx_Fram //´¿ÚÊý¾ÝÖ¡µÄ´¦Àí½á¹¹Ìå
{
char Data_RX_BUF [ RX_BUF_MAX_LEN ];
union {
__IO u16 InfAll;
struct {
__IO u16 FramLength :15; // 14:0
__IO u16 FramFinishFlag :1; // 15
} InfBit;
};
} strEsp8266_Fram_Record;
struct STRUCT_USARTx_Fram strEsp8266_Fram_Record = {
0 };
//USART 的 NVIC中断
static void ESP8266_USART_NVIC_Configuration ( void )
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure the NVIC Preemption Priority Bits */
NVIC_PriorityGroupConfig ( macNVIC_PriorityGroup_x );
/* Enable the USART3 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = macESP8266_USART_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
static void ESP8266_USART_Config ( void )
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
/* config USART clock */
macESP8266_USART_APBxClock_FUN ( macESP8266_USART_CLK, ENABLE );
macESP8266_USART_GPIO_APBxClock_FUN ( macESP8266_USART_GPIO_CLK, ENABLE );
/* USART GPIO config */
/* Configure USART Tx as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = macESP8266_USART_TX_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(macESP8266_USART_TX_PORT, &GPIO_InitStructure);
/* Configure USART Rx as input floating */
GPIO_InitStructure.GPIO_Pin = macESP8266_USART_RX_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(macESP8266_USART_RX_PORT, &GPIO_InitStructure);
/* USART1 mode config */
USART_InitStructure.USART_BaudRate = macESP8266_USART_BAUD_RATE;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
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(macESP8266_USARTx, &USART_InitStructure);
/* 中断配置 */
USART_ITConfig ( macESP8266_USARTx, USART_IT_RXNE, ENABLE ); //使能串口接收中断
USART_ITConfig ( macESP8266_USARTx, USART_IT_IDLE, ENABLE ); //使能串口空闲中断
ESP8266_USART_NVIC_Configuration ();
USART_Cmd(macESP8266_USARTx, ENABLE);
}
void macESP8266_USART_INT_FUN ( void )
{
uint8_t ucCh;
//获取RX中断状态
if ( USART_GetITStatus ( macESP8266_USARTx, USART_IT_RXNE ) != RESET )
{
ucCh = USART_ReceiveData( macESP8266_USARTx );//接收数据
if ( strEsp8266_Fram_Record .InfBit .FramLength < ( RX_BUF_MAX_LEN - 1 ) ) //长度判断
//向BUF缓冲区中写入数据ucCh,FramLength 在不断增加
strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ++ ] = ucCh;
}
//获取IDEL中断状态 ,数据帧接收完毕
if ( USART_GetITStatus( macESP8266_USARTx, USART_IT_IDLE ) == SET )
{
strEsp8266_Fram_Record .InfBit .FramFinishFlag = 1;//条件置位
ucCh = USART_ReceiveData( macESP8266_USARTx );
ucTcpClosedFlag = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "CLOSED\r\n" ) ? 1 : 0;
}
}
ESP8266的一般使用顺序,ESP8266连接当前环境的热点,与服务器建立TCP连接,传输数据。
AT+CWMODE=1:设置工作模式(STA模式)
AT+RST:模块重启(生效工作模式)
AT+CWJAP=“111”,“11111111”:连接当前环境的WIFI热点(热点名,密码)
AT+CIPMUX=0:设置单路连接模式
AT+CIPSTART=“TCP”,“xxx.xxx.xxx.xxx”,xxxx:建立TCP连接
AT+CIPMODE=1:开启透传模式
AT+CIPSEND:透传模式下,传输数据
+++:退出透传模式
程序的主处理流程
void ESP8266_StaTcpClient_UnvarnishTest ( void )
{
uint8_t ucStatus;
char cStr [ 100 ] = {
0 };
//使能PD_CH
macESP8266_CH_ENABLE();
//AT测试
ESP8266_AT_Test ();
//选择网络模式
ESP8266_Net_Mode_Choose ( STA );
//连接AP
while ( ! ESP8266_JoinAP ( macUser_ESP8266_ApSsid, macUser_ESP8266_ApPwd ) );
//启动多连接关闭
ESP8266_Enable_MultipleId ( DISABLE );
//连接服务器IP 端口号
while ( ! ESP8266_Link_Server ( enumTCP, macUser_ESP8266_TcpServer_IP, macUser_ESP8266_TcpServer_Port, Single_ID_0 ) );
//设置模式进入透传模式
while ( ! ESP8266_UnvarnishSend () );
while ( 1 )//进入循环
{
//此处可以修改数据源,此处为一串字符串,也可以是从开发版上获取传感器数据,比如温湿度传感器
sprintf ( cStr,"ABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n" );
ESP8266_SendString ( ENABLE, cStr, 0, Single_ID_0 ); //发送数据
Delay_ms ( 100 );
if ( ucTcpClosedFlag ) //检测是否丢失链接
{
ESP8266_ExitUnvarnishSend (); //如果丢失,退出透传模式
do ucStatus = ESP8266_Get_LinkStatus (); //获取链接状态
while ( ! ucStatus );
if ( ucStatus == 4 ) //失去链接后重连
{
while ( ! ESP8266_JoinAP ( macUser_ESP8266_ApSsid, macUser_ESP8266_ApPwd ) );
while ( !ESP8266_Link_Server ( enumTCP, macUser_ESP8266_TcpServer_IP, macUser_ESP8266_TcpServer_Port, Single_ID_0 ) );
}
while ( ! ESP8266_UnvarnishSend () );
}
}
发送AT指令函数
/*
cmd:待发送的命令,
reply1,reply2期待的回复
waittime 等待时间
*/
bool ESP8266_Cmd ( char * cmd, char * reply1, char * reply2, u32 waittime )
{
strEsp8266_Fram_Record .InfBit .FramLength = 0; //数据长度置零
macESP8266_Usart ( "%s\r\n", cmd );
if ( ( reply1 == 0 ) && ( reply2 == 0 ) ) //没有收到数据
return true;
Delay_ms ( waittime ); //延时函数
//中断接收函数
strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ] = '\0';
macPC_Usart ( "%s", strEsp8266_Fram_Record .Data_RX_BUF );
if ( ( reply1 != 0 ) && ( reply2 != 0 ) )
return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply1 ) ||
( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply2 ) );
else if ( reply1 != 0 )
return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply1 ) );
else
return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply2 ) );
}
选择NET模式
bool ESP8266_Net_Mode_Choose ( ENUM_Net_ModeTypeDef enumMode )
{
switch ( enumMode )
{
case STA:
return ESP8266_Cmd ( "AT+CWMODE=1", "OK", "no change", 2500 );
case AP:
return ESP8266_Cmd ( "AT+CWMODE=2", "OK", "no change", 2500 );
case STA_AP:
return ESP8266_Cmd ( "AT+CWMODE=3", "OK", "no change", 2500 );
default:
return false;
}
}
链接wifi, AT+CWJAP
/*
pSSID用户名
pPassWord 密码
*/
bool ESP8266_JoinAP ( char * pSSID, char * pPassWord )
{
char cCmd [120];
sprintf ( cCmd, "AT+CWJAP=\"%s\",\"%s\"", pSSID, pPassWord );
return ESP8266_Cmd ( cCmd, "OK", NULL, 5000 );
}
连接外部服务器 AT+CIPSTART
bool ESP8266_Link_Server ( ENUM_NetPro_TypeDef enumE, char * ip, char * ComNum, ENUM_ID_NO_TypeDef id)
{
char cStr [100] = {
0 }, cCmd [120];
switch ( enumE )
{
case enumTCP:
sprintf ( cStr, "\"%s\",\"%s\",%s", "TCP", ip, ComNum );
break;
case enumUDP:
sprintf ( cStr, "\"%s\",\"%s\",%s", "UDP", ip, ComNum );
break;
default:
break;
}
if ( id < 5 )
sprintf ( cCmd, "AT+CIPSTART=%d,%s", id, cStr);
else
sprintf ( cCmd, "AT+CIPSTART=%s", cStr );
return ESP8266_Cmd ( cCmd, "OK", "ALREAY CONNECT", 4000 );
}
获取链接状态AT+CIPSTATUS
uint8_t ESP8266_Get_LinkStatus ( void )
{
if ( ESP8266_Cmd ( "AT+CIPSTATUS", "OK", 0, 500 ) )
{
if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:2\r\n" ) )
return 2;
else if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:3\r\n" ) )
return 3;
else if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:4\r\n" ) )
return 4;
}
return 0;
}
发送数据"AT+CIPSEND=
/*
返回值
1,发送成功
0,发送失败
*/
bool ESP8266_SendString ( FunctionalState enumEnUnvarnishTx, char * pStr, u32 ulStrLength, ENUM_ID_NO_TypeDef ucId )
{
char cStr [20];
bool bRet = false;
if ( enumEnUnvarnishTx )
{
macESP8266_Usart ( "%s", pStr );
bRet = true;
}
else
{
if ( ucId < 5 )
sprintf ( cStr, "AT+CIPSEND=%d,%d", ucId, ulStrLength + 2 );
else
sprintf ( cStr, "AT+CIPSEND=%d", ulStrLength + 2 );
ESP8266_Cmd ( cStr, "> ", 0, 1000 );
bRet = ESP8266_Cmd ( pStr, "SEND OK", 0, 1000 );
}
return bRet;
}
主函数
void ESP8266_Init ( void )
{
ESP8266_GPIO_Config ();
ESP8266_USART_Config ();
macESP8266_RST_HIGH_LEVEL();
macESP8266_CH_DISABLE();
}
int main ( void )
{
USARTx_Config ();//串口打印函数
SysTick_Init ();//系统时钟初始化
ESP8266_Init ();//esp8266初始化
ESP8266_StaTcpClient_UnvarnishTest ();
while ( 1 );
}
实验现象
通过网络助手,收到开发版发来的数据
模块作为AP的配置
ESP8266_AT_Test ();
ESP8266_Net_Mode_Choose ( AP );
//设置模块的IP
while ( ! ESP8266_CIPAP ( macUser_ESP8266_TcpServer_IP ) );
//创建模块热点
while ( ! ESP8266_BuildAP ( macUser_ESP8266_BulitApSsid, macUser_ESP8266_BulitApPwd, macUser_ESP8266_BulitApEcn ) );
//模块启动多连接
ESP8266_Enable_MultipleId ( ENABLE );
//模块开启或关闭服务器
while ( ! ESP8266_StartOrShutServer ( ENABLE, macUser_ESP8266_TcpServer_Port, macUser_ESP8266_TcpServer_OverTime ) );
//ESP8266 获取 AP IP
ESP8266_Inquire_ApIp ( cStr, 20 );
参考
《ESP8266_用户手册_V0.3.pdf》
《ESP8266 Non-OS SDK AT 指令集.pdf》
《野火YH-ESP8266模块用户手册.pdf》
《野火提供的esp8266源码》
文章浏览阅读307次。ASP.NET MVC 是一个全新的Web应用框架ASP.NET 代表支撑应用框架的技术平台,表明ASP.NET MVC和传统的WebForm应用框架一样,都是建立在ASP.NET平台之上。MVC 表示该框架背后的设计思想,意味着ASP.NET MVC采用了MVC架构模式。MVC在20世纪70年代后期出现,产生于Xerox PARC施乐公司的帕洛阿尔托研究中心的Small..._aspnet mvvm
文章浏览阅读350次。解压压缩包后,打开终端,进入当前chromedriver所在的路径,将chromedriver移动到默认路径(/usr/local/bin/)二、下载对应版本的浏览器驱动器:找到版本一致或最接近的版本的驱动器。若列表中含有selenium则表明安装成功。记得勾选上继承全局包,要不然会报错。_m1 mac selenium配置
文章浏览阅读4.6k次。谨以此片献给各种遇到坑的朋友。官网上的OpenCV 插件,根据github 上的描述 是针对UE4 4.16 版本以下的版本来提供的 OpenCV 采用的是3.0.0 , 也可以使用openCv 3.2.0环境描述:Ue4 4.15 OpenCV 3.2.0固有插件配置步骤:1, 创建一个C++ 的工程,打开后, 关闭即可。2,将OpenCV 的插件文件 解压缩之后, 将里面的文件..._ue4 opencv操作texture
文章浏览阅读1w次,点赞3次,收藏11次。直接在cmd命令行输入:conda install --channel https://conda.anaconda.org/menpo opencv3 接着根据提示按Y即可
文章浏览阅读646次。#include#includestruct mubang{int x;int y;}a[5005];int cmp(const void *a,const void *b){struct mubang *c=(struct mubang *)a;struct mubang *d=(struct mubang *)b;if(c->x!=d->x)re_nyoj 心急的c小加
文章浏览阅读1.7k次。学习JavaEE的你们是不是一头雾水呢? C/S client/server 客户端/服务器 B/C browser/server 浏览器/服务器 通过浏览器访问到对应页面,发送请求(同步请求,异步请求,ajax请求,会读接口文档)---服务器(云服务器:腾讯云服务器 阿里云服务器等等)---应用服务器Tomcat---匹配servlet---service业务处理---dao层 JDBC Hibemate,ORM---数据库---File---servlet(控制器Controller)MVC_javaee基础知识
文章浏览阅读910次,点赞28次,收藏19次。交互性检索是在检索用户不能构建良好的检索式(关键词)的情况下,通过与检索平台交流互动并不断修改检索式,从而获得较准确检索结果的过程。新闻推荐需要:获取用户请求,召回候选新闻,对候选新闻进行排序,最终给用户推出新闻。将用户持续浏览新闻的推荐过程看成一个决策过程,通过强化学习学习每一次推荐的最佳策略,提高用户的点击率。无人驾驶被认为是强化学习短期内能技术落地的一个应用方向,很多公司投入大量资源在无人驾驶上,其中百度的无人巴士“阿波龙”已经在北京、武汉等地展开试运营,自动无人驾驶的行车视野如下图所示。
文章浏览阅读3.5w次,点赞102次,收藏685次。简历是什么找工作之前投递的个人信息和工作能力----不全面应该是:个人当前阶段的价值体现前者:我能卖多少钱;后者:我现在值多少钱建议:每隔半年/一年给自己做总结的时候写一份简历(相当于个人价值总结)面试要刻意、精心准备公司内部晋升答辩,需要精心准备(ppt、演讲基本要精心准备一个月的时间)面试,简历,同样需要精心准备目录面试官如何分析一份简历简历模板和内容个人信息教育经历专业技能工作经历项目经历体现自己的亮点课程总结注意:不要造假学历造假:学信网可查工作经历造假:可_前端简历
文章浏览阅读2.6k次。https://www.dwhd.org/20160724_085212.html_有gcc高版本的yum库
文章浏览阅读320次。1起步依赖原理分析 1.1分析spring-boot-starter-parent 按住Ctrl点击pom.xml中的spring-boot-starter-parent,跳转到了spring-boot-starter-parent的pom.xml,xml配置如下(只摘抄了部分重点配置):<parent> <groupId>org.sp..._springboot 自动配置分析与整合测试
文章浏览阅读9.1k次。最近想要使用Crypto.Cipher 的AES模块,可总是找不到Crypto.Cipher接下来介绍几个坑1.AES是在pyCrypto中而不是crypto中2.这个pyCrypto中间的C一定要大写,不然也不能用接下来介绍正确的安装姿势1.首先需要现在一款编译器Microsoft Visual C++ Compiler for Python 2.7下载地址https://www.m..._python2.7 使用pycrypto
文章浏览阅读2.9k次,点赞4次,收藏7次。递归算法:将正整数n表示成一系列正整数之和,n=n1+n2+...+nk,其中n1>=n2>=n3>=...>=nk>=1,k>=1。正整数n的这种表示称为正整数n的划分。正整数n的不同的划分个数城外正整数n的划分数,记作p(n)。例如,正整数6有如下11种不同的划分,所以p(6)=11。6;5+1;4+2;4+1+1;3+3;3+2+1;3+1+1+1;2+2+2_n的划分种数,其中划分大于等于2非递归算法