单片机实验板功能设计
为验证数据通信内容,让单片机板上的四个按键与android手机客户端上的四个LED灯相互控制;为达到上述基本实验要求,采用单字符传输数据即可,硬件需设计两块相同的单片机电路板,包含单片机最小系统,四路输入,四路输出,MAX232模块,九针插口,由于Zigbee模块与蓝牙模块即插即用,即分别设计四路插口即可。单片机的功能图如下图所示:
实际单片机效果图为:
单片机模块通过蓝牙模块与安卓客户端连接,进而进行数据的传输。
单片机写入的程序如下:
#include<reg52.h> sbit key1=P2^0;//上 sbit key2=P2^2;//左 sbit key3=P2^1;//右 sbit key4=P2^3;//下 sbit led1=P0^0;//上 sbit led2=P0^3;//左 sbit led3=P0^1;//右 sbit led4=P0^2;//下 void delay(unsigned int xms) { unsigned int i,j; for(i=xms;i>0;i--) for(j=110;j>0;j--); } void Send_bit(unsigned char b) { SBUF=b; while(!TI);//判断是否发送完成 TI=0; } void init(void) { SCON=0x50; TMOD|=0x20; TH1=0xFA; TR1=1; EA=1; } void main() { init(); ES=1; key1=1;//初始化定义按键和小灯泡最开始的值 key2=1; key3=1; key4=1; led1=1; led2=1; led3=1; led4=1; while(1) { if(!key1)//第一个灯的控制上 { delay(10); if(key1==0) { Send_bit(1); } } if(!key2)//第二个灯的控制下 { delay(10); if(key2==0) { Send_bit(2); } } if(!key3)//第三个灯的控制左 { delay(10); if(key3==0) { Send_bit(3); } } if(!key4)//第四个灯的控制右 { delay(10); if(key4==0) { Send_bit(4); } } } } void Serial_INT(void)interrupt 4 { int a; if(RI)//如果有接受到字符 { RI=0; a=SBUF; if(a=='1') { led1=!led1; } if(a=='2') { led2=!led2; } if(a=='3') { led3=!led3; } if(a=='4') { led4=!led4; } if(TI)//判断与此同时是否有发送,在中断过程中只接受而不发送 { TI=0; } } }
android手机客户端
选用安卓手机,编写安卓程序。设计界面完成“连接”、“断开”和“上”、“下”、“左”、“右”四个方向按键,以及读取连接状态的显示。
安卓软件编写环境:
Android Studio 3.1.2
JRE:1.8.0_152-release-1024-b02 amd64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
通过编程完成各按键功能。界面及功能如下图所示:
下面为android端接收单片机传来的数据,实现截图中间四个模拟led灯亮灭的代码,以及读写数据的代码:
// 该Handler从BluetoothChatService中获取信息 private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MESSAGE_STATE_CHANGE: if (D) Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1); switch (msg.arg1) { case BluetoothChatService.STATE_CONNECTED: mTitle.setText(R.string.title_connected_to); mTitle.append(mConnectedDeviceName); mConversationView.setText(null); break; case BluetoothChatService.STATE_CONNECTING: mTitle.setText(R.string.title_connecting); break; case BluetoothChatService.STATE_LISTEN: case BluetoothChatService.STATE_NONE: mTitle.setText(R.string.title_not_connected); break; } break; case MESSAGE_WRITE: byte[] writeBuf = (byte[]) msg.obj; // 自动发送 if (auto == true) { // 自动发送模块 mHandler.postDelayed(runnable, 1000); } else if (auto == false) { mHandler.removeCallbacks(runnable); } // 发送计数 if (outhex == true) { String writeMessage = Data_syn.Bytes2HexString(writeBuf); countout += writeMessage.length() / 2; outcount.setText("" + countout); } else if (outhex == false) { String writeMessage = null; try { writeMessage = new String(writeBuf, "GBK"); } catch (UnsupportedEncodingException e1) { e1.printStackTrace(); } countout += writeMessage.length(); outcount.setText("" + countout); } break; case MESSAGE_READ: byte[] readBuf = (byte[]) msg.obj; //检错误码计算函数 if (inhex == true) { String readMessage = " " + Data_syn.bytesToHexString(readBuf, msg.arg1); fmsg += readMessage; mConversationView.append(readMessage); // 接收计数,更显UI countin += readMessage.length() / 2; incount.setText("" + countin); } else if (inhex == false) { String readMessage = null; try { readMessage = new String(readBuf, 0, msg.arg1, "GBK"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } fmsg += readMessage; mConversationView.append(readMessage); // 接收计数,更新UI countin += readMessage.length(); incount.setText("" + countin); //将字符型的readmessage转换为int型的 int messAge=Integer.valueOf(readMessage); //对接收到的控制指令进行计数,分别表示上下左右的次数 if(messAge==1){ countI=countI+1; //Toast.makeText(BluetoothChat.this,"I:"+countI,Toast.LENGTH_SHORT).show(); }else { if(messAge==2){ countJ=countJ+1; //Toast.makeText(BluetoothChat.this,"J:"+countJ,Toast.LENGTH_SHORT).show(); }else { if (messAge==3){ countK=countK+1; //Toast.makeText(BluetoothChat.this,"K:"+countK,Toast.LENGTH_SHORT).show(); }else { countL=countL+1; //Toast.makeText(BluetoothChat.this,"L:"+countL,Toast.LENGTH_SHORT).show(); } } } //根据上面的次数,进行背景的变换,即模拟led亮灭 switch (messAge){ case 1: { if (countI % 2 == 1) { upled.setImageResource(R.drawable.circle);//更换背景 } else { upled.setImageResource(R.drawable.circleline); } } case 2: { if (countJ % 2 == 1) { downled.setImageResource(R.drawable.circle);//更换背景 } else { downled.setImageResource(R.drawable.circleline); } } case 3: { if (countK % 2 == 1) { leftled.setImageResource(R.drawable.circle);//更换背景 } else { leftled.setImageResource(R.drawable.circleline); } } case 4:{ if(countL % 2==1) { rightled.setImageResource(R.drawable.circle);//更换背景 }else { rightled.setImageResource(R.drawable.circleline); } } } } break; case MESSAGE_DEVICE_NAME: // 保存已连接设备的名称 mConnectedDeviceName = msg.getData().getString(DEVICE_NAME); Toast.makeText(getApplicationContext(), "连接到 " + mConnectedDeviceName, Toast.LENGTH_SHORT) .show(); break; case MESSAGE_TOAST: Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST), Toast.LENGTH_SHORT) .show(); break; } } };
android端点击上下左右控制单片机端小灯亮灭的代码实现,即点击按钮,发送不同的字符01、02、03、04控制亮灭。