0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

ESP8266无线通讯模块的驱动设计与实现

CHANBAEK 来源:木南创智 作者:尹家军 2022-12-08 14:31 次阅读

我们的物联网产品所使用的平台都支持无线通讯,而且无线通讯本身更的成本较低,受到大家的欢迎。在本篇文章中,我们将详细讨论并实现ESP8266无线通讯模块的驱动。

1 、功能概述

ESP8266是由乐鑫公司出品的一款物联网芯片,因为价格较低,性能稳定等收到很大关注。

该芯片可工作于三种WIFI模式下,分别是:station模式,AP模式以及混合模式,通过AT指令进行控制,显影的指令格式为:AT+CWMODE=mode。mode的取值决定设定的模式:

当mode为1时,ESP8266工作于station 模式:ESP8266 模块通过路由器连接互联网,手机电脑通过互联网实现对设备的远程控制。

当mode为2时,ESP8266工作于softAP 模式:ESP8266 模块作为热点,手机或电脑直接与模块连接,实现局域网无线控制。

当mode为3时,ESP8266工作于softAP + station模式:两种模式的共存模式,即可以通过互联网控制可实现无缝切换,方便操作。

ESP8266拥有2种传输模式,即正常模式和透传模式。而传输模式的配置也是采用AT指令,具体格式为:AT+CIPMODE=mode。其中mode 取值0时,为普通传输模式;而mode 取值1时,为透传模式,仅支持TCP单连接和 UDP固定通信对端的情况。在正常模式下,每次发送数据前都必须先发送指令AT+CIPSEND=param。而在透传模式下,我们就不需要在每次发送数据前都发送指令AT+CIPSEND=param了,只需要发送一次AT+CIPSEND,之后发送的所有内容全部当成是数据了。但这又存在一个问题,我们想要发送命令该如何呢?那么就需要发送数据"+++"来退出透传模式。

ESP8266有几种不同的使用方式,最为常见的就是使用AT指令进行操作。ESP8266的AT指令分为基础AT指令、WiFi功能AT指令和TCP/IP相关AT指令3个方面。这些指令从使用功能上讲可分为4类:

Dingtalk_20221206154648.jpg

按照相应的格式发送不同的AT指令就可以实现ESP8266的数据通讯了。

2 、驱动设计与实现

ESP8266无线通讯模块是常用的通讯模块,我们已经描述了其功能及通讯方式,接下来我们将设计并实现其驱动程序。

2.1 、对象定义

在使用一个对象之前我们需要获得一个对象。同样的我们想要ESP8266无线通讯模块就需要先定义ESP8266无线通讯模块的对象。

2.1.1 、对象的抽象

我们要得到ESP8266无线通讯模块对象,需要先分析其基本特性。一般来说,一个对象至少包含两方面的特性:属性与操作。接下来我们就来从这两个方面思考一下ESP8266无线通讯模块的对象。

先来考虑属性,作为属性肯定是用于标识或记录对象特征的东西。我们来考虑ESP8266无线通讯模块对象属性。我们考虑到ESP8266的WIFI模式以及数据传输模式决定了其工作方式,在使用过程中有时我们也需要了解这两个模式的配置是什么,所以我们将其作为对象的属性已记录这两个模式配置。我们每一个ESP8266对象都需要接收数据,所以要有一个接受缓存区,我们定义了一个结构体变量来作为对象接收缓冲区。

接着我们还需要考虑ESP8266无线通讯模块对象的操作问题。我们想要使用ESP8266对象实现我们的功能,就需要发送命令或数据以及接收数据。串口接收数据我们一般使用中断方式,所以定义了缓冲区,不再需要特定的操作。串口发送消息需要实现,但这依赖于具体的硬件平台,所以我们将其作为对象的操作。此外,我们使用串口通讯时,需要控制时序就离不开延时函数,而延时操作一般都依赖于具体的软硬件平台,所以我们将延时函数作为对象的一个操作。

根据上述我们对ESP8266无线通讯模块的分析,我们可以定义ESP8266无线通讯模块的对象类型如下:

/*定义ESP8266对象*/
typedef struct Esp8266Object {
 Esp8266CWModeType cwMode;    //WIFI模式
 Esp8266CIPModeType cipMode;   //传输模式,正常或透传
 struct EspRxBuffer{
   uint8_t queue[Esp8266RxBufferLength];   //数据存储队列
   uint8_t lengthRecieving;               //正在接收的数据长度
   uint8_t lengthRecieved;                //已经接收的数据长度
 }rxBuffer;
 void (*SendData)(uint8_t *sData,uint16_t sSize);//数据发送函数指针
 void (*Delayms)(volatile uint32_t nTime);     //延时操作指针
}Esp8266ObjectObject;

2.1.2 、对象初始化

