打印
[STM32H7]

WIFI模块ESP8266

[复制链接]
33|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
模块介绍
模块连接
模块连接时基于串口方式连接,其模块与电脑(服务器)之间数据的发送与接收也是基于串口。


WIFI模块的模式
mode=1 :Station模式(连接到WIFI)
mode=2:AP模式(自己作为WIFI源供其他连接)
mode=3:AP+Station模式(以上两者模式的合并)
WIFI模块常用AT指令



使用特权

评论回复
沙发
键盘手没手|  楼主 | 2024-6-30 20:10 | 只看该作者
透传模式理解
透传模式就是单片机通过串口形式与模块连接,而模块与上位机之间的数据交互的具体不用考虑。

使用特权

评论回复
板凳
键盘手没手|  楼主 | 2024-6-30 20:10 | 只看该作者
如果不开启透传模式,在每次发送数据前都必须先发送指令AT+CIPSEND=
AT+CIPSEND=4
  
OK
>                //在 > 后面输入要上传的数据

但是开启了透传模式,我们就不需要在每次发送数据前都发送指令AT+CIPSEND=了,只需要发送一次AT+CIPSEND,之后发送的所有内容全部当成是数据了!

使用特权

评论回复
地板
键盘手没手|  楼主 | 2024-6-30 20:11 | 只看该作者
代码实现
代码介绍
1、对串口的配置。
串口初始化、串口中断接收数据,串口发送函数封装(模块发送数据)

2、AT指令的发送,并发送AT指令时发送相关的数据:熟练运用spprintf()函数。

实现步骤

1. 重置模组为出厂模式:AT+RESTORE                        示例:AT+RESTORE                     OK
2. 设置工作模式:AT+CWMODE=<mode>                示例:AT+CWMODE=1             OK
3. 连接当前环境的WIFI热点:AT+CWJAP=<ssid>,< pwd >       
                < ssid >:字符串参数,当前WIFI的名字
                 < pwd >:字符串参数,连接密码
                 示例:AT+CWJAP="TCP_Server","12345678"
                       WIFI CONNECTED             
                       WIFI GOT IP
4. 建立TCP连接通道        :AT+CIPSTART="TCP",<ip>,<port>
                 < ip >:字符串参数,IP地址
                  < port >:字符串参数,服务器端口
        示例: AT+CIPSTART="TCP","192.168.4.1",333
              CONNECTED
5. 开启透传模式:AT+CIPMODE=1
6. 发送数据: AT+CIPSEND=<length>
                 <length> 发送数据的字节长度
        示例: AT+CIPSEND=10
      OK
       >在此处填写要发送的内容
注释:示例是在串口调试助手下的发送与返回。也是给代码编写提供示例。

使用特权

评论回复
5
键盘手没手|  楼主 | 2024-6-30 20:11 | 只看该作者
c文件
#include "delay.h"
#include "wifi.h"
#include "stdarg.h"                  
#include "stdio.h"       
#include "stdlib.h"
#include "string.h"         
#include "usart.h"
#include "stm32f10x.h"
#include "sys.h"
#include "lcd.h"



//串口接收缓存区        
char USART2_RX_BUF[USART2_MAX_RECV_LEN];                                 //接收缓冲,最大USART3_MAX_RECV_LEN个字节.

//接收到的数据状态
//[15]:0,没有接收到数据;1,接收到了一批数据.
//[14:0]:接收到的数据长度
vu16 USART2_RX_STA=0;          

void USART2_IRQHandler(void)
{
        u8 res;
        if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)//接收到数据
        {         
                        USART_ClearITPendingBit(USART2, USART_IT_RXNE);
                  res =USART_ReceiveData(USART2);                 
                        USART2_RX_BUF[USART2_RX_STA&0X3FFF]=res;        //记录接收到的值
                        USART2_RX_STA++;               
                        //USART_SendData(USART1,res);
                        //printf("%x",res);
                        USART2_RX_STA|=0x8000;                        //标记接收完成
        }
}   


