2019-06-12 01:52:48 qq_31278537 阅读数 502
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4010 人正在学习 去看看 朱有鹏

用Android Studio 创建Socket客户端向单片机发送数据

首先要跟单片机通信得用到ESP8266WiFi模块

因为我是新手小白,所以ESP8266模块的相关介绍直接贴大佬的博客了
1、ESP8266串口WiFi模块的基本使用
http://www.shaoguoji.cn/2017/01/15/ESP8266-usage/
2、51单片机通过ESP8266模块与手机进行通讯(单片机)
https://blog.csdn.net/qimi923511491/article/details/79284625

之所以写这博客主要是想记个笔记哈,在网上找了好多大佬写的博客大大小小有些问题,应该是方法过时了吧,所以我要把我总结出来的方法贴出来,emmmm

1.先创建界面
在这里插入图片描述
1、界面代码部分

<?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="com.example.wulianprojects.MainActivity"
    android:orientation="vertical">

    <!--android:orientation="vertical",垂直布局,水平布局的话是horizontal-->
    <!--android:layout_width="match_parent",宽度最大化-->
    <!--android:layout_height="wrap_content",高度根据自身-->
    <!--android:background="@mipmap/titlebar_bg",背景-->
    <!--android:gravity="center",水平垂直居中-->
    <!--android:text="登录",控件文字-->
    <!--android:textSize="20sp",控件文字大小-->

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@mipmap/titlebar_bg"
        android:gravity="center">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="客户端"
            android:textColor="@color/themeTextColor"
            android:textSize="20sp" />
    </LinearLayout>

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="服务器IP:"
        android:id="@+id/edGateIp" />

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="通信端口:"
        android:id="@+id/edGateSn" />


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp"
        android:orientation="horizontal"
        android:gravity="center">

        <Button
            android:id="@+id/btnSearch"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textSize="24sp"
            android:text="自动填写"
            android:background="@drawable/btn_bg_round_click"
            android:textColor="@drawable/btn_click_text_color"
            />

        <Button
            android:id="@+id/btnLogin"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textSize="24sp"
            android:text="连接服务器"
            android:background="@drawable/btn_bg_round_click"
            android:textColor="@drawable/btn_click_text_color"/>
    </LinearLayout>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:layout_marginTop="20dp"
        android:text="温馨提示:请在连接服务器WiFi的情况下进行操作哦"
        />



    <!--临时测试专用区域-->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="16sp"
            android:text="数据接收:"/>

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="内容"
            android:id="@+id/sjjs" />
    </LinearLayout>


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="16sp"
            android:text="数据发送:"/>

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="内容"
            android:id="@+id/sjfs" />
    </LinearLayout>

    <Button
        android:id="@+id/fs"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="24sp"
        android:text="发送数据"
        android:background="@drawable/btn_bg_round_click"
        android:textColor="@drawable/btn_click_text_color"/>
        
</LinearLayout>

注意:因为按钮我加了美化,所以要在res文件下的drawable中建俩个.xml布局
具体方法可以参考这位大佬的博客
https://blog.csdn.net/ymszzu/article/details/82756655

新建方法如下
在这里插入图片描述
1、btn_bg_round_click.xml按钮美化布局代码

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="false">
        <shape android:shape="rectangle" >
            <solid android:color="@color/color_white" />
            <corners android:radius="5dp" />
            <stroke android:width="1dp" android:color="#acacac" />
        </shape>
    </item>

    <item android:state_pressed="true" >
        <shape android:shape="rectangle">
            <solid android:color="@color/color_blue" />
            <corners android:radius="5dp" />
            <stroke android:width="1dp" android:color="#acacac" />
        </shape>
    </item>


</selector>

2、btn_click_text_color.xml文字美化布局代码

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_pressed="false" android:color="@color/color_blue"/>
    <item android:state_pressed="true" android:color="@color/color_white"/>

</selector>

3、在res文件下的values中的colors.xml颜色文件中添加两种颜色

    <color name="color_blue">#FFFF00</color>
    <color name="color_white">#00BFFF</color>

总体图片如下:
在这里插入图片描述

