admin管理员组

文章数量:1794759

Android Studio设计APP实现与51单片机通过WIFI模块(ESP8266

Android Studio设计APP实现与51单片机通过WIFI模块(ESP8266

目录

一、前言

二、效果展示

1、APP界面展示

 2、C51硬件展示

三、Android Studio APP源代码

1、AndroidManifest.xml

1、请求联网:

2、开放明文传输:

2、MainActivity.java

3、Layout页面布局文件 activity_main.xml

四、Keil C51单片机源码

五、WIFI模块(ESP8266-01S)注意事项

六、后述     

一、前言

        本文将详细介绍如何利用Android Studio设计 APP 实现与C51单片机通过WIFI模块通讯控制LED灯亮灭,本人是外行属于是越菜越爱玩,找了很多资料,但都不得要领,最后终于靠着摸索学习实现了手机与C51模块的WIFI通讯,特来与大家分享,希望对各位能有所帮助。废话不多说,先看效果。

二、效果展示 1、APP界面展示

 2、C51硬件展示

 

        可以看到,该APP基本实现了手机与C51单片机之间的WIFI通讯,手机端可以发送和接收数据,可以选择直接给WIFI发送数据,也可以将发送的数据的发送代码固化为按键,比如我上面的四个LED按键其实底层代码就是按下分别发送“1”、“2”、“3”、“4”来控制四个灯的亮灭。本app只是用来实验手机与C51单片机之间的WIFI通讯,目前来说算是成功了,当然能控制LED不是最终结果,这只是一个开始,后续可以通过修改调用该程序实现更复杂的内容,目前我也在朝着这个方向努力`(*>﹏<*)′

  三、Android Studio APP源代码 1、AndroidManifest.xml

首先需要联网别忘了给 Android 添加网络连接权限:

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="schemas.android/apk/res/android" xmlns:tools="schemas.android/tools" package="com.example.tcp_led"> <uses-permission android:name="android.permission.INTERNET"/> //需要对WiFi进行操作,所以需要设置网络权限 <application android:usesCleartextTraffic="false" //开放明文传输 android:allowBackup="true" android:icon="@drawable/bh" android:label="@string/app_name" android:roundIcon="@drawable/bh_round" android:supportsRtl="true" android:theme="@style/Theme.TCP_LED" tools:ignore="UnusedAttribute"> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> 1、请求联网: <uses-permission android:name="android.permission.INTERNET"/> 2、开放明文传输: android:usesCleartextTraffic="false" 2、MainActivity.java package com.example.tcp_led; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.Socket; import java.UnknownHostException; public class MainActivity extends AppCompatActivity { String a; int b; connectthread lianjie; TextView receive; Socket socket=null; Button connect; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); EditText ip=findViewById(R.id.mEtIP); EditText port=findViewById(R.id.mEtPort); EditText out=findViewById(R.id.mEtOut); receive=findViewById(R.id.receive); connect=findViewById(R.id.mBt1); Button send=findViewById(R.id.mBt7); Button LED1=findViewById(R.id.mBt3); Button LED2=findViewById(R.id.mBt4); Button LED3=findViewById(R.id.mBt5); Button LED4=findViewById(R.id.mBt6); Button Clear=findViewById(R.id.mBt8); // 连接 按键底层代码 connect.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { a=ip.getText().toString(); String c=port.getText().toString(); if("".equals(a)||"".equals(c)){ Toast.makeText(MainActivity.this,"请输入ip和端口号",Toast.LENGTH_SHORT).show(); receive.append("请输入ip和端口号" + "\\r\\n"); } else{b=Integer.parseInt(c); lianjie=new connectthread(); lianjie.start();} } }); // 发送数据 按键底层代码 send.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //子线程中进行网络操作 new Thread(new Runnable() { @Override public void run() { if(socket!=null){ try { String text=out.getText().toString(); lianjie.outputStream.write(text.getBytes()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }else{ runOnUiThread(new Runnable()//不允许其他线程直接操作组件,用提供的此方法可以 { public void run() { // TODO Auto-generated method stub Toast.makeText(MainActivity.this,"请先建立连接",Toast.LENGTH_SHORT).show(); receive.append("请先建立连接" + "\\r\\n"); } }); } } }).start(); } }); // LED1 按键底层代码 其实就是发送数据按键代码基础上修改的,后面三个按键都是 LED1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //子线程中进行网络操作 new Thread(new Runnable() { @Override public void run() { if(socket!=null){ try { String text="1"; lianjie.outputStream.write(text.getBytes()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }else{ runOnUiThread(new Runnable()//不允许其他线程直接操作组件,用提供的此方法可以 { public void run() { // TODO Auto-generated method stub Toast.makeText(MainActivity.this,"请先建立连接",Toast.LENGTH_SHORT).show(); receive.append("请先建立连接" + "\\r\\n"); } }); } } }).start(); } }); // LED2 按键底层代码 LED2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //子线程中进行网络操作 new Thread(new Runnable() { @Override public void run() { if(socket!=null){ try { String text="2"; lianjie.outputStream.write(text.getBytes()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }else{ runOnUiThread(new Runnable()//不允许其他线程直接操作组件,用提供的此方法可以 { public void run() { // TODO Auto-generated method stub Toast.makeText(MainActivity.this,"请先建立连接",Toast.LENGTH_SHORT).show(); receive.append("请先建立连接" + "\\r\\n"); } }); } } }).start(); } }); // LED3 按键底层代码 LED3.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //子线程中进行网络操作 new Thread(new Runnable() { @Override public void run() { if(socket!=null){ try { String text="3"; lianjie.outputStream.write(text.getBytes()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }else{ runOnUiThread(new Runnable()//不允许其他线程直接操作组件,用提供的此方法可以 { public void run() { // TODO Auto-generated method stub Toast.makeText(MainActivity.this,"请先建立连接",Toast.LENGTH_SHORT).show(); receive.append("请先建立连接" + "\\r\\n"); } }); } } }).start(); } }); // LED4 按键底层代码 LED4.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //子线程中进行网络操作 new Thread(new Runnable() { @Override public void run() { if(socket!=null){ try { String text="4"; lianjie.outputStream.write(text.getBytes()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }else{ runOnUiThread(new Runnable()//不允许其他线程直接操作组件,用提供的此方法可以 { public void run() { // TODO Auto-generated method stub Toast.makeText(MainActivity.this,"请先建立连接",Toast.LENGTH_SHORT).show(); receive.append("请先建立连接" + "\\r\\n"); } }); } } }).start(); } }); Clear.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { receive.setText(""); } }); // onCreate } //子线程中进行网络相关操作 // 联网子线程 class connectthread extends Thread { OutputStream outputStream=null; InputStream inputStream=null; @SuppressWarnings("InfiniteLoopStatement") @Override public void run() { //连接 try { socket=new Socket(a, b); runOnUiThread(new Runnable()//不允许其他线程直接操作组件,用提供的此方法可以 { public void run() { // TODO Auto-generated method stub Toast.makeText(MainActivity.this,"连接成功",Toast.LENGTH_SHORT).show(); receive.append("连接成功" + "\\r\\n"); } }); } catch (UnknownHostException e) { // TODO Auto-generated catch block runOnUiThread(new Runnable()//不允许其他线程直接操作组件,用提供的此方法可以 { public void run() { // TODO Auto-generated method stub Toast.makeText(MainActivity.this,"连接失败",Toast.LENGTH_SHORT).show(); receive.append("连接失败" + "\\r\\n"); } }); e.printStackTrace(); }catch (IOException e) { e.printStackTrace(); runOnUiThread(new Runnable()//不允许其他线程直接操作组件,用提供的此方法可以 { public void run() { // TODO Auto-generated method stub Toast.makeText(MainActivity.this,"连接失败",Toast.LENGTH_SHORT).show(); receive.append("连接失败" + "\\r\\n"); } }); } if(socket!=null){ //获取输出流对象 try { outputStream=socket.getOutputStream(); outputStream.write(123); } catch (IOException e) { e.printStackTrace(); } try{ do { final byte[] buffer = new byte[1024];//创建接收缓冲区 inputStream = socket.getInputStream(); final int len = inputStream.read(buffer);//数据读出来,并且返回数据的长度 runOnUiThread(new Runnable()//不允许其他线程直接操作组件,用提供的此方法可以 { public void run() { // TODO Auto-generated method stub receive.append(new String(buffer, 0, len) + "\\r\\n"); } }); } while (true); } catch (IOException ignored) { } } } } // MainActivity } 3、Layout页面布局文件 activity_main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="schemas.android/apk/res/android" xmlns:app="schemas.android/apk/res-auto" xmlns:tools="schemas.android/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" android:background="#f1f3f4"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="TCP客户端" android:textSize="50dp" android:background="#ffffff" android:gravity="center" /> <EditText android:id="@+id/mEtIP" android:layout_width="300dp" android:layout_height="wrap_content" android:inputType="textWebEditText" android:hint="请输入服务器IP" android:drawableStart="@drawable/ic_tree" android:drawablePadding="20dp" android:layout_gravity="center" android:textSize="20sp" android:autofillHints="" /> <!--端口 --> <EditText android:id="@+id/mEtPort" android:layout_width="300dp" android:layout_height="wrap_content" android:inputType="date" android:hint="请输入服务器端口" android:drawableStart="@drawable/ic_tree" android:drawablePadding="20dp" android:layout_gravity="center" android:textSize="20sp" android:autofillHints="" /> <!--发送 --> <EditText android:id="@+id/mEtOut" android:layout_width="300dp" android:layout_height="wrap_content" android:inputType="date" android:hint="请输入发送数据" android:drawableStart="@drawable/ic_tree" android:drawablePadding="20dp" android:layout_gravity="center" android:textSize="20sp" android:autofillHints="" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center"> <Button android:id="@+id/mBt1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="连接" tools:ignore="UsingOnClickInXml" /> <Button android:id="@+id/mBt7" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="发送数据" tools:ignore="UsingOnClickInXml" /> <Button android:id="@+id/mBt8" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="清除" tools:ignore="UsingOnClickInXml" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center"> <Button android:id="@+id/mBt3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="LED1" tools:ignore="UsingOnClickInXml" /> <Button android:id="@+id/mBt4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="LED2" tools:ignore="UsingOnClickInXml" /> <Button android:id="@+id/mBt5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="LED3" tools:ignore="UsingOnClickInXml" /> <Button android:id="@+id/mBt6" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="LED4" tools:ignore="UsingOnClickInXml" /> </LinearLayout> <TextView android:id="@+id/receive" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> </LinearLayout>

布局预览:

        如此app上位机端操作就基本大功告成了,接下来就是下位机C51方面的程序了。 

四、Keil C51单片机源码 #include "reg51.h" #define uchar unsigned char #define uint unsigned int sbit SW1=P1^0; //S1按键 sbit LED1=P1^1; sbit LED2=P1^2; sbit LED3=P1^3; sbit LED4=P1^4; //ESP8266 EN、vcc脚接 vcc 3.3 GND 接地,必须和51共地 //ESP8266 TX 接P3^0, RX 接P3^1 bit flag=0; uchar SendBuf[9]="LED1 ON! "; uchar RecBuf[15]; uchar RecNum=0; void delay_10us(uint us); //延时 void delay(uint n); //延时 void UART_Init(); void UART_SendByte(uchar dat); void ESP8266_SendCmd(uchar *pbuf); void ESP8266_SendData(uchar *pbuf); void ESP8266_ModeInit(void); //WIFI模块初始化 void UART_Irq( ); // 接收信号 void delay_10us(uint us) { while(us--); } void delay(uint n) { uint i,j; for(i=0;i<n;i++) for(j=0;j<100;j++); } void UART_Init() { SCON=0X50; //串口:工作方式1 TMOD=0X20; //定时器:工作方式2 TH1=0xFD; //波特率:9600 TL1=0xFD; ES=0; //禁止串口中断 EA=1; //使能总中断 TR1=1; //启动计数器 } void UART_SendByte(uchar dat) { ES=0; //禁止串口中断 SBUF=dat; //串口发送 while(TI==0); //等待发送结束 TI=0; //发送标志位清零 ES=1; //使能串口中断 } void ESP8266_SendCmd(uchar *pbuf) { while(*pbuf!='\\0') //遇到空格跳出循环 { UART_SendByte(*pbuf); delay_10us(5); pbuf++; } delay_10us(5); UART_SendByte('\\r'); //回车 delay_10us(5); UART_SendByte('\\n'); //换行 delay(1000); } void ESP8266_SendData(uchar *pbuf) { uchar i=0; ESP8266_SendCmd("AT+CIPSEND=0,9"); //发送数据:AT+CIPSEND=<id>,<length> for(i=0;i<=8;i++) { UART_SendByte(*pbuf); delay_10us(5); pbuf++; } } void ESP8266_ModeInit(void) //WIFI模块初始化 { ESP8266_SendCmd("AT+CWMODE=3"); //设置路由器模式 1:Station,,2:AP,3:Station+AP ESP8266_SendCmd("AT+CWSAP=\\"百行\\",\\"12345678\\",11,0"); //设置WIFI热点名称及密码 ESP8266_SendCmd("AT+CIPAP=\\"192.168.4.2\\""); //设置AP的IP地址 ESP8266_SendCmd("AT+RST"); //重新启动wifi模块 ESP8266_SendCmd("AT+CIPMUX=1"); //开启多连接模式 ESP8266_SendCmd("AT+CIPSERVER=1,8080"); //启动TCP/IP 端口为8080 } void main() { P1=0x01; while(SW1); //等待S1键按下 LED1=LED2=LED3=LED4=1; UART_Init(); //串口初始化 ESP8266_ModeInit(); ES=1; //允许串口中断 while(1) { if(flag==1) { flag = 0; ESP8266_SendData(SendBuf); } delay(10); } } void UART_Irq( ) interrupt 4 // 接收信号 { if(RI) { RI=0; RecBuf[RecNum]=SBUF; //接收到网络数据:+IPD,0<id>,1<数据长度>:F<接收的数据> if(RecBuf[0]=='+') RecNum++; else RecNum=0; if(RecNum==10) { RecNum=0; if(RecBuf[0]=='+'&&RecBuf[1]=='I'&&RecBuf[2]=='P'&&RecBuf[3]=='D') { switch(RecBuf[9]) { case '1': P1 = 0xfD;break; case '2': P1 = 0xfB;break; case '3': P1 = 0xf7;break; case '4': P1 = 0xef;break; default:P1 = 0xe0; } SendBuf[3] = RecBuf[9]; flag = 1; } } } } 五、WIFI模块(ESP8266-01S)注意事项

        相比于编写代码,硬件方面就简单多了,就是有一些需要格外注意的事项,也是我在实践中遇到的问题,现在分享给大家。

ESP8266-01S WIFI模块接线
                    TXRXD(P3^0)
                    RXTXD(P3^1)
                    EN3.3V
                    VCC3.3V
                    GNDGND

        这里需要特别注意在TX和RX中,TX代表WIFI模块发送数据,应该和单片机串行数据接收端RXD相连接,RX代表WIFI模块接受数据,应该和单片机串行数据发送端TXD相连接。EN、VCC必须接3.3V电源,另外WIFI模块工作时会发热,属于正常情况。GND接地需要特别注意,WIFI模块必须和51单片机共地,否则单片机将无法正常读取数据。其他引脚悬空就可以了,也就是说WIFI模块只需和51连接三根线即可,两根串行数据线,一根共地线。

六、后述       

本文简单介绍了如何利用Android Studio设计 APP 实现与C51单片机通过WIFI模块通讯控制LED灯亮灭,由于本人也是外行小白,通过多方学习(Copy)终于实现了手机控制单片机,如果对你有用的话一定记得点个赞啊!

Github 源码资源免费下载github/SHUGEX/TCP_LED

CSDN 源码资源积分下载download.csdn/download/weixin_45694843/85238966

 

 

 

 

本文标签: 单片机模块appandroidStudio