1、单片机实验板功能设计
为验证数据通信内容,让单片机板上的四个按键与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;
}
}
}
2、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控制亮灭。
3、功能演示部分截图