我们知道,一个对象仅作声明是不能使用的,我们需要先对其进行初始化,所以这里我们来考虑ESP8266无线通讯模块对象的初始化函数。一般来说,初始化函数需要处理几个方面的问题。一是检查输入参数是否合理;二是为对象的属性赋初值;三是对对象作必要的初始化配置。据此我们设计ESP8266无线通讯模块对象的初始化函数如下:

/*ESP8266对象初始化*/
voidEsp8266Initialization(Esp8266ObjectObject *esp,    //ESP8266对象
                   Esp8266CWModeTypecwMode,    //WIFI模式
                   Esp8266CIPModeTypecipMode,  //传输模式,正常或透传
                   char *wifiName,              //WIFI名称
                  char*wifiPassword,          //WIFI密码
                   ESP8266SendDataTypesend,    //发送函数指针
                   ESP8266DelaymsTypedelayms   //毫秒延时函数
                  )
{
 char cwjap[50];
 char cwsap[50];
 
 if((esp==NULL)||(send==NULL)||(delayms==NULL))
 {
   return;
 }
 esp->SendData=send;
 esp->Delayms=delayms;
 
 esp->cwMode=cwMode;
 esp->cipMode=cipMode;
 
 esp->rxBuffer.lengthRecieved=0;
 ClearReciveBuffer(esp);
 
 //设置工作模式 1:station模式   2:AP模式 3:兼容 AP+station模式
 if(Esp8266SendCommmand(esp,cwModeCmd[esp->cwMode],"OK",50)==Esp8266_TxFial)
 {
   return;
 }
 
 //让Wifi模块重启的命令
 if(Esp8266SendCommmand(esp,"AT+RST","OK",20)==Esp8266_TxFial)
 {
   return;
 }
 
 esp->Delayms(3000);         //延时3S等待重启成功
 
 if(esp->cwMode==Esp8266_StationMode)
 {
   sprintf(cwjap,"AT+CWJAP_CUR=\"%s\",\"%s\"\\r\\n",wifiName,wifiPassword);
   
   //让模块连接上自己的路由
   if(Esp8266SendCommmand(esp,cwjap,"OK",600)==Esp8266_TxFial)
   {
     return;
   }
   
   if(esp->cipMode==Esp8266_TransMode)
   {
     if(Esp8266EnterTrans(esp)==Esp8266_TxFial)
     {
       return;
     }
   }
   else
   {
     //=0:单路连接模式    =1:多路连接模式
     if(Esp8266SendCommmand(esp,"AT+CIPMUX=0\\r\\n","OK",20)==Esp8266_TxFial)
     {
       return;
     }
   }
 }
 else if(esp->cwMode==Esp8266_SoftAPMode)
 {
   sprintf(cwsap,"AT+CWSAP_CUR=\"%s\",\"%s\"\\r\\n",wifiName,wifiPassword);
   
   //设置模块的WIFI名和密码
   if(Esp8266SendCommmand(esp,cwsap,"OK",600)==Esp8266_TxFial)
   {
     return;
   }
 }
 else if(esp->cwMode==Esp8266_MixedMode)
 {
   //尚未使用,有待添加
 }
}

2.2 、对象操作

我们已经完成了ESP8266无线通讯模块对象类型的定义和对象初始化函数的设计。但我们的主要目标是获取对象的信息,接下来我们还要实现面向ESP8266无线通讯模块的各类操作。

对于ESP8266来说,发送命令主要是AT命令,这是与发送数据完全不同的操作,所以我们设计了一个专用于命令发送的操作函数。

/*ESP8266发送命令*/
static Esp8266TxStatusTypeEsp8266SendCommmand(Esp8266ObjectObject *esp,char *cmd,char *ack,uint16_ttimeOut)
{
 esp->SendData((unsigned char *)cmd, strlen((const char *)cmd));       //写命令到网络设备
 
 if(ack&&timeOut)
 {
   while(timeOut--)      //等待超时
   {
     if(ChecRecieveFinished(esp) == Esp8266_RxFinish)    //如果数据接收完成
     {
       if(strstr((const char *)esp->rxBuffer.queue,ack) != NULL)       //如果检索到关键词
       {
         ClearReciveBuffer(esp);
                           
         return Esp8266_RxSucceed;
       }
     }
             
     esp->Delayms(10);
   }
 }
 
 return Esp8266_TxFial;
}

而ESP8266在发送数据时,因发送模式的不同会有一定区别。在透传模式下只需要发送数据就好了。而在普通模式下,需要先发送AT命令再发送发送数据。所以我们可设计数据发送函数如下:

