欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android单片机与蓝牙模块通信实例代码

程序员文章站 2024-03-02 10:38:04
啦啦毕业了,毕业前要写毕业设计,需要写一个简单的蓝牙app进行交互,通过参考网上资料,问题顺利搞定,下面小编把具体实现思路分享给大家,供大家参考。 1、android蓝牙...

啦啦毕业了,毕业前要写毕业设计,需要写一个简单的蓝牙app进行交互,通过参考网上资料,问题顺利搞定,下面小编把具体实现思路分享给大家,供大家参考。

1、android蓝牙编程

  蓝牙3.0及以下版本编程需要使用uuid,uuid是通用唯一识别码(universally unique identifier),这是一个软件构建的标准,也是被开源基金会组织应用在分布式计算环境领域的一部分。在蓝牙3.0及下一版本中,uuid被用于唯一标识一个服务,比如文件传输服务,串口服务、打印机服务等,如下:

#蓝牙串口服务 
serialportserviceclass_uuid = '{00001101-0000-1000-8000-00805f9b34fb}' 
lanaccessusingpppserviceclass_uuid = '{00001102-0000-1000-8000-00805f9b34fb}'
#拨号网络服务 
dialupnetworkingserviceclass_uuid = '{00001103-0000-1000-8000-00805f9b34fb}'
#信息同步服务 
irmcsyncserviceclass_uuid = '{00001104-0000-1000-8000-00805f9b34fb}' 
sdp_obexobjectpushserviceclass_uuid = '{00001105-0000-1000-8000-00805f9b34fb}'
#文件传输服务 
obexfiletransferserviceclass_uuid = '{00001106-0000-1000-8000-00805f9b34fb}' 
irmcsynccommandserviceclass_uuid = '{00001107-0000-1000-8000-00805f9b34fb}'

  蓝牙的连接有主从设备,提供服务的可以认为是从设备。主设备通过uuid访问从设备提供具有相同uuid的服务,从而建立客服端—服务器(c/s)模式。

2、编程步骤

android使用蓝牙,需要获得权限,蓝牙权限获得代码如下:

<!-- 蓝牙权限 -->
<uses-permission android:name="android.permission.bluetooth"/>
<uses-permission android:name="android.permission.bluetooth_admin"/>

获取本地蓝牙适配器,如果蓝牙未开启,开启蓝牙设备:

bluetoothadapter = bluetoothadapter.getdefaultadapter();
if (bluetoothadapter == null) {
// device does not support bluetooth
return;
}
// 开启蓝牙
int request_enable_bt = 1;
if (!bluetoothadapter.isenabled()) {
intent intent = new intent(bluetoothadapter.action_request_enable);
startactivityforresult(intent, request_enable_bt);
}

搜索已配对的蓝牙设备,并添加到已配对列表中:

// 查询配对设备
list<string> devices = new arraylist<string>();
set<bluetoothdevice> bondeddevices = bluetoothadapter.getbondeddevices();
for (bluetoothdevice device : bondeddevices) {
devices.add(device.getname() + "-" + device.getaddress());
}

搜索未配对蓝牙设备,并添加到未配对列表:

mbluetoothadapter.startdiscovery();
//开始收索 搜索接收函数: 
final broadcastreceiver mreceiver = new broadcastreceiver() {
public void onreceive(context context, intent intent) { 
string action = intent.getaction(); // when discovery finds a device 
if (bluetoothdevice.action_found.equals(action)) {
// get the bluetoothdevice object from the intent 
bluetoothdevice device = intent.getparcelableextra(bluetoothdevice.extra_device); 
// add the name and address to an array adapter to show in a listview 
marrayadapter.add(device.getname() + "\n" + device.getaddress()); 
}
}
};
// 收索接收函数需要注册: 
// register the broadcastreceiver 
intentfilter filter = new intentfilter(bluetoothdevice.action_found); 
registerreceiver(mreceiver, filter); // don't forget to unregister during ondestroy

如果是服务器端,需要建立监听,注意监听的是某个服务的uuid,服务器监听类如下:

private class connectthread extends thread {
private final string my_uuid = "00001101-0000-1000-8000-00805f9b34fb";
private final bluetoothsocket socket;
private final bluetoothdevice device;
public connectthread(bluetoothdevice device) {
this.device = device;
bluetoothsocket tmp = null;
try {
tmp = device.createrfcommsockettoservicerecord(uuid.fromstring(my_uuid));
} catch (ioexception e) {
e.printstacktrace();
}
this.socket = tmp;
}
public void run() {
bluetoothadapter.canceldiscovery();
try {
socket.connect();
connectedthread = new connectedthread(socket);
connectedthread.start();
} catch (ioexception e) {
try {
socket.close();
} catch (ioexception ee) {
ee.printstacktrace();
}
return;
}
//manageconnectedsocket(socket);
}
public void cancel() {
try {
socket.close();
} catch (ioexception e) {
e.printstacktrace();
}
}
}

客户端与服务器端建立连接成功后,需要connectedthread类接收发送数据:

// 客户端与服务器建立连接成功后,用connectedthread收发数据
private class connectedthread extends thread {
private final bluetoothsocket socket;
private final inputstream inputstream;
private final outputstream outputstream;
public connectedthread(bluetoothsocket socket) {
this.socket = socket;
inputstream input = null;
outputstream output = null;
try {
input = socket.getinputstream();
output = socket.getoutputstream();
} catch (ioexception e) {
e.printstacktrace();
}
this.inputstream = input;
this.outputstream = output;
}
public void run() {
byte[] buff = new byte[1024];
int bytes;
while (true) {
try {
bytes = inputstream.read(buff);
string str = new string(buff, "iso-8859-1");
str = str.substring(0, bytes);
log.e("recv", str);
} catch (ioexception e) {
e.printstacktrace();
break;
}
}
}
public void write(byte[] bytes) {
try {
outputstream.write(bytes);
} catch (ioexception e) {
e.printstacktrace();
}
}
public void cancel() {
try {
socket.close();
} catch (ioexception e) {
e.printstacktrace();
}
}
}

  到此为止就是蓝牙开发的大致步骤,其中没有涉及到蓝牙客户端建立连接类,不过可查阅ble和经典蓝牙android开发。

3、毕设蓝牙app介绍

  毕设蓝牙app需要接收单片机通过蓝牙模块发送上来的数据,并且蓝牙app也可以给单片机发送数据来进行控制。页面布局如下,一个是整体页面,一个是设置页面,测试手机是魅蓝note。因为毕设做的是十字路口红绿灯控制系统,所有页面布局有4个led灯,分别代表路口的4个红绿灯,会根据时间不同显示不同的颜色(红/绿/黄),并且会显示倒计时,最后来一张红绿灯系统整体图。

Android单片机与蓝牙模块通信实例代码Android单片机与蓝牙模块通信实例代码Android单片机与蓝牙模块通信实例代码

activity_main.xml文件如下:

<?xml version="1.0" encoding="utf-8"?>
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="wrap_content" android:paddingleft="@dimen/activity_horizontal_margin"
android:paddingright="@dimen/activity_horizontal_margin"
android:paddingtop="@dimen/activity_vertical_margin"
android:paddingbottom="@dimen/activity_vertical_margin" tools:context=".mainactivity">
<linearlayout
android:id="@+id/linear_layout_top"
android:layout_alignparenttop="true"
android:layout_width="match_parent"
android:layout_height="40dp">
<textview
android:id="@+id/notice_view"
android:layout_width="0dp"
android:layout_height="40dp"
android:text="蓝牙未开启"
android:layout_weight="3"/>
<textview
android:id="@+id/notice_recv_view"
android:layout_width="0dp"
android:layout_height="30dp"
android:layout_weight="3"/>
<textview
android:id="@+id/notice_send_view"
android:layout_width="0dp"
android:layout_height="30dp"
android:layout_weight="3"/>
<button
android:id="@+id/turn_on_off"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_weight="2"
android:text="on"/>
</linearlayout>
<textview
android:id="@+id/led1"
android:layout_centerhorizontal="true"
android:layout_below="@+id/linear_layout_top"
android:layout_width="40dp"
android:layout_height="20dp"
android:gravity="center"
android:text="led1"/>
<textview
android:id="@+id/led0"
android:layout_centerhorizontal="true"
android:layout_below="@+id/led1"
android:layout_width="40dp"
android:layout_height="20dp"
android:gravity="center"
android:text="+"/>
<textview
android:id="@+id/led3"
android:layout_below="@+id/led1"
android:layout_toleftof="@+id/led1"
android:layout_width="40dp"
android:layout_height="20dp"
android:gravity="center"
android:text="led3"/>
<textview
android:id="@+id/led2"
android:layout_centerhorizontal="true"
android:layout_below="@+id/led3"
android:layout_width="40dp"
android:layout_height="20dp"
android:gravity="center"
android:text="led2"/>
<textview
android:id="@+id/led4"
android:layout_below="@+id/led1"
android:layout_torightof="@+id/led1"
android:layout_width="40dp"
android:layout_height="20dp"
android:gravity="center"
android:text="led4"/>
<scrollview
android:id="@+id/scroll_view"
android:layout_below="@+id/led2"
android:layout_above="@+id/linear_layout_bottom"
android:layout_width="match_parent"
android:layout_height="match_parent">
<textview
android:id="@+id/recv_view"
android:text=""
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</scrollview>
<linearlayout
android:id="@+id/linear_layout_bottom"
android:layout_alignparentbottom="true"
android:layout_width="match_parent"
android:layout_height="50dp">
<button
android:id="@+id/clear_recv_view"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="clear" />
<edittext
android:id="@+id/send_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="3"
android:hint="输入框,默认@#结尾"/>
<button
android:id="@+id/send"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="send" />
</linearlayout>
</relativelayout>

