发布于2022-06-25 18:33 阅读(516) 评论(0) 点赞(13) 收藏(3)
3、Layout页面布局文件 activity_main.xml
本文将详细介绍如何利用Android Studio设计 APP 实现与C51单片机通过WIFI模块通讯控制LED灯亮灭,本人也是新手刚入门,找了很多资料,但都不得要领,最后终于靠着摸索学习实现了手机与C51模块的WIFI通讯,特来与大家分享,希望对各位能有所帮助。废话不多说,先看效果。
可以看到,该APP基本实现了手机与C51单片机之间的WIFI通讯,手机端可以发送和接收数据,可以选择直接给WIFI发送数据,也可以将发送的数据的发送代码固化为按键,比如我上面的四个LED按键其实底层代码就是按下分别发送“1”、“2”、“3”、“4”来控制四个灯的亮灭。本app只是用来实验手机与C51单片机之间的WIFI通讯,目前来说算是成功了,后续可以通过修改调用该程序实现更复杂的内容,目前我也在朝着这个方向努力`(*>﹏<*)′
首先需要联网别忘了给 Android 添加网络连接权限:
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/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>
<uses-permission android:name="android.permission.INTERNET"/>
android:usesCleartextTraffic="false"
- 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.net.Socket;
- import java.net.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
- }
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/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方面的程序了。
- #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;
- }
- }
- }
- }
相比于编写代码,硬件方面就简单多了,就是有一些需要格外注意的事项,也是我在实践中遇到的问题,现在分享给大家。
ESP8266-01S WIFI模块 | 接线 |
---|---|
TX | RXD(P3^0) |
RX | TXD(P3^1) |
EN | 3.3V |
VCC | 3.3V |
GND | GND |
这里需要特别注意在TX和RX中,TX代表WIFI模块发送数据,应该和单片机串行数据接收端RXD相连接,RX代表WIFI模块接受数据,应该和单片机串行数据发送端TXD相连接。EN、VCC必须接3.3V电源,另外WIFI模块工作时会发热,属于正常情况。GND接地需要特别注意,WIFI模块必须和51单片机共地,否则单片机将无法正常读取数据。其他引脚悬空就可以了,也就是说WIFI模块只需和51连接三根线即可,两根串行数据线,一根共地线。
以上就是今天要讲的内容,本文简单介绍了如何利用Android Studio设计 APP 实现与C51单片机通过WIFI模块通讯控制LED灯亮灭,由于本人也是刚开始学习,本文还有很多不足的地方,目前我的程序也还在开发中,后续我会随时更新文章中不足的部分,欢迎各位有需要的订阅我的这个专栏获取最新内容。
代码已开源:(其实以上就是全部内容了)
Github 源码资源免费下载https://github.com/SHUGEX/TCP_LED
CSDN 源码资源积分下载https://download.csdn.net/download/weixin_45694843/85238966
原文链接:https://blog.csdn.net/weixin_45694843/article/details/124486464
作者:java战神
链接:http://www.javaheidong.com/blog/article/465154/6f7b96649a6b442d5757/
来源:java黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 java黑洞网 All Rights Reserved 版权所有,并保留所有权利。京ICP备18063182号-2
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!