2、在AndroidManifest.xml文件中添加WiFi相关的权限

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

在这里插入图片描述

  1. MainActivity.java代码部分
public class MainActivity extends AppCompatActivity {

    //控件定义
    EditText edGateIp, edGateSn;
    Button btnSearch, btnLogin;

    //消息机制
    private Handler messageHandler;

    //开辟一个socket
    Socket socket = null;

    OutputStream OutputStream = null;//定义数据输出流,用于发送数据
    BufferedReader bufferedReader;//声明输入流对象
    InputStream InputStream = null;//定义数据输入流,用于接收数据

    //定义一个逻辑变量,用于判断服务器连接状态
    boolean isConnected = false;

    //用于控制读数据线程是否执行
    boolean RD = false;


    //测试区域
    Button fs;
    EditText sjfs, sjjs;



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //控件绑定
        edGateIp = findViewById(R.id.edGateIp);
        edGateSn = findViewById(R.id.edGateSn);
        btnSearch = findViewById(R.id.btnSearch);
        btnLogin = findViewById(R.id.btnLogin);

        fs=findViewById(R.id.fs);
        sjfs=findViewById(R.id.sjfs);
        sjjs=findViewById(R.id.sjjs);


        //自动填写按钮事件
        btnSearch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //自动填写服务器固定的IP地址跟端口号
                edGateIp.setText("192.168.4.1");
                edGateSn.setText("5000");
            }
        });

        //连接服务器按钮事件
        btnLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //容错机制
                //取出文本框内容,用来判断输入框是否为空
                String ip = edGateIp.getText().toString();
                String sn = edGateSn.getText().toString();

                if((ip== null || ip.length() == 0 )&& (sn== null || sn.length() == 0))
                    Toast.makeText(MainActivity.this, "IP地址、端口号不能为空", Toast.LENGTH_SHORT).show();
                else if(ip== null || ip.length() == 0)
                    Toast.makeText(MainActivity.this, "IP地址不能为空", Toast.LENGTH_SHORT).show();
                else if(sn== null || sn.length() == 0)
                    Toast.makeText(MainActivity.this, "端口号不能为空", Toast.LENGTH_SHORT).show();

                else {
                    //判断服务器连接状态
                    if (isConnected != true) {
                        //创建一条新的Socket连接
                        new ClientThread().start();
                        //按钮文字改变
                        btnLogin.setText("断开连接");
                        //页面消息
                        Toast.makeText(MainActivity.this, "服务器连接成功!", Toast.LENGTH_SHORT).show();
                        //二次判断,服务器是否已连接上
                        if (socket == null) {
                            //没连接的话,按钮文字改为连接服务器,页面消息提示
                            btnLogin.setText("连接服务器");
                            Toast.makeText(MainActivity.this, "连接错误,请检查WiFi是否连上,IP、端口是否输入正确!", Toast.LENGTH_SHORT).show();
                        }

                    } else {
                        //按钮按下的时候已在连接情况下,服务器断开连接
                        if (socket != null) {
                            try {
                                //退出服务器
                                socket.close();
                                //服务器状态改为空
                                socket = null;
                                //服务器连接转态改为空
                                isConnected = false;
                                //读数据线程不执行
                                RD = false;

                                btnLogin.setText("连接服务器");
                                //页面文字显示
                                Toast.makeText(MainActivity.this, "与服务器断开连接!", Toast.LENGTH_SHORT).show();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
        });

        //发送按钮按下状态
        fs.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                    //这里可以用线程也可以不用线程
                    String zt = btnLogin.getText().toString();


                    if(zt == "断开连接"){
                        new sj().start();
                        if(sjfs != null && sjfs.length() > 0){
                            //handlerMessage处理发送信息刷新UI界面
                            Message msgMessage =new Message();
                            msgMessage.obj=sjfs.getText().toString();
                            msgMessage.what=0;
                            messageHandler.sendMessage(msgMessage);
                        }
                        else //页面文字显示
                            Toast.makeText(MainActivity.this, "发送的数据不能为空!", Toast.LENGTH_SHORT).show();
                    }
                    else //页面文字显示
                        Toast.makeText(MainActivity.this, "未连接服务器,请先连接!", Toast.LENGTH_SHORT).show();
            }
        });


        //消息处理机制
        messageHandler = new Handler() { // 等待socket连接成功
            @Override
            public void handleMessage(android.os.Message msgMessage) {
                String sendString="";
                String receiveString="";

                switch (msgMessage.what) {
                    case 0:
                        //append追加显示数据,之前数据不会被替换
                        sendString="用户端发送:"+msgMessage.obj.toString()+"\n";
                        sjjs.append(sendString);
                        break;

                    case 1:
                        receiveString="服务器端发送:"+msgMessage.obj.toString()+"\n";
                        //append追加显示数据,之前数据不会被替换
                        sjjs.append(receiveString);
                        break;
                    default:
                        break;
                }
            }
        };
    }

    //用线程创建Socket连接,线程不允许更新UI(用Handler实现)
    public class ClientThread extends Thread{
        public void run(){
            //定义两个变量用于储存ip跟端口号
            InetAddress GateIp;
            int GateSn;
            try {
                //判断socket的状态,防止重复执行
                if(socket == null){
                    //获取输入的IP地址
                    GateIp = InetAddress.getByName(edGateIp.getText().toString());
                    //获取输入的端口
                    GateSn = Integer.valueOf(edGateSn.getText().toString());
                    //新建一个socket,连接
                    socket = new Socket(GateIp,GateSn);
                    ///获取socket的输出流,接收数据
                    InputStream = socket.getInputStream();


                    //取得输入流、输出流
                    //取得输入流、输出流
                    bufferedReader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    OutputStream=socket.getOutputStream();

                    //接收数据可用子线程也可直接在此线程操作
                    char[] buffer=new char[256];//定义数组接收输入流数据
                    String bufferString="";//定义一个字符接收数组数据
                    int conut =0;//初始化buffer数组长度为0
                    int tag=0;//初识写入数组的位置

                    isConnected=true;

                    //死循环重复接收输入流数据并进行处理
                    while (true) {
                        //当输入流写入buffer数组的长度大于0时即接收到数据时
                        while ((conut=bufferedReader.read(buffer))>0) {
                            //将buffer数组的数据全部写入bufferString字符类型
                            while ( tag<buffer.length) {
                                bufferString=bufferString+buffer[tag];
                                tag++;
                            }
                            //将数据给messageHandler刷新UI界面
                            Message msgMessage =new Message();
                            msgMessage.obj=bufferString;
                            msgMessage.what=1;
                            messageHandler.sendMessage(msgMessage);
                            //初始化数据,以便处理下一条输入流信息
                            tag=0;
                            bufferString="";
                        }
                    }
                }
                //出错提示
                //UnknownHostExceptionDNS解析出错
                //IOException读写文件异常
            } catch (UnknownHostException e) {
                //在命令行打印异常信息在程序中出错的位置及原因
                e.printStackTrace();
            } catch (IOException e) {
                //在命令行打印异常信息在程序中出错的位置及原因
                e.printStackTrace();
            }
        }
    }


