Android端 同 单片机 利用蓝牙模块的通信实现

控制/MCU

1814人已加入

描述

这次期末的课程设计做了一个智能灯光控制系统,系统整体的功能不在此赘述,系统主要是要实现下位机同上位机的通信,上位机选用的是Android手机端,下位机是52单片机,通过蓝牙模块实现通信。虽然系统很简单,但还是第一次完成的走完从下位机数据采集,数据传输,再到上位机的处理这个流程,故在这里做一个记录,也希望能够帮到有需要的人。

一、下位机通信

下位机选用的是52单片机,数据来自几个传感器,传感器采集到数据后通过串口发送到蓝牙模块,然后蓝牙模块发送到上位机。因代码量较大,所以只在这里贴出传输有关的函数。

//利用串口发送一个字符 void SendOneByte(unsigned char c) { SBUF = c; while(!TI); TI = 0; } //重写putchar函数,就可以直接调用printf()函数向串口发送数据,程序自动将printf()中的数据转换成char调用putchar发送 char putchar(char ch) { ES=0; SBUF=ch; while(!TI); TI=0; ES=1; return 0; } //初始化串口 void InitUART() { TMOD = 0x20; PCON = 0x00; SCON = 0x50; TH1 = 0xFD; TL1 = 0xFD; TR1 = 1; ES = 1; EA = 1; } //串口中断 void UARTInterrupt() interrupt 4 { //RI为1则表示串口接收到数据 if(RI) { RI = 0; r_buf = SBUF; //价格SBUF中的数据赋给r_buf,然后就可以对数据进行处理 } } void main() { InitUART(); while(1) { } }

、蓝牙模块

蓝牙模块我选用的是HC-05,这个模块我之前也没用使用过,查询了一些资料后就能够上手了,感觉还是很好用。模块有六个引脚,如果用的是带一个小按钮的HC-05,EN就不用接;然后VCC和GND分别接电源和地;TXD 和 RXD在配置AT指令的时候分别接单片机的TXD和RXD,但是在正常使用时,HC-05的TXD和RXD分别接单片机的RXD和TXD,这个需要注意;还有一个引脚是state,当有蓝牙连接的时候会置1,将其随意连接到单片机的引脚上。

使用前先利用AT指令集配置模块,设置波特率和主从模式等,然后就可以连线使用。连接后蓝牙模块会进入快闪模式,进入AT指令集后会进入慢闪模式,当有蓝牙设备连接后会进入双闪模式。


三、Android端程序

Android端主要就是接受数据,做出一定处理,还需发送指令给单片机。我用的代码也是在网上找的然后又做了一些修改,源代码出处找不到了。主要代码如下:

