單片機實驗板功能設計
為驗證數據通信內容,讓單片機板上的四個按鍵與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控制亮滅。