//向服务器发送数据子程序
    public class sj extends Thread {
        public void run() {
            //判断连接状态
            if (socket != null) {
                try {
                    //判断输入框是否为空
                    if (sjfs != null && sjfs.length() > 0) {
                        //输入框内容转码后向服务器发送
                        OutputStream.write((sjfs.getText().toString()+"\n").getBytes("utf-8"));
                        //清空缓冲区
                        OutputStream.flush();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } // 连接输出流
            }
        }
    }



}

注意,向模块发送和接收代码必须放在一个子线程中,否者会闪退运行不出来,代码加了很多容错机制,解决了空数据闪退问题哈,虽然有点乱,但还是能用的哈,现学现卖,emmmm,勿喷哈,演示图我就不贴了。。。有点麻烦,懒得调试,另外要用到两个串口调试软件,一般买模块会发资料你,这个我也不贴了,百度好像没存,嗯就是这样。

2018-09-02 11:24:14 XiaoCaiDaYong 阅读数 9594
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4010 人正在学习 去看看 朱有鹏

上一篇是写关于自写Android手机APP给单片机下发数据的,这次我将写一下APP如何接受单片机数据。

其实使用调试助手,或者别人开的的APP同样能够实现接受单片机数据,但想学习的,我还是建议能够自己写一个Android软件,这样从底层到上层都能学到很多东西。

