这次期末的课程设计做了一个智能灯光控制系统,系统整体的功能不在此赘述,系统主要是要实现下位机同上位机的通信,上位机选用的是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端主要就是接受数据,做出一定处理,还需发送指令给单片机。我用的代码也是在网上找的然后又做了一些修改,源代码出处找不到了。主要代码如下:
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);
}
}
}
};
}
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();
}
}