/*ESP8266发送数据*/
void Esp8266SendData(Esp8266ObjectObject*esp,uint8_t *sData,uint16_t sSize)
{
 if(esp->cipMode==Esp8266_TransMode)
 {
   esp->SendData(sData,sSize);
 }
 else
 {
   char cmd[32];
 
   esp->Delayms(50);
   ClearReciveBuffer(esp);
   sprintf(cmd,"AT+CIPSEND=%d\\r\\n",sSize);
   
   if(Esp8266SendCommmand(esp,cmd, ">",1)==Esp8266_RxSucceed)     //收到‘>’时可以发送数据
   {
     esp->SendData(sData,sSize);
   }
 }
}

3 、驱动的使用

我们已经设计并实现了ESP8266无线通讯模块的驱动程序。接下来我们将设计一个简单的应用以验证驱动的设计是否符合要求。

3.1 、声明并初始化对象

使用基于对象的操作我们需要先得到这个对象,所以我们先要使用前面定义的ESP8266无线通讯模块对象类型声明一个ESP8266无线通讯模块对象变量,具体操作格式如下:

Esp8266ObjectObjectesp;

声明了这个对象变量并不能立即使用,我们还需要使用驱动中定义的初始化函数对这个变量进行初始化。这个初始化函数所需要的输入参数如下:

Esp8266ObjectObject*esp, //ESP8266对象

Esp8266CWModeTypecwMode, //WIFI模式

Esp8266CIPModeTypecipMode, //传输模式,正常或透传

char*wifiName, //WIFI名称

char*wifiPassword, //WIFI密码

ESP8266SendDataTypesend, //发送函数指针

ESP8266DelaymsTypedelayms //毫秒延时函数

对于这些参数,对象变量我们已经定义了。而WIFI模式与传输模式均为枚举,根据实际情况选择就好了。同样WIFI名称和WIFI密码更具实际使用情况输入,注意时字符串就可以了。最主要的是我们需要定义几个函数,并将函数指针作为参数。这几个函数的类型如下:

/*定义ESP8266数据发送指针类型*/
typedef void(*ESP8266SendDataType)(uint8_t *sData,uint16_t sSize);


/*延时操作指针*/
typedef void (*ESP8266DelaymsType)(volatileuint32_t nTime);

对于这几个函数我们根据样式定义就可以了,具体的操作可能与使用的硬件平台有关系。实际上我们主要需要关注的是串口发送函数。具体函数定义如下:

/*串口数据发送*/
static void SendDataForEsp8266(uint8_t*txData,uint16_t length)
{
 HAL_UART_Transmit(&esp8266huart,txData,length,1000);
}

对于延时函数我们可以采用各种方法实现。我们采用的STM32平台和HAL库则可以直接使用HAL_Delay()函数。于是我们可以调用初始化函数如下:

/*ESP8266对象初始化*/
  Esp8266Initialization(&esp,                   //ESP8266对象
                    Esp8266_StationMode,    //WIFI模式
                    Esp8266_TransMode,      //传输模式,正常或透传
                    wifiName,               //WIFI名称
                    wifiPassword,           //WIFI密码
                    SendDataForEsp8266,     //发送函数指针
                    HAL_Delay               //毫秒延时函数
                    );

3.2 、基于对象进行操作

我们定义了对象变量并使用初始化函数给其作了初始化。接着我们就来考虑操作这一对象获取我们想要的数据。我们在驱动中已经将获取数据并转换为转换值的比例值,接下来我们使用这一驱动开发我们的应用实例。

/*ESP8266数据通讯*/
void Esp8266DataCommunication(void)
{
 uint8_tsData[16]={0x10,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F};
 
 Esp8266SendData(&esp,sData,16);
}

4 、应用总结

在这一篇中我们设计并实现了ESP8266无线模块的驱动,并基于次驱动程序设计了一个简单的验证应用。测试结果是符合我们的预期的,说明我们设计的驱动没有问题。

在使用驱动程序时需要注意,这一驱动只是实现了ESP8266的基本功能,所以要想实现更复杂的功能是可以在驱动基础上扩展的。后续我们也会根据使用的需要进一步扩充驱动。当然这个驱动是基于AT指令来实现操作的,扩充这个驱动程序的功能也需要使用AT指令来实现。

本驱动程序在设计时,考虑使用串口中断来接收数据,所以我们为对象设计了一个接收数据缓存结构。在设计应用时需在串口中断服务函数中向缓存种添加数据。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 物联网
    +关注

    关注

    2866

    文章

    41549

    浏览量

    358118
  • 无线通讯
    +关注

    关注

    5

    文章

    520

    浏览量

    37725
  • 驱动设计
    +关注

    关注

    1

    文章

    108

    浏览量

    15185
  • ESP8266
    +关注

    关注

    50

    文章

    946

    浏览量

    43870