APP页面如图:

硬件连接如图:

单片机的硬件代码:

if(0 == P32)    //  通过串口给手机发送字符串   wantin
        {
            ms_delay(400);
            if(0 == P32)
            {
                ES = 0;
            	TI = 1; 
            	printf("AT+CIPSEND=?\r\n");
            	LED();
            	ms_delay(1000) ;
                printf("AT+CIPSEND=0,10\r\n");
            	LED();
            	ms_delay(1000) ;
                printf("wangting\r\n");
            	LED(); 
            	ms_delay(1000) ;
            	LED();
            	ms_delay(1000) ;
            	LED();
            	ms_delay(1000) ;
            	while(!TI);
            	TI = 0;
            	ES = 1;
            }
            while(0 == P32);
        } 

我这里只贴了串口发送的代码,它的数据是通过按键进行发送的,以前的文章也有写到。上发的内容为wangting.

app代码部分:

package com.open_open_wt.myapplication;

import android.os.Handler;
import android.os.Message;
import android.support.v7.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.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private ConnectThread mConnectThread;
    private Socket mSocket;
    private EditText mEIP;
    private EditText mEPort;
    private String mStrIP;
    private int miPort;
    private Button mBtnConn;
    private Button mBtnRecData;
    private TextView mtvRec;
    private String line;
    private String mstr;
    private int flag=1;
    BufferedReader br;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mEIP=(EditText)findViewById(R.id.eTIP);
        mEPort=(EditText)findViewById(R.id.eTPort);
        mBtnConn=(Button)findViewById(R.id.btConn);
        mBtnRecData=(Button)findViewById(R.id.bRecData);
        mtvRec=(TextView)findViewById(R.id.tVRecData);
        mBtnConn.setOnClickListener(this);
        mBtnRecData.setOnClickListener(this);

    }
    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.btConn:
                //  连接
                if(mSocket == null || !mSocket.isConnected()){
                    mStrIP=mEIP.getText().toString();
                    miPort=Integer.valueOf(mEPort.getText().toString());
                    mConnectThread=new ConnectThread(mStrIP,miPort);
                    mConnectThread.start();
                }
                if(mSocket != null && mSocket.isConnected()){
                    try {
                        mSocket.close();
                        mSocket=null;
                        mBtnConn.setText("连接");
                        Toast.makeText(MainActivity.this,"连接断开",Toast.LENGTH_LONG).show();
                    }catch (IOException e){
                        e.printStackTrace();
                    }
                }
                break;
            case R.id.bRecData:
                if(mSocket != null && mSocket.isConnected()){
                    if(flag==1){
                        Toast.makeText(MainActivity.this,"开始接受数据",Toast.LENGTH_LONG).show();
                        mBtnRecData.setText("Doing recDta");
                        GetTCPstring();
                        flag=(-1)*flag;
                    }
                    else{
                        Toast.makeText(MainActivity.this,"停止接受数据",Toast.LENGTH_LONG).show();
                        mBtnRecData.setText("RecData");
                        try {
                            mSocket.getInputStream().close();
                        } catch (IOException e) {
                            e.printStackTrace();
                            Toast.makeText(MainActivity.this,"停止接受数据失败",Toast.LENGTH_LONG).show();
                        }
                        flag=(-1)*flag;
                    }

                }
                else{
                    mBtnRecData.setText("RecData");
                    Toast.makeText(MainActivity.this,"开始接受数据失败",Toast.LENGTH_LONG).show();
                }

                break;

        }

    }

    private void GetTCPstring(){
        new Thread(){
            public void run(){
                try{
                    char[] cbuf=new char[10];
                    br=new BufferedReader(new InputStreamReader(mSocket.getInputStream()));
                    while (true){
                        if(br.ready()){
                            br.read(cbuf,0,10);
                            line=String.valueOf(cbuf);
                            handler.sendMessage(handler.obtainMessage());
                        }
                    }
            }catch(IOException e){
                    e.printStackTrace();
                    Toast.makeText(MainActivity.this,"接受数据失败",Toast.LENGTH_LONG).show();

                }
        }
        }.start();
    }

    //  消息句柄
    private Handler handler=new Handler(){
      public void handleMessage(Message msg){
          super.handleMessage(msg);
          mstr+=line;
          if(mstr.length()>500){
              mstr="";
          }
          mtvRec.setText(mstr);

      }
    };

    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);
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mBtnConn.setText("断开");
                        Toast.makeText(MainActivity.this,"连接成功",Toast.LENGTH_LONG).show();
                    }
                });

            }catch (IOException e){
                e.printStackTrace();
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(MainActivity.this,"连接失败",Toast.LENGTH_LONG).show();
                    }
                });
            }
        }
    }
}

