基于51单片机Android WiFi控制LED开关设计与实现 一、系统方案 手机APP通过ESP8266 WIFI模块与51单片机通信控制LED灯、蜂鸣器的开关。下位机由单片机、ESP8266模块和LED灯组成,上位机由Android手机APP承担。我们在APP上发送LED灯、蜂鸣器的开关控制指令,ESP8266将收到的数据发送给单片机,从而实现对LED灯、蜂鸣器进行开关控制。
设计好的实物是这个样子: 二、硬件设计 ESP8266模块作为一个透传模块使用,RXD、TXD分别连接51单片机的TXD和RXD,VCC接3.3V电压,GND接地,只需要连接这些管脚,ESP8266模块就可以正常工作了。在单片机P16口上连接蜂鸣器、P26、P27连接两个3mm的LED灯,我们的目的是通过手机APP上的开关控制着LED灯的亮灭以及蜂鸣器打开与关闭。 原理图如下:
三、单片机软件设计 硬件的连接不复杂,接下来主要是单片机和手机APP代码的编写。 单片机代码主要是串口初始化、串口中断和ESP8266的初始化。首先是串口初始化: TMOD=0x20; //定时器1工作在方式2 TH1 = 0xfd; //波特率9600 TL1 = 0xfd; SM0=0; //串口工作在方式1 SM1=1; EA = 1; //开总中断 REN = 1; //使能串口 TR1 = 1; //定时器1开始计时 然后是ESP8266初始化: delayms(1000); //延时 sendString("AT+CWMODE=2\r\n"); //设置ESP8266工作在AP模式下 delayms(1000); sendString("AT+CIPMUX=1\r\n"); //允许多连接 delayms(1000); sendString("AT+CIPSERVER=1,8080\r\n"); //建立服务器 delayms(1000); ES = 1; //esp8266初始化之后开串口中断 贴上51单片机负责串口发送的两个函数: //发送一个字节 void sendChar(uchar a) { SBUF = a; while(TI==0); TI=0; } //发送字符串 void sendString(uchar *s) { while(*s!='\0') { sendChar(*s); s++; } } 在串口中断中处理接收到的数据: 1:打开蜂鸣器 2:关闭蜂鸣器 3:打开红灯 4:关闭红灯 5:打开绿灯 6:关闭绿灯 esp8266在收到数据并转发给单片机时的数据格式:+IPD,<client号>,<收到的字符长度>:收到的字符,比如+IPD,0,5:hello,其中+PID是固定的;0代表的是TCP客户端编号,esp8266最多支持5个客户端同时连接,也就是说客户端编号是0到4,在本设计中由于只有一个客户端与esp8266相连,所以客户端编号是0;5代表收到的字符长度;hello是收到的字符。在本例中esp8266发送给单片机的数据是+IPD,0,1:1,我们把接收到的字符串缓存到字符数组中,所以在处理收到的数据逻辑中,首先判断是否是以'+'开始的,否则视作无效数据,然后判断数组中的第十个数据,因为第十个数据才是手机APP发送过来的数据。 void uart() interrupt 4 { if(RI == 1) { RI = 0; //清除串口接收标志位 receiveTable=SBUF; if(receiveTable[0]=='+') { i++; } else { i=0; } if(i==10) { i=0; switch(receiveTable[9]) { case '1': BEEP=0; break; case '2': BEEP=1; break; case '3': RedLED=0; break; case '4': RedLED=1; break; case '5': GreenLED=0; break; case '6': GreenLED=1; break; } } } } 四、Android APP软件设计 Android APP是借助Android Studio来开发的,界面比较简单,通过编辑框输入esp8266的IP地址和端口号,esp8266默认的IP地址是192.168.4.1,端口号是8080,这些都可以通过AT指令进行修改。布局页面的xml代码我们就不贴了,熟悉Android开发的读者很快就能根据截图编写出来,放上一个APP界面的截图: 我们主要看一下逻辑代码部分: 首先是控件的初始化和按钮点击事件回调的绑定 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mBtnConnect = (Button) findViewById(R.id.btn_connect); mEtIP = (EditText) findViewById(R.id.et_ip); mEtPort = (EditText) findViewById(R.id.et_port); mBtnRedOn = (Button) findViewById(R.id.btn_red_on); mBtnRedOff = (Button) findViewById(R.id.btn_red_off); mBtnYellowOn = (Button) findViewById(R.id.btn_yellow_on); mBtnYellowOff = (Button) findViewById(R.id.btn_yellow_off); mBtnBlueOn = (Button) findViewById(R.id.btn_blue_on); mBtnBlueOff = (Button) findViewById(R.id.btn_blue_off); mBtnConnect.setOnClickListener(this); mBtnRedOn.setOnClickListener(this); mBtnRedOff.setOnClickListener(this); mBtnYellowOn.setOnClickListener(this); mBtnYellowOff.setOnClickListener(this); mBtnBlueOn.setOnClickListener(this); mBtnBlueOff.setOnClickListener(this); } 按钮的点击回调方法: public void onClick(View v) { switch (v.getId()) { case R.id.btn_connect: //连接 if (mSocket == null || !mSocket.isConnected()) { String ip = mEtIP.getText().toString(); int port = Integer.valueOf(mEtPort.getText().toString()); mConnectThread = new ConnectThread(ip, port); mConnectThread.start(); } if (mSocket != null && mSocket.isConnected()) { try { mSocket.close(); mBtnConnect.setText("连接"); } catch (IOException e) { e.printStackTrace(); } } break; case R.id.btn_red_on: if (out != null) { out.print("1"); out.flush(); } break; case R.id.btn_red_off: if (out != null) { out.print("2"); out.flush(); } break; case R.id.btn_yellow_on: if (out != null) { out.print("3"); out.flush(); } break; case R.id.btn_yellow_off: if (out != null) { out.print("4"); out.flush(); } break; case R.id.btn_blue_on: if (out != null) { out.print("5"); out.flush(); } break; case R.id.btn_blue_off: if (out != null) { out.print("6"); out.flush(); } break; } } 负责连接esp8266的线程: private class ConnectThread extends Thread { private String ip; private int port; public ConnectThread(String ip, int port) { this.ip = ip; this.port = port; } @Override public void run() { try { mSocket = new Socket(ip, port); out = new PrintStream(mSocket.getOutputStream()); runOnUiThread(new Runnable() { @Override public void run() { mBtnConnect.setText("断开"); } }); new HeartBeatThread().start(); } catch (IOException e) { e.printStackTrace(); runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this, "连接失败", Toast.LENGTH_SHORT).show(); } }); } } }
|
@王栋春 :VX18326681813
@王栋春 :好的
学习了,程序最好标注一下。