关于51单片机+ESP8266

2019-04-15 12:36发布

前言:这个题目是我在单片机课程设计《基于ESP8266的物联电梯系统》中用到的,其实本质上就是实现了单片机对esp8266进行初始化,再将手机连上esp8266的WiFi,然后再通过手机端发送指令,esp8266接收到命令传入单片机,单片机再进行相应的操作。esp8266这种小型模块,在物联世界的发展中,有着强大的生命力,我本人比较喜欢它。同时这个也有相应的作品,程序也比较完整,希望能帮到大家。

代码概况:将模块的VCC,GND,TXD,RXD与单片机的VCC,GND,RXD,TXD接好,以为51单片机没有进程和线程的概念,所以就在main函数的while(1)中放入我们要的主程序,而用串口中断的方式来接收esp8266发过来的数据信息,从而实现用esp8266控制单片机。


/***************************************************main.c***************************************************************/
void main()
{
    init();               //这里是你自己的程序里面自定义的初始化程序
    init_esp();     //初始化esp8266
      while(1)
      {
        ES=1;        //因为每次处理完接收到的数据都关闭串口中断,所以在主程序循环中加入ES=1开启中断
        reach_floor();      //这个是我的主程序的名称
        
      }
}
//*********************串口中断程序********************************
void ser() interrupt 4
{
    unsigned char ldat;
    RI=0;
    ldat=SBUF;
    remote_control(ldat);    //esp8266接收数据并且作相应处理
}

/*********************************************esp8266.h****************************************************************/
#ifndef ESP8266_H
#define ESP8266_H

//#include
#include
#include
#include"main.h"
#define uint unsigned int
#define uchar unsigned char

void init_esp();
void remote_control(unsigned char ldat);

extern uint lift_key_5,lift_key_4,lift_key_3,lift_key_2,lift_key_1;   //因为我做的是电梯系统,所有这里需要接收到对应楼层号码信息,就改变楼层的数值。
#endif


/***********************************************esp8266.c***************************************************************/
#include"esp8266.h"

void init_esp()
{
    unsigned int a;
    TH1=0XFD;    //串口中断的波特率设为9600,同时记得将esp8266的AT固件代码改为9600的波特率,然后刷入该AT固件。
    TH0=0XFD;
    TR1=1;
    REN=1;       //使能串口允许接收
    SM0=0;      //工作在串口的工作方式1
    SM1=1;
    ES=0;       //串口中断关闭,待初始化后再打开
    EA=1;       //总中断打开
    TI = 1;
        for (a=0; a<50000; a++);    //延时几秒,让模块有时间启动
        printf ("AT+CWMODE=3 "); //设置为softAP和station共存模式

        for (a=0; a<30000; a++);    
        printf ("AT+RST ");  //重新启动模块

        for (a=0; a<50000; a++);    
        printf ("AT+CIPMUX=1 "); //启动多连接
    
        for (a=0; a<20000; a++);
        printf ("AT+CIPSERVER=1 ");//建立server,默认端口为333
                                    
        for (a=0; a<20000; a++);
        printf ("AT+CIPSTO=50 ");     //服务器超时时间设置
        
        for (a=0; a<20000; a++);
        RI=0;
        ES=1;   //初始化完成,串行口中断打开
//到了这里,就有一个疑问:ESP8266在接收到AT命令之后都会返回一个OK,为什么这里我没有相应的语句保证ESP8266成功接收到上面的几条命令呢? //答案是:因为单片机与esp8266通过的直接连接极少的情况才会丢失信息,比较可靠,而且我想速度达到最快。
//执行上述命令,模块进入服务模式,下面单片机就可以接收远程发来的数据
}