//初始化IO 串口2
//bound:波特率          
void wifi_usart2_init(u32 bound)
{
        NVIC_InitTypeDef NVIC_InitStructure;
        GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);        // GPIOA时钟
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE); //串口2时钟使能

        USART_DeInit(USART2);  //复位串口2
                 //USART2_TX   PA2
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //复用推挽输出
  GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA2
   
    //USART2_RX          PA3
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化PA3
       
       
                //设置中断优先级
        NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//抢占优先级2
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;                //子优先级2
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        //IRQ通道使能
        NVIC_Init(&NVIC_InitStructure);        //根据指定的参数初始化VIC寄存器
       
        USART_InitStructure.USART_BaudRate = bound;//波特率一般设置为9600;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
        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(USART2, &USART_InitStructure); //初始化串口        2
        //使能接收中断
  USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启中断
        USART_Cmd(USART2, ENABLE);                    //使能串口

        USART2_RX_STA=0;                //清零
}
/******************************************************************************
      函数说明:发送数据到串口2
      入口数据:DATA_BUF  发送的数据           
                len   发送的长度         
      返回值:  无
******************************************************************************/
void esp8266_send_data(u8 *DATA_BUF,u8 len)        //发送数据到串口2
{
        u16 j;
        if(len <= 0)
                return ;
        if(len>USART2_MAX_SEND_LEN)                        //最多只能发MAX_LEN个数据
        {
                for(j=0;j<USART2_MAX_SEND_LEN;j++)                                                        //循环发送数据
                {
                        USART_SendData(USART2,DATA_BUF[j]);
                        while(USART_GetFlagStatus(USART2,USART_FLAG_TC)==RESET); //循环发送,直到发送完毕          
                }
        }
        else
        {
                for(j=0;j<len;j++)                                                        //循环发送数据
                {
                        USART_SendData(USART2,DATA_BUF[j]);
                        while(USART_GetFlagStatus(USART2,USART_FLAG_TC)==RESET); //循环发送,直到发送完毕          
                }
        }
}
/******************************************************************************
      函数说明:检查是否有相应回复的数据
      入口数据:str 检查的字符串         
                           
      返回值:  str出现的位置开始
******************************************************************************/
u8* esp8266_check_cmd(u8 *str)                //检查回复是否有字符串str
{
        USART2_RX_STA = 0;
        return (u8*)strstr((const char*)USART2_RX_BUF,(const char*)str);       
}
/******************************************************************************
      函数说明:连接WIFI                 TCP服务器   
                                                                根据电脑上连接的WIFI和IP地址,建立模块与电脑上服务器之间的连接
                                                                将模块连接与WIFI(wifi名字和密码),并确认是那台电脑上(电脑上的ip地址)的服务器
                                                                电脑与模块需要连接在同以WIFI下
                                                                使模块与电脑通过串口,连接于电脑端的服务器软件或平台
      入口数据:id                  WIFI帐号
                                                                key                        WIFI密码
                                                                ip                        TCP服务器的IP地址
                                                                port                TCP服务器的端口号
                           
      返回值:  连接成功返回0,        WIFI连接失败返回-1, TCP连接失败返回-2
******************************************************************************/