刚开始学习Android代码,写的逻辑一定有问题,因为我测试了一下,会有闪退问题,但功能是能用的。手机连接到WIFI模块的WIFI上,然后打开我编写的APP——连接——接收数据按钮按下,接收的数据如图:

能够正确接收数据了,这就说明,手机基本能正确接收单片机上发的数据了,后期还需要不断的研究与深化。

APP源码,大家可以下载:https://download.csdn.net/download/xiaocaidayong/11215938          RecDataWt.rar

2018-05-07 18:17:02 qq_41570228 阅读数 11885
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4010 人正在学习 去看看 朱有鹏

  51单片机是市面上比较普及的单片机种类,同时也深受广大电子爱好者的青睐。在51单片机的众多功能中串口通信占据了重要的地位,通过串口通信,我们可以实现51单片机与其他设备的互联,增加了学习的趣味性。

  HC-05蓝牙模块为主从一体的蓝牙模块,并可与手机实现实时的通信。将单片机的串口通信通过HC-05进行扩展从而实现无线通信,更可使用手机来控制单片机完成工作。

 要完成单片机与Android手机的无线通信,首先我们要在写好单片机的控制程序,因为HC-05只是对串口通信功能进行延伸, 并不能独立完成通信。

 编写串口通信的程序中首先我们要对串口的配置进行初始化

void UartConfigurationInit()
{
    TMOD=0x20;  //设置定时器1工作方式为方式2   
    TH1=0xfd;  	  //波特率9600
    TL1=0xfd;  
    TR1=1;      //启动定时器1     
    SM0=0;SM1=1;      //串口方式1         
    REN=1;      //允许接收   
    PCON=0x00;  //关倍频   
    ES=1;       //开串口中断   
    EA=1;       //开总中断
}

配置好串口后,在编写发送函数前我们需要对串口发送数据的原理有个了解:

转码过程:

发送十进制数:查询ASCII码表后发送相应的字符 ,如SBUF=65;则会收到字符‘A’;

发送字符:原样输出

发送字符串:强行对SBUF传递字符串会造成输出乱码,得不到想要的结果。想要发送字符串则需要运用指针,每次发送时发送指针指向的那个字符,因为发送频率很快,最后输出时组合起来还是一条字符串。

实现整数转为字符串发送:

   0x30对应的字符‘0’,当我们要发送一个整数时,需要将该整数按最高位到最低位得到顺序依次发送,发送时需要在原始数据上加上0x30或者48,则会输出相应的数字字符。


字符发送函数:

void PostChar(uchar character)  
{     
	    SBUF=character;   //发送单个字符
	    while(!TI);TI=0; //发送完成标志 
}

字符串的发送需要依靠字符发送函数来实现:

  这里加了一个延时函数delay(),因为在实际与手机通信中我发现发送速度过快会产生严重的数据丢失,因此加上一个延时可以较好的保证数据的准确度,具体延时数据根据大家实际需要调整。

void  PostString(uchar *p)  
{  
	    while(*p)  	   //若指针指向的地址为空,则跳出循环
	    {  
	        PostChar(*p); //指针第一次默认指向首地址
			delay(20);  //延时,作用为提高发送准确度
	        p++;  
	    }	  
}

十进制数据发送:

 因为十进制数据不能直接发送,所以要先加上0x30或者48后再转为字符型。