mainactivity.java文件如下:

package com.luoxn28.bluetooth;
import android.bluetooth.bluetoothadapter;
import android.bluetooth.bluetoothdevice;
import android.bluetooth.bluetoothsocket;
import android.content.intent;
import android.graphics.color;
import android.os.bundle;
import android.os.message;
import android.support.v7.app.actionbaractivity;
import android.view.menu;
import android.view.menuitem;
import android.view.view;
import android.widget.button;
import android.widget.edittext;
import android.widget.scrollview;
import android.widget.textview;
import android.widget.toast;
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;
public class mainactivity extends actionbaractivity implements view.onclicklistener {
public static final int recv_view = 0;
public static final int notice_view = 1;
private bluetoothadapter bluetoothadapter = null;
private connectthread connectthread = null;
private connectedthread connectedthread = null;
private textview noticeview = null;
private button turnonoff = null;
private textview led0, led1, led2, led3, led4;
scrollview scrollview = null;
private textview recvview = null;
private button clearrecvview = null;
private edittext sendtext = null;
private button send = null;
@override
protected void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.activity_main);
// 获取bluetoothadapter
bluetoothadapter = bluetoothadapter.getdefaultadapter();
if (bluetoothadapter == null) {
// device does not support bluetooth
return;
}
// 注册监听事件
noticeview = (textview) findviewbyid(r.id.notice_view);
turnonoff = (button) findviewbyid(r.id.turn_on_off);
led0 = (textview) findviewbyid(r.id.led0);
led1 = (textview) findviewbyid(r.id.led1);
led2 = (textview) findviewbyid(r.id.led2);
led3 = (textview) findviewbyid(r.id.led3);
led4 = (textview) findviewbyid(r.id.led4);
scrollview = (scrollview) findviewbyid(r.id.scroll_view);
recvview = (textview) findviewbyid(r.id.recv_view);
clearrecvview = (button) findviewbyid(r.id.clear_recv_view);
sendtext = (edittext) findviewbyid(r.id.send_text);
send = (button) findviewbyid(r.id.send);
turnonoff.setonclicklistener(this);
clearrecvview.setonclicklistener(this);
send.setonclicklistener(this);
if (!bluetoothadapter.isenabled()) {
noticeview.settext("蓝牙未开启");
}
else {
noticeview.settext("蓝牙已开启");
}
noticeview.setbackgroundcolor(color.gray);
led0.setbackgroundcolor(color.gray);
led1.setbackgroundcolor(color.gray);
led2.setbackgroundcolor(color.gray);
led3.setbackgroundcolor(color.gray);
led4.setbackgroundcolor(color.gray);
}
private boolean ison = false;
@override
public void onclick(view view) {
switch (view.getid()) {
case r.id.turn_on_off: // 发送'0'或者'1'都可以
if (bluetoothadapter == null || !bluetoothadapter.isenabled()) {
toast.maketext(this, "蓝牙未开启", toast.length_short).show();
break;
}
if (connectedthread == null) {
toast.maketext(this, "未连接设备", toast.length_short).show();
break;
}
string turn_string = "1@#";
connectedthread.write(turn_string.getbytes());
if (ison == false) {
ison = true; // 打开了
turnonoff.settext("off");
led1.settext("");
led2.settext("");
led3.settext("");
led4.settext("");
}
else {
ison = false; // 关闭了
turnonoff.settext("on");
led1.settext("led1");
led2.settext("led2");
led3.settext("led3");
led4.settext("led4");
}
break;
case r.id.clear_recv_view: // 清空接收框
recvview.settext("");
break;
case r.id.send: // 发送数据,默认以"@#"结尾
if (bluetoothadapter == null || !bluetoothadapter.isenabled()) {
toast.maketext(this, "蓝牙未开启", toast.length_short).show();
return;
}
if (connectedthread == null) {
toast.maketext(this, "未连接设备", toast.length_short).show();
break;
}
string inputtext = sendtext.gettext().tostring() + "@#"; // 发送给单片机数据以"@#结尾",这样单片机知道一条数据发送结束
//toast.maketext(mainactivity.this, inputtext, toast.length_short).show();
connectedthread.write(inputtext.getbytes());
break;
default:
break;
}
}
private android.os.handler handler = new android.os.handler() {
public void handlemessage(message msg) {
bundle bundle = null;
switch (msg.what) {
case recv_view:
if (ison == false) {
ison = true;
turnonoff.settext("off");
}
bundle = msg.getdata();
string recv = bundle.getstring("recv");
recvview.append(recv + "\n");
scrollview.fullscroll(scrollview.focus_down); // 滚动到底部
if (recv.isempty() || recv.contains(" ") || recv.contains("#")) {
break;
}
int num = integer.valueof(recv) / 2; // 0-60s
if (num <= 20) {
led1.settext("");
led2.settext("");
led3.settext("");
led4.settext("");
led1.setbackgroundcolor(color.red);
led2.setbackgroundcolor(color.red);
led3.setbackgroundcolor(color.green);
led4.setbackgroundcolor(color.green);
}
else if (num < 30) {
int n = 30 - num;
led1.settext("" + n);
led2.settext("" + n);
if (num < 28) {
led3.setbackgroundcolor(color.green);
led4.setbackgroundcolor(color.green);
}
else {
led3.setbackgroundcolor(color.yellow);
led4.setbackgroundcolor(color.yellow);
}
}
else if (num <= 50) {
led1.settext("");
led2.settext("");
led3.settext("");
led4.settext("");
led1.setbackgroundcolor(color.green);
led2.setbackgroundcolor(color.green);
led3.setbackgroundcolor(color.red);
led4.setbackgroundcolor(color.red);
}
else {
int n = 60 - num;
led3.settext("" + n);
led4.settext("" + n);
if (num < 58) {
led1.setbackgroundcolor(color.green);
led2.setbackgroundcolor(color.green);
}
else {
led1.setbackgroundcolor(color.yellow);
led2.setbackgroundcolor(color.yellow);
}
}
break;
case notice_view:
bundle = msg.getdata();
string notice = bundle.getstring("notice");
noticeview.settext(notice);
break;
default:
break;
}
}
};
@override
public boolean oncreateoptionsmenu(menu menu) {
// inflate the menu; this adds items to the action bar if it is present.
getmenuinflater().inflate(r.menu.menu_main, menu);
return true;
}
@override
public boolean onoptionsitemselected(menuitem item) {
int id = item.getitemid();
if (id == r.id.start_bluetooth) {
if (bluetoothadapter != null) {
// 开启蓝牙
int request_enable_bt = 1;
if (!bluetoothadapter.isenabled()) {
intent intent = new intent(bluetoothadapter.action_request_enable);
startactivityforresult(intent, request_enable_bt);
noticeview.settext("开启蓝牙成功");
//toast.maketext(this, "开启蓝牙成功", toast.length_short).show();
} else {
toast.maketext(this, "蓝牙已开启", toast.length_short).show();
}
}
return true;
}
else if (id == r.id.show_devices) {
if (bluetoothadapter != null) {
if (!bluetoothadapter.isenabled()) {
toast.maketext(this, "蓝牙未开启", toast.length_short).show();
return true;
}
// 查询配对设备
list<string> devices = new arraylist<string>();
set<bluetoothdevice> bondeddevices = bluetoothadapter.getbondeddevices();
for (bluetoothdevice device : bondeddevices) {
devices.add(device.getname() + "-" + device.getaddress());
}
stringbuilder text = new stringbuilder();
for (string device : devices) {
text.append(device + "\n");
}
toast.maketext(this, text, toast.length_short).show();
}
return true;
}
else if (id == r.id.find_devices) {
toast.maketext(this, "该功能暂时不可用", toast.length_short).show();
}
else if (id == r.id.connect_devices) {
if (bluetoothadapter == null || !bluetoothadapter.isenabled()) {
toast.maketext(this, "蓝牙未开启", toast.length_short).show();
return true;
}
// 查询配对设备 建立连接,只能连接第一个配对的设备
list<string> devices = new arraylist<string>();
set<bluetoothdevice> bondeddevices = bluetoothadapter.getbondeddevices();
for (bluetoothdevice device : bondeddevices) {
connectthread = new connectthread(device);
connectthread.start();
//toast.maketext(this, "连接成功", toast.length_short).show();
break;
}
}
return super.onoptionsitemselected(item);
}
private class connectthread extends thread {
private final string my_uuid = "00001101-0000-1000-8000-00805f9b34fb";
private final bluetoothsocket socket;
private final bluetoothdevice device;
public connectthread(bluetoothdevice device) {
this.device = device;
bluetoothsocket tmp = null;
try {
tmp = device.createrfcommsockettoservicerecord(uuid.fromstring(my_uuid));
} catch (ioexception e) {
e.printstacktrace();
}
this.socket = tmp;
}
public void run() {
bluetoothadapter.canceldiscovery();
try {
socket.connect();
connectedthread = new connectedthread(socket);
connectedthread.start();
} catch (ioexception e) {
try {
socket.close();
} catch (ioexception ee) {
ee.printstacktrace();
}
return;
}
//manageconnectedsocket(socket);
}
public void cancel() {
try {
socket.close();
} catch (ioexception e) {
e.printstacktrace();
}
}
}
// 客户端与服务器建立连接成功后,用connectedthread收发数据
private class connectedthread extends thread {
private final bluetoothsocket socket;
private final inputstream inputstream;
private final outputstream outputstream;
public connectedthread(bluetoothsocket socket) {
this.socket = socket;
inputstream input = null;
outputstream output = null;
try {
input = socket.getinputstream();
output = socket.getoutputstream();
} catch (ioexception e) {
e.printstacktrace();
}
this.inputstream = input;
this.outputstream = output;
}
public void run() {
stringbuilder recvtext = new stringbuilder();
byte[] buff = new byte[1024];
int bytes;
bundle tmpbundle = new bundle();
message tmpmessage = new message();
tmpbundle.putstring("notice", "连接成功");
tmpmessage.what = notice_view;
tmpmessage.setdata(tmpbundle);
handler.sendmessage(tmpmessage);
while (true) {
try {
bytes = inputstream.read(buff);
string str = new string(buff, "iso-8859-1");
str = str.substring(0, bytes);
// 收到数据,单片机发送上来的数据以"#"结束,这样手机知道一条数据发送结束
//log.e("read", str);
if (!str.endswith("#")) {
recvtext.append(str);
continue;
}
recvtext.append(str.substring(0, str.length() - 1)); // 去除'#'
bundle bundle = new bundle();
message message = new message();
bundle.putstring("recv", recvtext.tostring());
message.what = recv_view;
message.setdata(bundle);
handler.sendmessage(message);
recvtext.replace(0, recvtext.length(), "");
} catch (ioexception e) {
e.printstacktrace();
break;
}
}
}
public void write(byte[] bytes) {
try {
outputstream.write(bytes);
} catch (ioexception e) {
e.printstacktrace();
}
}
public void cancel() {
try {
socket.close();
} catch (ioexception e) {
e.printstacktrace();
}
}
}
}

menu_main.xml文件如下:

<menu 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" tools:context=".mainactivity">
<item
android:id="@+id/show_devices"
android:title="@string/show_devices"
android:orderincategory="100"
app:showasaction="never" />
<item
android:id="@+id/start_bluetooth"
android:title="@string/start_bluetooth"
android:orderincategory="100"
app:showasaction="never" />
<item
android:id="@+id/find_devices"
android:title="@string/find_devices"
android:orderincategory="100"
app:showasaction="never" />
<item
android:id="@+id/connect_devices"
android:title="@string/connect_devices"
android:orderincategory="100"
app:showasaction="never" />
</menu>

strings.xml文件如下:

<resources>
<string name="app_name">bluetooth</string>
<string name="action_settings">settings</string>
<string name="start_bluetooth">开启蓝牙</string>
<string name="show_devices">查询配对设备</string>
<string name="find_devices">搜索设备</string>
<string name="connect_devices">连接设备</string>
</resources>

到这里整个app已经开发完成,亲测可用,如果有什么错误,欢迎评论指正谈论^_^。

到此,本文全部内容就给大家介绍完了,亲自测试过,代码安全可靠,放心实用,如果有任何问题欢迎给我留言,小编会及时回复的!