收藏 人收藏

    评论

    相关推荐

    智能家居DIY之硬件设计2----WiFi通讯模块ESP8266+2.4GHZ中转器)

    本帖最后由 linchenfeng 于 2017-4-22 00:23 编辑 本贴介绍基于ESP8266的WiFi通讯模块,又名“路由模块”。 在上一个帖子介绍了NRF24LE1
    发表于 04-03 20:44

    ESP8266怎么实现链路层

    事情是这样的,我想用WIFI模块STM32+ESP8266(内置LWIP协议)实现WIFI探针功能,需要更改底层无线网卡驱动,但是现在不知道
    发表于 02-18 03:29

    ATK-ESP8266 WIFI模块测试实验-STM32驱动无线WIFI模块ESP8266的学习心得

    ATK-ESP8266 WIFI模块测试实验-STM32驱动无线WIFI模块ESP8266的学习
    发表于 06-01 12:18

    STM32与ESP8266是如何进行通讯

    Hi,我是小鱼君~本期小鱼君给大家带来了简单易懂的单片机与ESP8266进行无线通讯的教程。在一个比赛中需要用到单片机发送数据到云端,我们就用到了ESP8266这个比较简单的模块,网上
    发表于 07-14 06:02

    ESP8266系列模块选型

    ESP8266系列模块选型ESP8266 ESP-01 ESO-02
    发表于 01-05 17:34 37次下载

    ESP8266模块官方使用指导

    无线WiFi ESP8266模块主导文件,内容包括命令指导,使用测试、实例和使用方法
    发表于 06-08 17:52 233次下载

    ESP8266串口WIFI远距离无线模块

    ESP8266串口WIFI 无线模块 WIFI远距离无线模块 穿墙王
    发表于 05-10 10:15 56次下载

    esp8266无线串口模块分析介绍

     ESP8266芯片是一款串口转无线模芯片,内部自带固件,用户操作简单,无需编写时序信号等。ESP8266 系列模组是安信可(Ai-thinker)公司采用乐鑫ESP8266芯片开发的
    发表于 11-03 10:28 1.2w次阅读

    如何将ESP8266连接到WiFi

    在之前的ESP8266项目中,我简要介绍了ESP8266 WiFi模块,如何开始使用ESP8266和Arduino,ESP8266
    的头像 发表于 07-29 11:32 8.5w次阅读
    如何将<b class='flag-5'>ESP8266</b>连接到WiFi

    ESP8266 wifi模块开发汇总

                                  ESP8266 wifi模块开发汇总 ESP8266 wifi模块开发汇总本文档主要介绍开发者在
    发表于 11-05 19:21 183次下载
    <b class='flag-5'>ESP8266</b> wifi<b class='flag-5'>模块</b>开发汇总

    ESP8266模块开发入门教程

    ,NB-IOT更加合适。一. ESP8266模块三种工作模式1.STA模式 STA 模式:ESP8266 模块通过路由器连接互联网,手机或电脑通过互联网
    发表于 12-07 17:21 18次下载
    <b class='flag-5'>ESP8266</b><b class='flag-5'>模块</b>开发入门教程

    STM32与ESP8266通讯

    Hi,我是小鱼君~本期小鱼君给大家带来了简单易懂的单片机与ESP8266进行无线通讯的教程。在一个比赛中需要用到单片机发送数据到云端,我们就用到了ESP8266这个比较简单的模块,网上
    发表于 12-17 18:34 22次下载
    STM32与<b class='flag-5'>ESP8266</b><b class='flag-5'>通讯</b>

    ESP8266相互通讯ESP-NOW)

    办法,可以用一个ESP8266模块作为一个总的控制,就像一个管家,来和其他ESP8266通讯,来实现我们想要的功能。先说一下
    发表于 12-29 19:33 10次下载
    <b class='flag-5'>ESP8266</b>相互<b class='flag-5'>通讯</b>(<b class='flag-5'>ESP</b>-NOW)

    ESP8266 Arduino通讯

    电子发烧友网站提供《ESP8266 Arduino通讯.zip》资料免费下载
    发表于 11-15 09:38 14次下载
    <b class='flag-5'>ESP8266</b> Arduino<b class='flag-5'>通讯</b>

    ESP8266初次如何实现无线通信(基于电脑与ESP8266)

    的且集成的国产WIFI模块,它有很多种型号,但是使用方法没什么太大的区别,也可以说没区别,有些看起来引脚比较多的ESP8266模块只是将这个芯片的IO口拓展出来了而已。还有 一种原因就是它采用的是Micropython编程的
    发表于 05-30 09:53 14次下载
    <b class='flag-5'>ESP8266</b>初次如何<b class='flag-5'>实现</b><b class='flag-5'>无线</b>通信(基于电脑与<b class='flag-5'>ESP8266</b>)