void IntConversionChar(uint number)
{
       uint model;	//模
       uint numberByte; //十进制数据不同位上的值

     for(model=1000;model>=1;model=model/10) //model的取值根据实际需要选择,选择过大会浪费资源

      {
            numberByte = number/model;	//相除取整
			//当取到整数数据的最高位时,将其加上0x30或者48并转为字符型后发送
            if(numberByte >=1 ) PostChar((uchar)(numberByte%10+0x30));
      		//if(numberByte >=1 ) PostChar((unsigned char)(numberByte%10+48));
	  }	
}

以上就是51单片机使用HC-05蓝牙模块与Android手机通信的程序的要点和原理。

完整程序:

https://download.csdn.net/download/qq_41570228/10398277



2018-04-03 11:15:51 qqr99000 阅读数 666
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4010 人正在学习 去看看 朱有鹏

一、问题出现

       用单片机发送指令时候,有时候是按照16进制发送的,如果上位机,这里的上位机包含用JAVA,Android或者其他软件编译的,接收数据时,不做解析会出现乱码现象。

二、问题解决

1、单片机发送前,就使用正常字符串格式

2、上位机接收时候进行数据转换,代码如下:原理还是比较简单的,如果了解字符之间转换格式,一会就看明白了。代码也不多。

private static final String HEX_CODE = "0123456789ABCDEF";

    public static String byteArrayToHexString(byte[] bs) {
        int _byteLen = bs.length;
        StringBuilder _result = new StringBuilder(_byteLen * 2);
        for (int i = 0; i < _byteLen; i++) {
            int n = bs[i] & 0xFF;
            _result.append(HEX_CODE.charAt(n >> 4));
            _result.append(HEX_CODE.charAt(n & 0x0F));
        }
        return String.valueOf(_result);
    }
//Sokect接收流中这样处理。
while (true) {
    // 每次接收的数据
    byte[] data = new byte[1024];
    int len = bis.read(data);
    String data1 = byteArrayToHexString(Arrays.copyOf(data, len));
    System.out.println(data1);// 就是这儿输出的data1是乱码
}

2016-07-04 12:01:58 qq_29918347 阅读数 4708
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4010 人正在学习 去看看 朱有鹏

前段时间一直在加班,单身狗的周末也搭进去了…只是为了解决一个莫名其妙的bug,不过最终bug还是拜倒在了朕的强大气场下,哈哈哈,现在就在这里好好吐槽下软件遇上硬件的坑;

先简单说说情景:软件需要给硬件设备的单片机发送一串byte数组,用于打开软件与硬件设备之间的通讯通道,软件命令发送完,接着就打开一个线程用于接收从硬件设备回传的数据,然后开始做其他的一些操作。但是现在出现的问题是命令发送了,会出现偶尔接收不到数据,刚开始还以为是硬件部门的问题,请硬件部门的人过来协助,结果发现软件发送的指令单片机也是接收到了的,那么是我写的程序有问题?NO~

中间的各种脑残调试,这里就不细说了,说说最终得到的分析结果:从软件发送指令到单片机接收到指令,其实是需要时间的,至于这个时间大概在两百毫秒以内,而软件在发送了这段指令之后,就直接执行后面的接收操作,但是这个时候单片机有可能还没有接收到软件发送的指令,通道没有打开,而我的程序已经在开始读取数据了(读个鬼啊,什么都没有),这样就造成了我的操作界面一直处于等待的状态…那为什么有时候又可以读取到数据了?因为从发送数据到单片机接收数据,这个时间不可控的,为什么不可控,这里我猜测跟系统资源及单片机内的程序有关,这种情况就好像当电脑内存紧张时,软件运行速度会降低一样(当然这种情况要毕竟很少),而单片机程序部分如果接收到指令后还做了其他耗时操作这个也是有可能的…知道了原因,那么在程序发送命令后,就简单粗暴的强制线程睡眠一秒Thread.sleep(200),其实这种方法,依然存在问题,正确的最好的办法是让单片机在接收到我发出的命令后返回一个响应(但是要跟硬件部门沟通了~~~)

没有更多推荐了,返回首页