//远程选择电梯楼层程序 //这里楼层的号码用了符号来代替,应为在给esp8266发送命令的过程中,通常需要输入一些数值,而esp8266有时又会返回一些数值, //在串口接收的过程中,这些接收到的数字会影响我们的程序对楼层的判断,所以要采取特殊的表示楼层的方法。
void remote_control(unsigned char ldat)
{
         unsigned int a;

            switch(ldat)
            {
                case '!':                     //感叹号表示1楼,当然你也可以用其他表示方式,你也可以先接收到1,然后再进行其他的判断
                        printf ("AT+CIPSEND=0,33 ");               //发送语句的命令
                        for (a=0; a<10000; a++);
                        printf ("%c please enter your destination:",'1');   //需要发送的语句
                        lift_key_1=on;
                        break;
                case '@':
                        printf ("AT+CIPSEND=0,33 ");
                        for (a=0; a<10000; a++);
                        printf ("%c please enter your destination:",'2');
                        lift_key_2=on;
                        break;                        
                case '#':
                        printf ("AT+CIPSEND=0,33 ");
                        for (a=0; a<10000; a++);
                        printf ("%c please enter your destination:",'3');
                        lift_key_3=on;
                        break;
                case '$':
                        printf ("AT+CIPSEND=0,33 ");
                        for (a=0; a<10000; a++);
                        printf ("%c please enter your destination:",'4');
                        lift_key_4=on;
                        break;
                case '%':
                        printf ("AT+CIPSEND=0,33 ");
                        for (a=0; a<10000; a++);
                        printf ("%c please enter your destination:",'5');
                        lift_key_5=on;
                        break;
            }
            ES=0;
}




//下面附上更为可靠的esp8266初始化函数(使用了do...while...循环,确保esp8266回复了ok) //这里使用的是定时器2,所以程序与上面的有点不同
void init_esp()
{
    uint a;
     uchar ldat;
     int d =1;
    
     SCON=0x50; //串口工作方式1,8位UART,波特率可变  
     TH2=0xFF;           
     TL2=0xFD;    //波特率:115200 晶振=11.0592MHz
     RCAP2H=0xFF;   
     RCAP2L=0xFD; //16位自动再装入值

     TCLK=1;   
     RCLK=1;   
     C_T2=0;   
     EXEN2=0; //波特率发生器工作方式

    TR2=1 ; //定时器2开始            //
    TI = 1;

    REN=1;       //使能串口允许接收
    SM0=0;      //工作在串口的工作方式1
    SM1=1;
    ES=0;       //串口中断关闭,待初始化后再打开
    EA=1;       //总中断打开
    
        for (a=0; a<50000; a++);    //延时几秒,让模块有时间启动
        printf ("AT+CWMODE=3 "); //
        do{
            if(RI)
            {                //查询是否有数据接收
                    ldat=SBUF;        //数据暂存于变量中
                    RI=0;
                    if (ldat=='K')//命令执行成功,就会返回OK,这里就是查询是否有K返回,若有K返回,就说明执行成功,可以执行下一条,否则继续循环
                        d=0;
             }    
             }while (d);  
           d =1;//b、c、d复位,便于执行下一条命?
    
        for (a=0; a<50000; a++);    
        printf ("AT+RST ");
        do{
            if(RI)
             {            
                    ldat=SBUF;        
                    RI=0;
                    if (ldat=='K')
                        d=0;
             }
            }while (d);  
        d =1;

        for (a=0; a<80000; a++);    
        printf ("AT+CIPMUX=1 ");
       do{
           if(RI)
             {            
                   ldat=SBUF;        
                    RI=0;
                    if (ldat=='K')
                        d=0;
              }
             }while (d);
        d =1;

        for (a=0; a<10000; a++);
        printf ("AT+CIPSERVER=1 ");     
         do{
            if(RI)
            {            
                ldat=SBUF;        
                RI=0;
                if (ldat=='K')
                    d=0;
            }
          }while (d);
        d =1;

        for (a=0; a<10000; a++);
        printf ("AT+CIPSTO=50 ");          //服务器超时时间
          do{
              if(RI)
                {                
                    ldat=SBUF;        
                   RI=0;
                        if (ldat=='K')
                            d=0;
                }
         }while (d);
        d =1;
        for (a=0; a<10000; a++);
        ES=1;   //串行口中断打开
}