int esp8266_connect_ap_tcp(u8 *ssid,u8 *password,u8 *ip,u8 *port)        //发送WIFI账号,密码
{
                u8 idkey_buf[64]={0};
                u8 ip_server[64]={0};
                u8 i;
                int n;
                int m;
                char *ipbuf;
                char *ipbuf1;
                //u8 debuf[1] = """;
                int datelen1,datelen2;
                //将发送的数据通过sprintf存入数组
                //然后发送AT指令和等待模块连接,返回相应的数据
                datelen1 = sprintf((char *)idkey_buf,"AT+CWJAP=\"%s\",\"%s\"\r\n",ssid,password);//连接指令
                datelen2 = sprintf((char *)ip_server,"AT+CIPSTART=\"TCP\",\"%s\",%s\r\n",ip,port);//连接指令
                esp8266_send_data("AT+RSTORE\r\n",11);
       
                delay_ms(1000);         //延时3S等待重启成功
                delay_ms(1000);
                //设置工作模式 1:station模式   2:AP模式  3:兼容 AP+station模式
                esp8266_send_data("AT+CWMODE=1\r\n",13);
                delay_ms(1000);
                delay_ms(1000);
                esp8266_send_data(idkey_buf,datelen1);        //让模块连接上自己的路由                "WIFI GOT IP"
                delay_ms(1000);
                delay_ms(1000);
                delay_ms(1000);
                delay_ms(1000);
                delay_ms(1000);
                delay_ms(1000);
                delay_ms(1000);
                if(esp8266_check_cmd("WIFI CONNECTED"))
                {
                        delay_ms(1000);
                        esp8266_send_data("AT+CIFSR\r\n",10);                                                                        //查询本模块IP地址
                        delay_ms(1000);
                        delay_ms(1000);
                        delay_ms(1000);
                        ipbuf = (char*)esp8266_check_cmd("+CIFSR:");               
                       
                        //得到IP地址最后3 位 例如:192.168.1.120 得到 120                        //显示的是ESP8266模块的IP地址的后三位
                        for(i=0;i<3;i++)  
                        {
                                ipbuf = strstr(ipbuf,".");
                                ipbuf ++;
                        }                       
                        ipbuf1 = strstr(ipbuf,"\"");
                        n = ipbuf1-ipbuf;
                        ipbuf[n] = '\0';
                        m = atoi(ipbuf); //将字符格式 转换为int                                                //发送AT指令后,模块返回的是字符串,需要将后三位转化为数字
                        printf("clinet IP is:%d\r\n",m);
                        LCD_ShowString(40,0,"   ",RED,WHITE);        //接收数据显示至lcd屏
                        LCD_ShowString(40,0,(u8 *)ipbuf,RED,WHITE);        //接收数据显示至lcd屏
                        esp8266_send_data(ip_server,datelen2);        //建立TCP连接  这四项分别代表了 要连接的ID号0~4   连接类型  远程服务器IP地址   远程服务器端口号
                        delay_ms(1000);
                        delay_ms(1000);
                        delay_ms(1000);
                        delay_ms(1000);
                        if(esp8266_check_cmd("CONNECT"))                //判断是否连接成功
                        {
                         return m;
                        }
                               
                        else
                                return -2;
                }
                return -1;
}
/******************************************************************************
      函数说明:发送数据到服务器
                                                                模块建立TCP连接到服务器,并发送数据
      入口数据:data  发送的数据     
                                                                len   发送的长度
                           
      返回值:  若无TCP连接返回0,有返回1
******************************************************************************/
u8 esp8266_send_serverdata(u8 *data,u8 len)                //给服务器发数据,检查若无连接TCP 则return 0;连上则发送
{
        //检查TCP连接状态        AT+CIPSTATUS    STATUS:3
        u8 Send_ServerBuf[32] = {0};
        u8 len2=0;
        esp8266_send_data("AT+CIPSTATUS\r\n",14);                       
        delay_ms(10);
        if(esp8266_check_cmd("STATUS:3"))                                        //检查回复
        {
                len2=sprintf((char *)Send_ServerBuf,"AT+CIPSEND=%d\r\n",(int)len);
                esp8266_send_data(Send_ServerBuf,len2);//发送len个字节的数据到服务器端
                delay_ms(10);
                esp8266_send_data(data,len);
                return 1;
        }
        else
                return 0;
}
/******************************************************************************
      函数说明:解析服务器发送的有效数据
      参数:recv_buf  接收数组指针  
                           
      返回值:  有效数据的长度
******************************************************************************/
u16 esp8266_rev_serverdata(u8 *recv_buf)
{       
                u8 i,j;
                int len;
                char *USART_RX_BUF1;
                char *USART_RX_BUF2;
                u8 lens[3]={0};

                delay_ms(20);
                if(USART2_RX_STA&0X8000)                //接收到一次数据了
                {
                        //"\r\n+IPD,20:http://www.baidu.com"
                        if(strstr((const char*)USART2_RX_BUF,"+IPD"))
                        {                       
                                USART_RX_BUF1=strstr(USART2_RX_BUF,",");        //查找第一个 ","所在位置 返回指针
                                USART_RX_BUF2=strstr(USART2_RX_BUF,":"); //查找第一个  ":"所在位置 返回指针
                                j=USART_RX_BUF2-USART_RX_BUF1;   //数据长度计算 指针相减
                                if (j>3) j=3;
                                for(i=0;i<j;i++)
                                {
                                        lens[i]=USART_RX_BUF1[i+1];
                                }                               
                                len = atoi((const char *)lens);                        //字符串转整数
                                for(i=0;i<len;i++)
                                {
                                        recv_buf[i] = USART_RX_BUF2[i+1];
                                }
                                recv_buf[len]='\0';
                                USART2_RX_STA = 0;
                                return len;
                        }
                }
                USART2_RX_STA = 0;
                return 0;
}

使用特权

评论回复
6
键盘手没手|  楼主 | 2024-6-30 20:11 | 只看该作者
h文件
#ifndef __WIFI_H
#define __WIFI_H         
#include "sys.h"     

#define USART2_MAX_RECV_LEN                200                //最大接收缓存字节数
#define USART2_MAX_SEND_LEN                200                                //最大发送缓存字节数

