关于51单片机+ESP8266
2016-03-02 11:52
204 查看
前言:这个题目是我在单片机课程设计《基于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 <AT89X52.H>
#include<reg52.h>
#include <stdio.h>
#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\n"); //设置为softAP和station共存模式
for (a=0; a<30000; a++);
printf ("AT+RST\n"); //重新启动模块
for (a=0; a<50000; a++);
printf ("AT+CIPMUX=1\n"); //启动多连接
for (a=0; a<20000; a++);
printf ("AT+CIPSERVER=1\n");//建立server,默认端口为333
for (a=0; a<20000; a++);
printf ("AT+CIPSTO=50\n"); //服务器超时时间设置
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\n"); //发送语句的命令
for (a=0; a<10000; a++);
printf ("%c\nplease enter your destination:",'1'); //需要发送的语句
lift_key_1=on;
break;
case '@':
printf ("AT+CIPSEND=0,33\n");
for (a=0; a<10000; a++);
printf ("%c\nplease enter your destination:",'2');
lift_key_2=on;
break;
case '#':
printf ("AT+CIPSEND=0,33\n");
for (a=0; a<10000; a++);
printf ("%c\nplease enter your destination:",'3');
lift_key_3=on;
break;
case '$':
printf ("AT+CIPSEND=0,33\n");
for (a=0; a<10000; a++);
printf ("%c\nplease enter your destination:",'4');
lift_key_4=on;
break;
case '%':
printf ("AT+CIPSEND=0,33\n");
for (a=0; a<10000; a++);
printf ("%c\nplease 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\n"); //
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\n");
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\n");
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\n");
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\n"); //服务器超时时间
do{
if(RI)
{
ldat=SBUF;
RI=0;
if (ldat=='K')
d=0;
}
}while (d);
d =1;
for (a=0; a<10000; a++);
ES=1; //串行口中断打开
}
代码概况:将模块的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 <AT89X52.H>
#include<reg52.h>
#include <stdio.h>
#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\n"); //设置为softAP和station共存模式
for (a=0; a<30000; a++);
printf ("AT+RST\n"); //重新启动模块
for (a=0; a<50000; a++);
printf ("AT+CIPMUX=1\n"); //启动多连接
for (a=0; a<20000; a++);
printf ("AT+CIPSERVER=1\n");//建立server,默认端口为333
for (a=0; a<20000; a++);
printf ("AT+CIPSTO=50\n"); //服务器超时时间设置
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\n"); //发送语句的命令
for (a=0; a<10000; a++);
printf ("%c\nplease enter your destination:",'1'); //需要发送的语句
lift_key_1=on;
break;
case '@':
printf ("AT+CIPSEND=0,33\n");
for (a=0; a<10000; a++);
printf ("%c\nplease enter your destination:",'2');
lift_key_2=on;
break;
case '#':
printf ("AT+CIPSEND=0,33\n");
for (a=0; a<10000; a++);
printf ("%c\nplease enter your destination:",'3');
lift_key_3=on;
break;
case '$':
printf ("AT+CIPSEND=0,33\n");
for (a=0; a<10000; a++);
printf ("%c\nplease enter your destination:",'4');
lift_key_4=on;
break;
case '%':
printf ("AT+CIPSEND=0,33\n");
for (a=0; a<10000; a++);
printf ("%c\nplease 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\n"); //
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\n");
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\n");
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\n");
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\n"); //服务器超时时间
do{
if(RI)
{
ldat=SBUF;
RI=0;
if (ldat=='K')
d=0;
}
}while (d);
d =1;
for (a=0; a<10000; a++);
ES=1; //串行口中断打开
}
相关文章推荐
- 解决URL路径包含中文以及特殊符号
- 运算符(一)
- UVA10201
- weinx公众号--AccessToken和JsapiTicket的获取方法及长期保存 (整合)
- python 500 lines or less 参考地址
- python的资料
- lsof的用法
- WINDOWS快捷方式(*.lnk文件)打开方式关联错误的解决方法
- Android之ListView下拉刷新和上拉加载实现详解(含源码Demo)
- 求N天前日期的方法
- 实例解析Python设计模式编程之桥接模式的运用
- 嵌入式笔试题一
- Yii中CArrayDataProvider和CActiveDataProvider区别实例分析
- QT + Win7 SDK 中文时 乱码 常量中有换行符 问题
- Android Studio之Eclipse工程代码搬家
- Java开发Web Service的简介
- 猫猫学iOS之UIButton一行代码重写图片和标题位置源代码分享
- iOS 谁说程序猿不懂浪漫之 爱心
- 升级iOSBeta版本
- <手机控>开发过程记录