1、DeveiceListActivity类 public class DeviceListActivity extends Activity { // 调试用 private static final String TAG = "DeviceListActivity"; private static final boolean D = true; // 返回时数据标签 public static String EXTRA_DEVICE_ADDRESS = "设备地址"; // 成员域 private BluetoothAdapter mBtAdapter; private ArrayAdapter mPairedDevicesArrayAdapter; private ArrayAdapter mNewDevicesArrayAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 创建并显示窗口 requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); //设置窗口显示模式为窗口方式 setContentView(R.layout.device_list); // 设定默认返回值为取消 setResult(Activity.RESULT_CANCELED); // 设定扫描按键响应 Button scanButton = (Button) findViewById(R.id.button_scan); scanButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { doDiscovery(); v.setVisibility(View.GONE); } }); // 初使化设备存储数组 mPairedDevicesArrayAdapter = new ArrayAdapter(this, R.layout.device_name); mNewDevicesArrayAdapter = new ArrayAdapter(this, R.layout.device_name); // 设置已配队设备列表 ListView pairedListView = (ListView) findViewById(R.id.paired_devices); pairedListView.setAdapter(mPairedDevicesArrayAdapter); pairedListView.setOnItemClickListener(mDeviceClickListener); // 设置新查找设备列表 ListView newDevicesListView = (ListView) findViewById(R.id.new_devices); newDevicesListView.setAdapter(mNewDevicesArrayAdapter); newDevicesListView.setOnItemClickListener(mDeviceClickListener); // 注册接收查找到设备action接收器 IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); this.registerReceiver(mReceiver, filter); // 注册查找结束action接收器 filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); this.registerReceiver(mReceiver, filter); // 得到本地蓝牙 mBtAdapter = BluetoothAdapter.getDefaultAdapter(); } @Override protected void onDestroy() { super.onDestroy(); // 关闭服务查找 if (mBtAdapter != null) { mBtAdapter.cancelDiscovery(); } // 注销action接收器 this.unregisterReceiver(mReceiver); } public void OnCancel(View v){ finish(); } /** * 开始服务和设备查找 */ private void doDiscovery() { if (D) Log.d(TAG, "doDiscovery()"); // 在窗口显示查找中信息 setProgressBarIndeterminateVisibility(true); setTitle("查找设备中..."); // 显示其它设备(未配对设备)列表 findViewById(R.id.title_new_devices).setVisibility(View.VISIBLE); // 关闭再进行的服务查找 if (mBtAdapter.isDiscovering()) { mBtAdapter.cancelDiscovery(); } //并重新开始 mBtAdapter.startDiscovery(); } // 选择设备响应函数 private OnItemClickListener mDeviceClickListener = new OnItemClickListener() { public void onItemClick(AdapterView av, View v, int arg2, long arg3) { // 准备连接设备,关闭服务查找 mBtAdapter.cancelDiscovery(); // 得到mac地址 String info = ((TextView) v).getText().toString(); String address = info.substring(info.length() - 17); // 设置返回数据 Intent intent = new Intent(); intent.putExtra(EXTRA_DEVICE_ADDRESS, address); // 设置返回值并结束程序 setResult(Activity.RESULT_OK, intent); finish(); } }; // 查找到设备和搜索完成action监听器 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); // 查找到设备action if (BluetoothDevice.ACTION_FOUND.equals(action)) { // 得到蓝牙设备 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); // 如果是已配对的则略过,已得到显示,其余的在添加到列表中进行显示 if (device.getBondState() != BluetoothDevice.BOND_BONDED) { mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress()); }else{ //添加到已配对设备列表 mPairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress()); } // 搜索完成action } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { setProgressBarIndeterminateVisibility(false); setTitle("选择要连接的设备"); if (mNewDevicesArrayAdapter.getCount() == 0) { String noDevices = "没有找到新设备"; mNewDevicesArrayAdapter.add(noDevices); } } } }; }

2、Client类 public class BTClient extends Activity { private final static int REQUEST_CONNECT_DEVICE = 1; //宏定义查询设备句柄 private final static String MY_UUID = "00001101-0000-1000-8000-00805F9B34FB"; //SPP服务UUID号 private InputStream is; //输入流,用来接收蓝牙数据 private EditText edit0; //发送数据输入句柄 private TextView lightSwitch; private TextView lightStrength; private TextView lightMode; private TextView lightPower; private String switchMsg= ""; private String strengthMsg= ""; private String modeMsg= ""; BluetoothDevice _device = null; //蓝牙设备 BluetoothSocket _socket = null; //蓝牙通信socket boolean bRun = true; boolean bThread = false; boolean timesign=false; private BluetoothAdapter _bluetooth = BluetoothAdapter.getDefaultAdapter(); //获取本地蓝牙适配器,即蓝牙设备 /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //设置画面为主画面 main.xml edit0 = (EditText)findViewById(R.id.Edit0); //得到输入框句柄 lightSwitch = (TextView) findViewById(R.id.lightSwitch); lightStrength=(TextView) findViewById(R.id.lightStrength); lightMode=(TextView) findViewById(R.id.lightMode); lightPower=(TextView) findViewById(R.id.lightpower); lightSwitch.setText("关闭"); lightStrength.setText("8"); lightMode.setText("时间调节模式"); lightPower.setText("无数据"); //如果打开本地蓝牙设备不成功,提示信息,结束程序 if (_bluetooth == null){ Toast.makeText(this, "无法打开手机蓝牙,请确认手机是否有蓝牙功能!", Toast.LENGTH_LONG).show(); finish(); return; } // 设置设备可以被搜索 new Thread(){ public void run(){ if(_bluetooth.isEnabled()==false) { _bluetooth.enable(); } } }.start(); } //发送按键响应 public void onSendButtonClicked(View v){ try{ OutputStream os = _socket.getOutputStream(); //蓝牙连接输出流 modeMsg=edit0.getText().toString(); if(modeMsg.equals("1")||modeMsg.equals("2")||modeMsg.equals("3")) { if(modeMsg.equals("1")) { lightMode.setText("手动调节模式"); lightPower.setText("无数据"); timesign=false; } else if(modeMsg.equals("2")) { lightMode.setText("自动调节模式"); timesign=false; } else if(modeMsg.equals("3")) { lightMode.setText("时间调节模式"); lightPower.setText("无数据"); } } if(timesign) { final int timec = Integer.valueOf(modeMsg).intValue() * 1000; // CountDownTimer cdt = new CountDownTimer(timec, timec) { // @Override // public void onTick(long millisUntilFinished) { // } // // @Override // public void onFinish() { // edit0.setText("3"); // } // }; // cdt.start(); try{ Thread.currentThread().sleep(timec); } catch (InterruptedException e) { e.printStackTrace(); } edit0.setText("3"); } if(modeMsg.equals("3")&& !timesign) timesign=true; byte[] bos = edit0.getText().toString().getBytes(); edit0.setText(""); os.write(bos); }catch(IOException e){ } } //接收活动结果,响应startActivityForResult() public void onActivityResult(int requestCode, int resultCode, Intent data) { switch(requestCode){ case REQUEST_CONNECT_DEVICE: //连接结果,由DeviceListActivity设置返回 // 响应返回结果 if (resultCode == Activity.RESULT_OK) { //连接成功,由DeviceListActivity设置返回 // MAC地址,由DeviceListActivity设置返回 String address = data.getExtras() .getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS); // 得到蓝牙设备 _device = _bluetooth.getRemoteDevice(address); // 用服务号得到socket try{ _socket = _device.createRfcommSocketToServiceRecord(UUID.fromString(MY_UUID)); }catch(IOException e){ Toast.makeText(this, "连接失败!", Toast.LENGTH_SHORT).show(); } //连接socket Button btn = (Button) findViewById(R.id.Button03); try{ _socket.connect(); Toast.makeText(this, "连接"+_device.getName()+"成功!", Toast.LENGTH_SHORT).show(); btn.setText("断开"); }catch(IOException e){ try{ Toast.makeText(this, "连接失败!", Toast.LENGTH_SHORT).show(); _socket.close(); _socket = null; }catch(IOException ee){ Toast.makeText(this, "连接失败!", Toast.LENGTH_SHORT).show(); } return; } //打开接收线程 try{ is = _socket.getInputStream(); //得到蓝牙数据输入流 }catch(IOException e){ Toast.makeText(this, "接收数据失败!", Toast.LENGTH_SHORT).show(); return; } if(bThread==false){ ReadThread.start(); bThread=true; }else{ bRun = true; } } break; default:break; } } //接收数据线程 Thread ReadThread=new Thread(){ public void run(){ int num = 0; byte[] buffer = new byte[1024]; bRun = true; //接收线程 while(true){ try{ while(is.available()==0){ while(bRun == false){} } while(true){ num = is.read(buffer); //读入数据 String s=new String(buffer,0,num); switchMsg=s; strengthMsg=s; if(is.available()==0)break; //短时间没有数据才跳出进行显示 } //发送显示消息,进行显示刷新 handler.sendMessage(handler.obtainMessage()); }catch(IOException e){ } } } }; //消息处理队列 Handler handler= new Handler(){ public void handleMessage(Message msg){ super.handleMessage(msg); } }; //关闭程序掉用处理部分 public void onDestroy(){ super.onDestroy(); if(_socket!=null) //关闭连接socket try{ _socket.close(); }catch(IOException e){} } //连接按键响应函数 public void onConnectButtonClicked(View v){ if(_bluetooth.isEnabled()==false){ //如果蓝牙服务不可用则提示 Toast.makeText(this, " 打开蓝牙中...", Toast.LENGTH_LONG).show(); return; } //如未连接设备则打开DeviceListActivity进行设备搜索 Button btn = (Button) findViewById(R.id.Button03); if(_socket==null){ Intent serverIntent = new Intent(this, DeviceListActivity.class); //跳转程序设置 startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE); //设置返回宏定义 } else{ try{ //关闭连接socket _socket.close(); is.close(); _socket = null; bRun = false; btn.setText("连接"); }catch(IOException e){} } return; } //退出按键响应函数 public void onQuitButtonClicked(View v){ finish(); } }

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 相关推荐

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分