extern char  USART2_RX_BUF[USART2_MAX_RECV_LEN];                 //接收缓冲,最大USART2_MAX_RECV_LEN字节
extern u8  USART2_TX_BUF[USART2_MAX_SEND_LEN];                 //发送缓冲,最大USART2_MAX_SEND_LEN字节
extern vu16 USART2_RX_STA;                                                   //接收数据状态

void wifi_usart2_init(u32 bound);                                //串口2初始化

int esp8266_connect_ap_tcp(u8 *ssid,u8 *password,u8 *ip,u8 *port); //发送WIFI账号,密码/TCP服务器的IP,接口
u16 esp8266_rev_serverdata(u8 *USART_RX_buf);//解析服务器发送的有效数据
u8 esp8266_send_serverdata(u8 *data,u8 len);

#endif

使用特权

评论回复
7
键盘手没手|  楼主 | 2024-6-30 20:11 | 只看该作者
main.c文件
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "lcd.h"
#include "wifi.h"
#include "key.h"
#include "timer.h"
#include "beep.h"
#include "lcd_init.h"

//技术支持:

int main(void)
{        
        u16 rlen=0;
        int add;
        u8 key;
       
        u16 led0pwmval=0;            //PWM用变量
        u8 dir=1;                                                        //PWM初始递增
        u8 revbuf[200] = {0}; //接收buffer
        u8 heartbeat[5]={0x55,0x00,0x00,0x00,0xaa}; //心跳包格式
       
        u8 ledflag = 1;         //LED处理变量
        u8 beepflag = 0;//蜂鸣器处理变量
        u8 picflag = 0;//图片处理变量
        u8 pwmflag = 1;//PWM处理变量
       
        u8 beepfirst=1;//定义此变量来解决蜂鸣器上电后默认响的问题
        u8 picjif=0;//定义此变量解决PWM时刷新图片导致PWM观察不明显的问题

        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
        delay_init();                     //延时函数初始化          
        uart_init(115200);                  //串口1初始化为115200
       
        wifi_usart2_init(115200);
       
        LED_Init();                                   //初始化LED
        LCD_Init();                                         //初始化LCD
        KEY_Init();                                        //初始化KEY
        BEEP_Init();                                //初始化BEEP
        TIM1_PWM_Init(899,0);//初始化TIM1
       
        LCD_Fill(0,0,LCD_W,LCD_H,WHITE);//进行清屏
        LCD_ShowString(0,0,(u8*)"地址:     LED:  ",RED,WHITE);
        LCD_ShowString(0,16,(u8*)"蜂鸣器:   PWM:  ",RED,WHITE);
       
        add=esp8266_connect_ap_tcp("TZH-WiFi","88888888","192.168.0.25","8234");
        if(add)
        {
                heartbeat[1] = add&0xff;
                esp8266_send_serverdata(heartbeat,5);
        }
        LCD_ShowPicture(0,32,128,128,gImage_ta);
       
                while(1)
                {       
                       
                        key=KEY_Scan(0); //进行按键扫描 不检测连按
                        if( key == KEYLEFT_PRES ) //KEYLEFT按下,连接服务器
                        {
                                //连接wifi ap ssid ="TZHXXKJ" password = "1105_tzh" tcp server ip="192.168.1.147" port="8234"
                                add=esp8266_connect_ap_tcp((u8*)"TZH-WiFi","88888888","192.168.0.25","8234");
                                if(add)
                                {
                                        heartbeat[1] = add&0xff;
                                        esp8266_send_serverdata(heartbeat,5);
                                }
                        }
//-------------------------------------------------------------------------------------------------------                       
                        if(key==KEYRIGHT_PRES) //KEYRIGHT按下,往服务器发送数据
                        {       
                               
                                esp8266_send_serverdata((u8*)"123456789",9);
                               
                        }
                       
//-------------------------------------------------------------------------------------------------------                                       
                        if(!ledflag) //LED 相关处理
                        {
                                LED1=0;
                                LCD_ShowString(112,0,(u8*)"开",RED,WHITE);                               
                        }
                        else
                        {
                                LED1=1;
                                LCD_ShowString(112,0,(u8*)"关",RED,WHITE);       
                        }
                       
                        if(!beepflag) //蜂鸣器 相关处理
                        {
                                if(beepfirst) //第一次上电时蜂鸣器不响
                                {
                                       
                                        BEEP=0;
                                        LCD_ShowString(56,16,(u8*)"关",RED,WHITE);       
                                }
                                else       
                                {                                       
                                        BEEP=1;
                                        LCD_ShowString(56,15,(u8*)"开",RED,WHITE);       
                                }
                        }
                        else
                        {
                                BEEP=0;
                                LCD_ShowString(56,16,(u8*)"关",RED,WHITE);       
                        }
//-------------------------------------------------------------------------------------------------------                                       
                        if(picflag) //动态图片相关处理
                        {
                                LCD_ShowPicture(0,32,128,128,gImage_gif1);
                                LCD_ShowPicture(0,32,128,128,gImage_gif2);
                        }
//-------------------------------------------------------------------------------------------------------                                       
                        if(!pwmflag)//PWM 相关处理
                        {
                                if(picflag)//如果动态图片刷新为真
                                {
                                        picjif=1;//记录该状态
                                        picflag=0;//先禁止动态图片刷新 否则影响PWM观察
                                }
                                if(dir)led0pwmval += 15;
                                else         led0pwmval -= 15;
                                if(led0pwmval>800)dir=0;
                                if(led0pwmval==0)dir=1;                                                    
                                TIM_SetCompare1(TIM1,led0pwmval);
                                LCD_ShowString(112,16,(u8*)"开",RED,WHITE);       
                        }
                        else//PWM关闭
                        {
                                if(picjif)//如果记录状态为真,说明动态图片刷新被禁止
                                {
                                        picjif=0;//清除该状态变量
                                        picflag=1;//恢复动态图片刷新
                                }
                                TIM_SetCompare1(TIM1,0);                       
                                LCD_ShowString(112,16,(u8*)"关",RED,WHITE);                                       
                        }
                       
//-------------------------------------------------------------------------------------------------------                                       
//-------------------------------------------------------------------------------------------------------               
                        delay_ms(10);
                        rlen=esp8266_rev_serverdata(revbuf);                //接收服务器发过来的数据
                        if(rlen)
                        {
                                if(revbuf[2] == 1) //LED 相关处理
                                {
                                        ledflag=revbuf[3];
                                }
                                if(revbuf[2] == 2)//蜂鸣器 相关处理
                                {
                                        beepfirst=0;
                                        beepflag=revbuf[3];
                                }       
                                if(revbuf[2] == 3)//图片显示 相关处理
                                {
                                        switch(revbuf[3])
                                        {
                                                case 0x01:picflag=0;picjif=0;LCD_ShowPicture(0,32,128,128,gImage_ta);break;
                                                case 0x02:picflag=0;picjif=0;LCD_ShowPicture(0,32,128,128,gImage_yun);break;
                                                case 0x03:picflag=1;picjif=0;break;
                                                default:
                                                                                LCD_ShowPicture(0,32,128,128,gImage_ta);
                                        }
                                }                                               
                                if(revbuf[2] == 4) //PWM 相关处理
                                {
                                        pwmflag=revbuf[3];
                                }
                        }
                       
                       
                }                //end while(1)
}

