精华内容
下载资源
问答
  • 蓝牙模块 HC系列资料 HC05 HC06 Android开发包

    千次下载 热门讨论 2011-09-26 16:07:23
    蓝牙模块,HC系列较全的资料 附一个Android的应用程序,这是原厂家提供的,自己开发的话可以参考Android蓝牙类.如果是单片机开发的话就是用串口通信,数据量不大的近距离传输可以选择.
  • 代码我忘了在哪找的,只记得是把别人网上的代码稍微整理了一下,之后再加上自己的一些东西就成功了,对,反正就是成功了。很感谢我的一个哥们帮我组建了单片机和蓝牙...一,Android 手机蓝牙Android 手机蓝牙 ...

         代码我忘了在哪找的,只记得是把别人网上的代码稍微整理了一下,之后再加上自己的一些东西就成功了,对,反正就是成功了。很感谢我的一个哥们帮我组建了单片机和蓝牙设备硬件方面的东西,服务器那边也是他写的,灰常感谢...

    在上次的博客中写的手机设备向蓝牙设备中发送消息,代码很乱不是很容易整理,这次我会把源码的地址放到文末,大家可以测试一下。

    一,Android 手机蓝牙 与 Android 手机蓝牙

        从网上抠下来的那个代码,在一个APP中写了接受和发送,也就是说,两部手机用一个APP就可以通信,     

                                                             

    很清楚的看到,两个手机一个APP,在未连接之下点击目标蓝牙会先配对,配对成功之后就可相互发送消息了。

    二,Android 手机蓝牙向HC05设备发送数据

    在这里之前有一个问题导致APP无法使用,最后看到有博客这样写,我是这样理解的,你的目标设备可以分几类,每一类又有几个专门的UUID,使得匹配,差不多就是这个意思。最后也成功了,也是用这个APK ,那接受的部分就交给我哥们了,啊哈哈哈.

    下载地址:https://download.csdn.net/download/h2677lucy/10295861

    layout_buletooth_seacher.xml

    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical">
    
        <LinearLayout
            android:id="@+id/l1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="2"
            android:orientation="vertical">
    
            <ListView
                android:id="@+id/lvDevices"
                android:layout_width="match_parent"
                android:layout_height="250dp" />
    
            <TextView
                android:id="@+id/text_1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_horizontal"
                android:text="[CURRENT ORDER]"
                android:textSize="18sp" />
    
            <TextView
                android:id="@+id/receive_text"
                android:layout_width="match_parent"
                android:layout_height="40dp"
                android:background="#EEEEEE"
                android:gravity="center"
                android:textSize="20dp" />
        </LinearLayout>
    
        <LinearLayout
            android:layout_below="@id/l1"
            android:id="@+id/l2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:layout_weight="3">
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
    
                <Button
                    android:id="@+id/red"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_vertical"
                    android:layout_weight="1"
                    android:text="红灯"
                    android:textSize="10dp" />
    
                <Button
                    android:id="@+id/green"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_vertical"
                    android:textSize="10dp"
                    android:layout_weight="1"
                    android:text="绿灯"/>
                <Button
                    android:id="@+id/blue"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_vertical"
                    android:textSize="10dp"
                    android:layout_weight="1"
                    android:text="蓝灯" />
                <Button
                    android:id="@+id/breath"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_vertical"
                    android:textSize="10dp"
                    android:layout_weight="1"
                    android:text="呼吸灯" />
                <Button
                    android:id="@+id/close_all_led"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_vertical"
                    android:textSize="10dp"
                    android:layout_weight="1"
                    android:text="关灯" />
            </LinearLayout>
    
            <LinearLayout
                android:layout_width="match_parent"
    
                android:padding="5dp"
                android:layout_height="50dp">
    
                <TextView
                    android:id="@+id/textView"
                    android:layout_width="50dp"
                    android:layout_height="match_parent"
                    android:gravity="center"
                    android:background="#31555555"
                    android:text="亮度" />
    
                <SeekBar
                    android:id="@+id/seekBar"
                    style="@style/AlertDialog.AppCompat.Light"
                    android:layout_width="match_parent"
                    android:layout_height="50dp"
                    android:layout_gravity="center_vertical"
                    android:max="800"
                    android:background="#31555555"
                    android:progress="50" />
            </LinearLayout>
    
            <Button
                android:id="@+id/button"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:onClick="onClick_Search"
                android:text="搜索" />
        </LinearLayout>
        <LinearLayout
            android:layout_below="@id/l2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            >
            <TextView
                android:id="@+id/text_2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_horizontal"
                android:text="[RECEIVE ORDER]"
                android:textSize="18sp" />
            <TextView
                android:id="@+id/msg"
                android:layout_width="match_parent"
                android:layout_height="40dp"
                android:background="#EEEEEE"
                android:gravity="center"
                android:textSize="20dp" />
        </LinearLayout>
    
    </RelativeLayout>

    BuletoothClientActivity

    package com.managesoft.nullchen.buletoothdemo;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Set;
    import java.util.UUID;
    
    import android.graphics.Color;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.app.Activity;
    import android.bluetooth.BluetoothAdapter;
    import android.bluetooth.BluetoothDevice;
    import android.bluetooth.BluetoothServerSocket;
    import android.bluetooth.BluetoothSocket;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.util.Log;
    import android.view.View;
    import android.widget.AdapterView;
    import android.widget.AdapterView.OnItemClickListener;
    import android.widget.ArrayAdapter;
    import android.widget.Button;
    import android.widget.ListView;
    import android.widget.SeekBar;
    import android.widget.TextView;
    import android.widget.Toast;
    
    public class BuletoothClientActivity extends Activity implements OnItemClickListener{
        // 获取到蓝牙适配器
        private BluetoothAdapter mBluetoothAdapter;
        // 用来保存搜索到的设备信息
        private List<String> bluetoothDevices = new ArrayList<String>();
        // ListView组件
        private ListView lvDevices;
        // ListView的字符串数组适配器
        private ArrayAdapter<String> arrayAdapter;
        // UUID,蓝牙建立链接需要的
        private final UUID MY_UUID = UUID
                .fromString("00001101-0000-1000-8000-00805F9B34FB");
        // 为其链接创建一个名称
        private final String NAME = "Bluetooth_Socket";
        // 选中发送数据的蓝牙设备,全局变量,否则连接在方法执行完就结束了
        private BluetoothDevice selectDevice;
        // 获取到选中设备的客户端串口,全局变量,否则连接在方法执行完就结束了
        private BluetoothSocket clientSocket;
        // 获取到向设备写的输出流,全局变量,否则连接在方法执行完就结束了
        private OutputStream os;
        // 服务端利用线程不断接受客户端信息
        private AcceptThread thread;
        //定义按钮
        //定义按钮
        private Button close_all_led;
        private Button red1 = null;
        private Button green1 = null;
        private Button blue1 = null;
        private Button breath = null;
        private TextView receive1;
        private SeekBar seekBar;
        private String LED_STATE = "A 红灯亮";
        private TextView re_msg;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.layout_buletooth_seacher);
            red1 = (Button)findViewById(R.id.red);
            green1 = (Button)findViewById(R.id.green);
            blue1 = (Button)findViewById(R.id.blue);
            receive1 = (TextView)findViewById(R.id.receive_text);
            close_all_led = (Button)findViewById(R.id.close_all_led);
            breath = (Button)findViewById(R.id.breath);
            seekBar = (SeekBar)findViewById(R.id.seekBar);
            re_msg = (TextView)findViewById(R.id.msg);
    
            red1.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    LED_STATE = "R";
                    receive1.setText(LED_STATE);
                }
            });
            green1.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    LED_STATE = "G";
                    receive1.setText(LED_STATE);
                }
            });
            blue1.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    LED_STATE = "B";
                    receive1.setText(LED_STATE);
                }
            });
            close_all_led.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    LED_STATE = "E";
                    receive1.setText(LED_STATE);
                }
            });
            breath.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    LED_STATE = "H";
                    receive1.setText(LED_STATE);
                }
            });
            seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
                @Override
                public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
                    if (b){
                        LED_STATE ="{0:"+i+"}";
                        receive1.setText(LED_STATE);
                    }
                }
    
                @Override
                public void onStartTrackingTouch(SeekBar seekBar) {
    
                }
    
                @Override
                public void onStopTrackingTouch(SeekBar seekBar) {
    
                }
            });
            // 获取到蓝牙默认的适配器
            mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
            // 获取到ListView组件
            lvDevices = (ListView) findViewById(R.id.lvDevices);
            // 为listview设置字符换数组适配器
            arrayAdapter = new ArrayAdapter<String>(this,
                    android.R.layout.simple_list_item_1, android.R.id.text1,
                    bluetoothDevices);
            // 为listView绑定适配器
            lvDevices.setAdapter(arrayAdapter);
            // 为listView设置item点击事件侦听
            lvDevices.setOnItemClickListener(this);
    
            // 用Set集合保持已绑定的设备   将绑定的设备添加到Set集合。
            Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices();
            if (devices.size() > 0) {
                for (BluetoothDevice bluetoothDevice : devices) {
                    // 保存到arrayList集合中
                    bluetoothDevices.add(bluetoothDevice.getName() + ":"
                            + bluetoothDevice.getAddress() + "\n");
                }
            }
    
            // 因为蓝牙搜索到设备和完成搜索都是通过广播来告诉其他应用的
            // 这里注册找到设备和完成搜索广播
            IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
            registerReceiver(receiver, filter);
            filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
            registerReceiver(receiver, filter);
    
            // 实例接收客户端传过来的数据线程
            thread = new AcceptThread();
            // 线程开始
            thread.start();
        }
    
        //搜索蓝牙设备
        public void onClick_Search(View view) {
            setTitle("正在扫描...");
            // 点击搜索周边设备,如果正在搜索,则暂停搜索
            if (mBluetoothAdapter.isDiscovering()) {
                mBluetoothAdapter.cancelDiscovery();
            }
            mBluetoothAdapter.startDiscovery();
        }
        // 注册广播接收者
        private BroadcastReceiver receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context arg0, Intent intent) {
                // 获取到广播的action
                String action = intent.getAction();
                // 判断广播是搜索到设备还是搜索完成
                if (action.equals(BluetoothDevice.ACTION_FOUND)) {
                    // 找到设备后获取其设备
                    BluetoothDevice device = intent
                            .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    // 判断这个设备是否是之前已经绑定过了,如果是则不需要添加,在程序初始化的时候已经添加了
                    if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
                        // 设备没有绑定过,则将其保持到arrayList集合中
                        bluetoothDevices.add(device.getName() + ":"
                                + device.getAddress() + "\n");
                        // 更新字符串数组适配器,将内容显示在listView中
                        arrayAdapter.notifyDataSetChanged();
                    }
                } else if (action
                        .equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {
                    setTitle("搜索完成");
                }
            }
        };
    
        // 点击listView中的设备,传送数据
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position,
                                long id) {
            // 获取到这个设备的信息
            String s = arrayAdapter.getItem(position);
            // 对其进行分割,获取到这个设备的地址
            String address = s.substring(s.indexOf(":") + 1).trim();
            Log.d("TAG",address);
            // 判断当前是否还是正在搜索周边设备,如果是则暂停搜索
            if (mBluetoothAdapter.isDiscovering()) {
                mBluetoothAdapter.cancelDiscovery();
            }
            // 如果选择设备为空则代表还没有选择设备
            if (selectDevice == null) {
                //通过地址获取到该设备
                selectDevice = mBluetoothAdapter.getRemoteDevice(address);
            }
            // 这里需要try catch一下,以防异常抛出
            try {
                // 判断客户端接口是否为空
                if (clientSocket == null) {
                    // 获取到客户端接口
                    clientSocket = selectDevice
                            .createRfcommSocketToServiceRecord(MY_UUID);
                    // 向服务端发送连接
                    clientSocket.connect();
                    // 获取到输出流,向外写数据
                    os = clientSocket.getOutputStream();
    
                }
                // 判断是否拿到输出流
                if (os != null) {
                    // 需要发送的信息
                    //String text = "我传过去了";
                    // 以utf-8的格式发送出去
                    os.write(LED_STATE.getBytes("UTF-8"));
                }
                // 吐司一下,告诉用户发送成功
                Toast.makeText(this, "发送信息成功,请查收", 0).show();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                // 如果发生异常则告诉用户发送失败
                Toast.makeText(this, "发送信息失败", 0).show();
            }
    
        }
    
        // 创建handler,因为我们接收是采用线程来接收的,在线程中无法操作UI,所以需要handler
        Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                // TODO Auto-generated method stub
                super.handleMessage(msg);
                // 通过msg传递过来的信息,吐司一下收到的信息
               // Toast.makeText(BuletoothClientActivity.this, (String) msg.obj, Toast.LENGTH_SHORT).show();
                re_msg.setText((String)msg.obj);
            }
        };
    
        // 服务端接收信息线程
        private class AcceptThread extends Thread {
            private BluetoothServerSocket serverSocket;// 服务端接口
            private BluetoothSocket socket;// 获取到客户端的接口
            private InputStream is;// 获取到输入流
            private OutputStream os;// 获取到输出流
    
            public AcceptThread() {
                try {
                    // 通过UUID监听请求,然后获取到对应的服务端接口
                    serverSocket = mBluetoothAdapter
                            .listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
    
            public void run() {
                try {
                    // 接收其客户端的接口
                    socket = serverSocket.accept();
                    // 获取到输入流
                    is = socket.getInputStream();
                    // 获取到输出流
                    os = socket.getOutputStream();
    
                    // 无线循环来接收数据
                    while (true) {
                        // 创建一个128字节的缓冲
                        byte[] buffer = new byte[128];
                        // 每次读取128字节,并保存其读取的角标
                        int count = is.read(buffer);
                        // 创建Message类,向handler发送数据
                        Message msg = new Message();
                        // 发送一个String的数据,让他向上转型为obj类型
                        msg.obj = new String(buffer, 0, count, "utf-8");
                        // 发送数据
                        handler.sendMessage(msg);
                    }
                } catch (Exception e) {
                    // TODO: handle exception
                    e.printStackTrace();
                }
    
            }
        }
    }
    
    最后感谢我的好哥们和那个网友。
    展开全文
  • 蓝牙舵机云台控制花了两天时间实现简单的APP蓝牙舵机云台设置Android蓝牙协议分为两种,SPP协议和BLE(Bluetooth low energy)本项目采用的HC-05蓝牙4.0模块。BLE协议主要适用低功耗,具体其他的概念我暂时也不太明白...

    花了两天时间实现简单的APP蓝牙舵机云台设置

    首先说下遇到的问题,一开始调试,始终是通信不上,就是能检测到设备,但是始终提示

    newState == BluetoothProfile.STATE_DISCONNECTED
    Disconnected from GATT server
    

    根据大佬们介绍,这是报133错误。需要进行

    close();
    connect(mBluetoothDeviceAddress);
    

    然而并没有彻底解决问题。
    探究问题的根本,实际上是协议选择的不对。

    Android蓝牙协议分为两种,SPP协议和BLE(Bluetooth low energy)

    不知道的同鞋请自行科普。协议的选取实际上和蓝牙硬件设备也是有关系的。

    本项目采用的HC-05蓝牙4.0模块。

    BLE协议主要适用低功耗,具体其他的概念我暂时也不太明白。而SPP协议时候数据传输,点对点的收发,与串口收发数据很相似。

    采用SPP协议后,问题很快就得到解决。在前人基础上造车,使我的进步得到很大的提升。这里感谢这位博主qiqiwowo2

    下面介绍下,我主要修改了下数据传输和保存的相关的操作。SPP蓝牙数据传输具体细节就不具体研读了,前辈说的也很仔细。

    由于与硬件通信采用的是数据帧的格式,因此要实现字符串与16进制相关的转换。

    获取十六进制

    private String getHexString(String s) {
    		StringBuilder sb = new StringBuilder();
    		for (int i = 0; i < s.length(); i++) {
    			char c = s.charAt(i);
    			if (('0' <= c && c <= '9') || ('a' <= c && c <= 'f') ||
    					('A' <= c && c <= 'F')) {
    				sb.append(c);
    			}
    		}
    		if ((sb.length() % 2) != 0) {
    			sb.deleteCharAt(sb.length());
    		}
    		return sb.toString();
    	}
    

    字符串转字节数据

    	private byte[] stringToBytes(String s) {
    		byte[] buf = new byte[s.length() / 2];
    		for (int i = 0; i < buf.length; i++) {
    			try {
    				buf[i] = (byte) Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16);
    			} catch (NumberFormatException e) {
    				e.printStackTrace();
    			}
    		}
    		return buf;
    	}
    
    

    字节数组到16进制的转换

    	public static String bytes2Hex(byte[] b) {
    		String ret = "";
    		for (int i = 0; i < b.length; i++) {
    			String hex = Integer.toHexString(b[i] & 0xFF);
    			if (hex.length() == 1) {
    				hex = '0' + hex;
    			}
    			ret += hex.toUpperCase();
    		}
    		return ret;
    	}
    

    通过SharedPreferences 进行读写操作

    读操作

    SharedPreferences sp = getApplicationContext().getSharedPreferences("setting", Context.MODE_PRIVATE);
    valueDegree=sp.getInt("setvalue",0);
    

    写操作

    SharedPreferences sp = getApplicationContext().getSharedPreferences("setting", Context.MODE_PRIVATE);
    SharedPreferences.Editor editor = sp.edit();
    editor.putInt("setvalue",valueDegree);
    editor.commit();
    

    页面布局

    在这里插入图片描述

    前人栽树后人乘凉!!

    感谢的就不说了放个工程文件

    展开全文
  • Android蓝牙2.0app,若需要蓝牙2.0和蓝牙4.0的源码,可以去百度云盘下载。链接:http://pan.baidu.com/s/1eSygHLg 密码:knm6。这里面有介绍和相应蓝牙2.0和蓝牙4.0的源码和app的下载链接
  •  HC-05蓝牙模块为主从一体的蓝牙模块,并可与手机实现实时的通信。将单片机的串口通信通过HC-05进行扩展从而实现无线通信,更可使用手机来控制单片机完成工作。 要完成单片机与Android手机的无...

      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



    展开全文
  • android蓝牙通讯连接Hc-05模块
  • 程序完成了51单片机和手机的字符和数字通信,并有完整的注释,原理介绍可查看我的其他文章。
  • 【周记-Android移动端开发】手机蓝牙与下位机HC-05蓝牙模块通信系统 很久没有写博客了,计划一直都有,但总是被这样或者那样的事情给耽搁了,在此写下文字监督自己:不论长短,每周至少一篇!本文根据自己的实践...

    很久没有写博客了,计划一直都有,但总是被这样或者那样的事情给耽搁了,在此写下文字监督自己:不论长短,每周至少一篇!本文根据自己的实践总结而来,参考前人博客之余,也自己总结和开发了一些功能,在这里给自己备份也分享给大家。不同之处在于:自动打开并搜索蓝牙、修改蓝牙名字、完整接收蓝牙传输数据、修改蓝牙密码、解除蓝牙绑定。


    一、系统框架简介

    系统由上、下位机两部分构成,旨在实现移动端app通过蓝牙通信,将app发送过来的数据存储在下位机的存储单元,与此同时,app也可以通过指令查询下位机的参数设置。系统框架图如下:

    这里写图片描述

    二、软件界面设计

    话不多说,先上软件界面:

    这里写图片描述

    界面主要涉及到按键的监听和Activity的跳转:
    ①按键监听有四种方法,详情可以参考博客
    ②Activity的跳转包括:直接跳startActivity转和带返回跳startActivityForResult转,详情可以参考博客

    二、蓝牙开发

    蓝牙功能 函数名称
    (1)开启&关闭蓝牙 enable()/disable()
    (2)修改蓝牙名字 changeName()
    (3)搜索&显示蓝牙设备 DeviceListActivity
    (4)配对&连接蓝牙 connectToServerSocket(address)
    (5)数据收发 write/ConnectedThread
    (6)修改蓝牙密码 changeMima()
    (7)取消蓝牙配对 removeBond

    本系统中实现的功能如表所示,这里不打算赘述已经开发成熟的功能,可以参考这篇博客,讲得比较清晰,这里只针对自己在开发中添加的功能做一下记录,开发之前需要提醒的有两点:
    ①不要忘记蓝牙权限的设置:

    <uses-permission android:name="android.permission.BLUETOOTH"/>  
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>  

    ②让主程序弹出搜索对话框时,不要忘了intent设置;

    <activity android:name=".DeviceListActivity" 
    android:theme="@android:style/Theme.Dialog" 
    android:label="选取连接设备" 
    android:configChanges="orientation|keyboardHidden"/>

    (1)自动打开并搜索蓝牙

    一般的做法都是监听按键(打开蓝牙按键和搜索设备按键),先打开蓝牙,接着搜索蓝牙。但是,这样做无疑使操作更加复杂,在实际生产和用户使用时并不方便,我要做的效果是程序启动的时候自动打开蓝牙并开始搜索设备,于是乎,出问题了,蓝牙虽然打开了,但是不接着搜索设备了,汗。。。解决办法是,打开蓝牙后延时1秒后开始搜索,这样就行了

    //得到BluetoothAdapter对象
    BluetoothAdapter mBtAdapter = BluetoothAdapter.getDefaultAdapter();
    mBtAdapter.enable();//打开蓝牙
    Timer timer=new Timer();
    TimerTask task=new TimerTask(){//定时1k=new TimerTask(){//定时1秒后搜索设备
        @Override
         public void run() {
            Intent serverIntent = new Intent(MainActivity.this, DeviceListActivity.class); //跳转程序设置
            startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);  //设置返回宏定义
        }          
    };
    timer.schedule(task,1000);

    (3)修改蓝牙名字

    这一功能有两种实现方式,一种是通过蓝牙传输将名字传输给下位机,用单片机操作蓝牙AT指令直接修改蓝牙名字,这样,以后任何手机搜索该蓝牙设备时,显示的名字都是你所修改的名字;另一种方式是在软件层面实现蓝牙名字的修改,其实是搜索出蓝牙设备的ID,然后将其对应到你想修改的名字,并将这一映射存在本地,那么,以后这部手机下次搜索到该设备时,就会显示你所修改的名字,而不影响其他手机对该设备的显示。这种方法各有特色,就看你的需求了。这里就讲讲第二种方式的实现:

    步骤一:搜索蓝牙设备,获取并修改名字

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // TODO Auto-generated method stub
        super.onActivityResult(requestCode, resultCode, data);
        switch(requestCode) {
        case REQUEST_CONNECT_DEVICE:     //连接结果,由DeviceListActivity设置返回
            if (resultCode == Activity.RESULT_OK) { //选择蓝牙
                String address = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
                device = mBluetoothAdapter.getRemoteDevice(address);// 得到蓝牙设备句柄
                connectToServerSocket(address);
                setting_thread=true;
                ConnectedThread thread=new ConnectedThread();
                thread.start();
            }
            break;
            default:break;
        }
    }

    在从DeviceListActivity返回的数据中,其实已经包含蓝牙设备的句柄,我们可以通过device.getName()获取当前连接的蓝牙模块的名字,然后将设备的名字或者其唯一标识符(例如,98:D3:34:90:8A:BC)与新修改的名字做映射保存在本地。
    步骤二:存储设置到本地,下次搜索蓝牙时做映射显示
    使用SharedPreferences存储数据,SharedPreferences是Android平台上一个轻量级的存储类,主要是保存一些常用的配置比如窗口状态,一般在Activity中 重载窗口状态onSaveInstanceState保存一般使用SharedPreferences完成,它提供了Android平台常规的Long长 整形、Int整形、String字符串型的保存。

    //获取SharedPreferences对象
    Context ctx = MainActivity.this;       
    SharedPreferences sp = ctx.getSharedPreferences("SP", MODE_PRIVATE);
    //存入数据
    Editor editor = sp.edit();
    editor.putString("STRING_KEY", "string");
    editor.commit();

    (4)完整接收蓝牙传输数据

    在开发蓝牙数据接收时,发现一个问题:数据有时候会接收不完整。由于项目中的每一位数据返回都十分重要,所以必须保证数据的完整性,要解决这一问题需要清楚的了解如何从InputStream中读取数据,从输入流中读取数据最常用的方法基本上就是如下 3 个 read() 方法:

    ① read () 方法,这个方法从输入流中读取数据的下一个字节。返回 0 到 255 范围内的 int 字节值。如果因为已经到达流末尾而没有可用的字节,则返回值 -1 。
    ② read (byte[] b,int off,int len) 方法,将输入流中最多 len 个数据字节读入 byte 数组。尝试读取 len 个字节,但读取的字节也可能小于该值。以整数形式返回实际读取的字节数。
    ③ read (byte[] b) 方法, 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。以整数形式返回实际读取的字节数。

    对于三种方法的选择,需要看具体项目的需求,如果你能够通过某种方法知道数据的长度,那么建议用第一种方法,每次读取一个字节,保证数据的完整性;如果数据长度不知道,那么就用②或者③,一般③用的比较多,这一方法效率高但是读取数据的长度不确定—-不超过数组b的长度,所以就需要多次读取直到把数据全部读完。

    (5)修改蓝牙密码

    本项目中用的是HC-05蓝牙模块,该模块有接收蓝牙指令模式(即通信模式),和AT指令集模式,一般默认状态为蓝牙通信模式,要想修改蓝牙连接密码,需要将蓝牙模块切换到AT指令集模式,具体过程见下面的流程图:
    这里写图片描述

    (6)解除蓝牙绑定(配对)

    在真实场景中,要想在程序修改完密码后,之前连接的蓝牙设备都无法与该蓝牙模块建立连接,需要解除该模块与手机的绑定,即取消配对。要想解除所有的配对,当然是需要下位机控制蓝牙模块进入AT指令集模式,解除所有绑定,而与此同时,当前修改密码的手机也需要在软件层面解除绑定(配对),这样交互性更强。

    用过Android系统设置(Setting)的人都知道蓝牙搜索之后可以建立配对和解除配对,但是这两项功能的函数没有在SDK中给出,本项目利用Java的反射机制去调用removeBond解除绑定,从而取消本机与该蓝牙模块的配对。具体实现程序如下:当程序接收到下位机传来的修改密码成功的指令后,程序会弹出一个强提示,当用户点击确认按钮之后,程序解除绑定并退出程序。

    if(modify_flag){//修改密码成功
          AlertDialog.Builder builder = new Builder(MainActivity.this);
          builder.setTitle("密码修改成功");
          builder.setMessage("点击确定按钮重新启动!");
          builder.setCancelable(false);
          builder.setPositiveButton("确认", new OnClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int which) {
               try {//接触绑定
                   Method m = device.getClass().getMethod("removeBond", (Class[]) null);
                   m.invoke(device, (Object[]) null);
               } catch (Exception e) {
                    Log.e("erro", e.getMessage());
               }
               setting_thread=false;
               dialog.dismiss();
               mBluetoothAdapter.disable();//关闭蓝牙
               finish();
               System.exit(0);//销毁程序
               }
          });
          builder.setCancelable(false);
          builder.create().show();
    }else {
         Toast.makeText(MainActivity.this, "set failed!", Toast.LENGTH_SHORT).show();
    }
    展开全文
  • 树莓+HC-05蓝牙模块+android数据通信

    千次阅读 2017-03-17 08:14:14
    引脚2连接蓝牙模块vcc,引脚6连接蓝牙模块GND端,引脚8连接RXD端,引脚10连接TXD端。如下图所示 树莓端配置 步骤简介: 1. 配置树莓派的baud rate 默认情况下,树莓派读写串口的boud rate是115200,而HM-05...
  • APP作为信息的发送者与接受者,可以实现手机与手机的通信,手机向HC05发送数据(HC06就不知道了)。解压用AS打开生成APK就可以使用。
  • d手机通信程序 程序完成了51单片机和手机的字符和数字通信,并有完整的注释,原理介绍可查看我的其他文章 前找了很久才找到了,传上来更大家共享下,希望对大家有帮助,欢迎下载或者永久保存。
  • 官网代码不能兼容Android6.0以上版本,本人修改后可兼容使用,本代码是基于AndroidStudio开发
  • Android studio 2.2 安卓端与传统蓝牙HC05/06的通信APP,刚写,亲测可用。
  • 可用于stm32的蓝牙数据传输,内部只有单工,没有手机端到android端口
  • QT on Android 编写蓝牙使用HC-05

    千次阅读 热门讨论 2018-03-01 16:06:36
    前言:  由于17年机械创新设计大赛要使用蓝牙通讯,被迫缺少一个触摸显示器,所以只有在手机上开发界面来进行控制,其中最主要的就是蓝牙...这个蓝牙配置只可在Android上运行!  首先的就是配置一个蓝牙的类...
  • /*这是一个Android里的进度条,模拟飞机的油门推杆,当进度条被改变时获取改变后的值,然后通过蓝牙发送给Arduino扩展的蓝牙模块*/ private OnSeekBarChangeListener verticalSeekBarChangeListener = new ...
  • 背景知识视频教程使用App Inventor创建Android应用​viadean.comArduino微控制器:学习Arduino制作项目 - 国外课栈​viadean.comArduino 训练营:通过项目学习​viadean.com通过使用步进电机可以实现此迷你升降机...
  • Android连接HC05模块接收数据HC05模块Android连接连接蓝牙接收数据说明 HC05模块 要简单阅读 ATK-HC05-V11用户手册,注意其指令以及波特率要求; 通过串口转USB在PC端调试;我用的是:RS232—TTL 以及 友善串口调试...
  • 最近接了个工程自动化的项目,需求是实时接收从单片机传过来的数据,并进行数据分析处理再进行显示,在查阅大量的相关博客和自己踩了不少的坑后,想说把自己的一些经验分享出来给后来人做个参考www。

空空如也

空空如也

1 2 3 4 5 6
收藏数 108
精华内容 43
关键字:

hc05蓝牙android