使用特权

评论回复
8
键盘手没手|  楼主 | 2024-6-30 20:12 | 只看该作者
数据接收讲解
主要部分:
rlen=esp8266_rev_serverdata(revbuf);                //接收服务器发过来的数据
if(rlen)
{
        if(revbuf[2] == 1) //LED 相关处理
        {
                ledflag=revbuf[3];
        }
        if(revbuf[2] == 2)//蜂鸣器 相关处理
        {
                beepfirst=0;
                beepflag=revbuf[3];
        }       
        if(revbuf[2] == 3)//图片显示 相关处理
        {
                switch(revbuf[3])
                {
                        case 0x01:picflag=0;picjif=0;LCD_ShowPicture(0,32,128,128,gImage_ta);break;
                        case 0x02:picflag=0;picjif=0;LCD_ShowPicture(0,32,128,128,gImage_yun);break;
                        case 0x03:picflag=1;picjif=0;break;
                        default:
                                                        LCD_ShowPicture(0,32,128,128,gImage_ta);
                }
        }                                               
        if(revbuf[2] == 4) //PWM 相关处理
        {
                pwmflag=revbuf[3];
        }
}

使用特权

评论回复
9
键盘手没手|  楼主 | 2024-6-30 20:12 | 只看该作者
上位机发送的数据
> [1,OnAccept] -> PASS(192.168.1.177:18323)
> [1,OnReceive] -> 192.168.1.177:18323 (5 bytes)
-> HEX: 55 B1 00 00 AA
-> ASCII: U?
其中最主要看HEX十六进制数据
根据代码和接受的数据,可知,其最后在物理层连接部分,只是串口的应用。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

103

主题

1141

帖子

0

粉丝