源码传送门

前言

本篇文章将围绕App与单片机的蓝牙通信来说说lz最近进行开发的一些方案与思考

此文分为三部分:

单片机的PWM与串口通信

Android的蓝牙开发

单片机与Android App的通信方案

预览

视频观看:

环境

单片机

单片机:STC89C52

c语言

编写环境:Keil uVision4

烧录:stc-isp-15xx-v6.82

Android

android sdk 16+

Android studio 1.0+

单片机的PWM与串口通信

PWM

我相信PWM的概念大家都应该,如果还很模糊也可以去查查,可以看看这篇文章

设置一个全局变量t,PWM_T,每当定时器中断的时候使t自增1,当t等于100的时候,使之高电平,并让t等于0,当t等于PWM_T的时候,使之低电平,这样,我们就可以通过改变PWM_T的值来改变占空比,从而实现通过目标的电压,使之达到调节的效果(例如调节led灯的亮度,调节电机的速度等)

/****************************************************

定时器0中断模拟PWM

调节led的亮度

****************************************************/

int t = 0;

int PWM_T = 0; //占空比控制变

void main()

{

TMOD = 0x22; //定时器0,工作模式2,8位定时模式

TH0=210; //写入预置初值(取值1-255,数越大PWM频率越高)

TL0=210; //写入预置值 (取值1-255,数越大PWM频率越高)

TR0=1; //启动定时器

ET0=1; //允许定时器0中断

EA=1; //允许总中断

P1=0xff; //初始化P1,输出端口

PWM_T=30;

while(1)

{

if(!up) //当up按键按下的时候

{

if(PWM_T<100)

{

PWM_T+=1;

}

delay_1ms(20);

}

if(!down) //当down按键按下的时候

{

if(PWM_T>0)

{

PWM_T-=1;

}

delay_1ms(20);

}

}

}

timer0() interrupt 1

{

t++; //每次定时器溢出加1

if(t==100) //PWM周期 100个单位

{

t=0; //使t=0,开始新的PWM周期

P1=0x00; //输出端口,使之低电平

}

if(PWM_T==t) //按照当前占空比切换输出为高电平

{

P1=0xff; //输出端口,使之高电平

}

}

串口通信

上面我们说了PWM调速,那么要达到app实时显示速度,就必须要单片机把速度传输给手机(在这里先用占空比模拟实时速度,道理是一样的,春节快递停了,测速模块还没到),那么我的首选方案肯定是单片机通过蓝牙串口发送给app,app接收并进行显示,这里我的蓝牙模块是hc-06。串口通信很容易,但在这个过程中我发现难的地方是数据格式的定义和数据的解析,也就是说要统一使用16进制,还是10进制,数据的头节点和尾节点的定义,或者说数据每一位所代表的参数,在这里先埋个伏笔,文章的后面会对我自己的方案进行介绍.

Android蓝牙开发

那么android为我们提供的关于蓝牙的api其实已经很强大了,通常的步骤为:

打开蓝牙

搜索蓝牙设备

进行配对

连接

数据的发送与接收

开启蓝牙

private BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

/**

* 打开蓝牙

*/

public static void openBluetooth(@NonNull Activity activity) {

if (INSTANCE.bluetoothAdapter == null) {

// 设备不支持蓝牙

Toast.makeText(INSTANCE.context.getApplicationContext(), "您的设备似乎不支持蓝牙", Toast.LENGTH_SHORT).show();

return;

}

Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

activity.startActivityForResult(enableBtIntent, 6);

}

/**

* 关闭蓝牙

*/

public static void closeBluetooth() {

if (INSTANCE.bluetoothAdapter != null) {

INSTANCE.bluetoothAdapter.disable();

}

}

/**

* 判断蓝牙是否打开

* @return boolean 蓝牙是否打开

*/

public static boolean isBluetoothOpen() {

return INSTANCE.bluetoothAdapter != null && INSTANCE.bluetoothAdapter.isEnabled();

}

搜索附近的蓝牙设备

那么搜索蓝牙设备当然也是调用系统的api即可,然后系统通过广播接收者的方式告诉你,我找到设备了,下面po出代码

/**

* 搜索蓝牙设备

*/

public static void searchDevices() {

INSTANCE.bluetoothDevices.clear();

if (INSTANCE.bluetoothAdapter != null) {

// 寻找蓝牙设备,android会将查找到的设备以广播形式发出去

INSTANCE.bluetoothAdapter.startDiscovery();

}

}

下面是所要接收的广播

/**

* 初始化过滤器

*/

private void initIntentFilter() {

// 设置广播信息过滤

IntentFilter intentFilter = new IntentFilter();

//搜索到设备

intentFilter.addAction(BluetoothDevice.ACTION_FOUND);

intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);

intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);

//蓝牙状态改变

intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);

//绑定状态改变

intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);

// 注册广播接收器,接收并处理搜索结果

registerReceiver(receiver, intentFilter);

}

那么当接收到广播的时候,只需调用BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)就可以取出对应的搜索的蓝牙设备

蓝牙配对

/**

* 绑定设备

*

* @param device BluetoothDevice对象

* @return 是否绑定成功

*/

public static boolean bondDevice(BluetoothDevice device) {

if (INSTANCE.bluetoothAdapter == null) {

return false;

}

// 取消蓝牙设备搜索

INSTANCE.bluetoothAdapter.cancelDiscovery();

try {

if (device.getBondState() == BluetoothDevice.BOND_NONE) {

// 设备未配对,进行配对操作

Method method = BluetoothDevice.class.getMethod("createBond");

method.invoke(device);

}

return true;

} catch (Exception e) {

e.printStackTrace();

}

return false;

}

蓝牙连接

BluetoothSocket socket;

//获取一个uuid值

UUID uuid = uuidCandidates.get(candidate++);

//根据android不同sdk调用不同的api

if (secure) {

socket= device.createRfcommSocketToServiceRecord(uuid);

} else {

socket= device.createInsecureRfcommSocketToServiceRecord(uuid);

}

数据的发送与接收

参考了网上很多关于蓝牙数据通信的做法,好多都是每发送一次数据都关闭socket,但是那样我觉得并不好,因为socket的开启与关闭都是比较耗费资源的,那么我的方案是开启一个线程保持socket连接进行蓝牙数据的接收与发送。

public class TouchMsgThread extends Thread {

private BluetoothSocket socket;

private InputStream inputStream;

private OutputStream outputStream;

private Handler handler;

public TouchMsgThread(BluetoothSocket socket, Handler handler) {

this.socket = socket;

InputStream input = null;

OutputStream output = null;

this.handler = handler;

try {

input = socket.getInputStream();

output = socket.getOutputStream();

} catch (IOException e) {

e.printStackTrace();

}

this.inputStream = input;

this.outputStream = output;

}

public void run() {

while (true) {

try {

int count = 5;

byte[] bytes = new byte[count];

int readCount = 0; // 已经成功读取的字节的个数

while (readCount < count) {

readCount += inputStream.read(bytes, readCount, count - readCount);

}

int s = BinaryToHexString(bytes);

Message message=handler.obtainMessage();

message.what = 333;

message.obj=s;

handler.sendMessage(message);

} catch (Exception e) {

e.printStackTrace();

break;

}

}

}

public void write(byte[] bytes) {

try {

byte[] b = {-1,1,2,3,-1};

outputStream.write(b);

outputStream.flush();

} catch (IOException e) {

e.printStackTrace();

}

}

public void cancel() {

try {

if(outputStream!=null){

outputStream.close();

outputStream = null;

}

if(inputStream!=null){

inputStream.close();

inputStream = null;

}

//socket.close();

} catch (IOException e) {

e.printStackTrace();

}

}

//数据的检验,这里暂时先忽略

public static int BinaryToHexString(byte[] bytes) {

int result = 0;

String temp = "";

for(int i=0;i<5;i++){

byte b = bytes[i];

if(i==2){

temp = Integer.toHexString((b & 0xff));

}

if(i==3){

String hex = Integer.toHexString((b & 0xff));

result = Integer.parseInt(temp+hex, 16);

}

}

return result;

}

}

单片机与Android的通信方案

制定协议

那么上面我们已经讲了单片机与Android怎么样通过蓝牙进行信息交互了,但是在实际应用中,二者之间传递的信息类型太多了,比如实时速度,电量,还有车子灯光打开,或者修改车子密码等等信息,那么单片机或者app要怎么去判断传递过来的是哪种信息呢?那么我们就必须去制定一套数据协议,这里看看我的方案,协议规定:

包头

类型位

数据位

数据位

结束位

0xFF

0x**

0x**

0x**

0xFF

那么我们的数据位可以分别代表高二位和低二位,那么通常情况下这种方案就可以满足我们的需求了。举个例子:

类型位

数据位

数据位

功能

0X00

0X02

0X00

前进

0X00

0X01

0X00

后退

0X00

0X03

0X00

左转

0X00

0X04

0X00

右转

0X00

0X00

0X00

停止

0X02

0x00

0X01

车灯亮

0X02

0x00

0X02

车灯灭

0X03

雷达数据高位

雷达数据低位

发送雷达数据

协议的解析

未完待续

android单片机数据存储,Android与单片机的信息传输方案相关推荐

  1. android界面数据存储,Android应用开发基础之数据存储和界面展现(二)

    Android应用开发基础之数据存储和界面展现(二) 常见布局 相对布局 RelativeLayout 组件默认左对齐.顶部对齐 设置组件在指定组件的右边 android:layout_toRight ...

  2. android之数据存储,Android数据存储之File

    Android使用与其他平台类似的基于磁盘文件系统(disk-based file systems),上篇文章通过SharedPerference来进行数据存储,这次可以使用File.File 对象非 ...

  3. Android私有数据存储,Android获取私有存储目录

    (1)手机存储目录 //通过context对象获取私有目录,/data/data/packagename/filse context.getFileDir().getPath() (2)SD卡目录 1 ...

  4. android SharedPreferences数据存储

    android  SharedPreferences数据存储 很多时候我们开发的软件需要向用户提供软件参数设置功能,例如我们常用的QQ,用户可以设置是否允许陌生人添加自己为好友.对于软件配置参数的保存 ...

  5. 005 Android之数据存储

    文章目录 Android文件系统 Android文件的访问权限 文件访问权限实例 数据存储方式 内部存储 内部存储实例 外部存储 Shared Preferences Shared Preferenc ...

  6. android 储存方案,Android本地数据存储方案(一)

    Android系列的博客主要是记录和总结自己在平时学习之中遇到的问题,方便日后用到时查看,同时也希望对读者有所帮助.不足之处,欢迎指正~ 在说到Android数据存储之前,先提一下数据持久化,所谓数据 ...

  7. Android的数据存储之一------SharedPreferences

    下面将介绍下Android的数据存储,Android提供了5种方式存储数据: 1.SharedPreferences存储数据; 2.文件存储数据: 3.SQLite数据库存储数据: 4.使用Conte ...

  8. android常用的存储方式,Android 常见数据存储方式

    Android 常见数据存储方式有以下三种:1.使用SharedPreferences存储数据:其本质就是一个xml文件,可以保存字符串.布尔值.基础数据.集合等数据.常用于存储较简单的参数设置. 2 ...

  9. Android之数据存储-刘志远-专题视频课程

    Android之数据存储-17742人已学习 课程介绍         本课程介绍了Android中几种数据存储方式,让大家对Android中的数据存储一个系统的认识 课程收益     本课程介绍了A ...

最新文章

  1. Linux stat命令显示文件的状态信息
  2. 手机自动化测试:appium源码分析之bootstrap十二
  3. VTK:Math之EigenSymmetric
  4. (Linux 2.6设备管理机制)kobject和kset
  5. dbunit使用_使用dbUnit,JSON,HSQLDB和JUnit规则进行数据库单元测试
  6. C# ADO.NET
  7. pyqt5 qscrollarea到达_PyQt5如何用QPainter在QScrollArea上画线?
  8. Android github上的好的开源项目汇总
  9. Access数据库—第一章 数据库和表
  10. 看完20000条微博,捋一捋杜蕾斯的营销套路
  11. 拿来即用的网页倒计时组件
  12. VR相机市场杀出一匹黑马,SONICAM备受众筹用户追捧
  13. PHP复姓判断,PHP拆分姓名中的姓氏和名字函数
  14. c语言画一只小猪佩奇
  15. 科技引领未来,银联开放平台诚邀你的加入
  16. 40岁华为程序员被裁,985毕业也逃不过中年危机?
  17. 负载均衡Load Balance(F5 \ nginx \ LVS \ DNS轮询)
  18. JAXB解析XML为对象
  19. 用hadoop2.7.1 mapreduce实现QQ好友推荐功能
  20. Java输入输出(IO)和流的基本概念以及几种方法

热门文章

  1. 理财型保险-不值得购买的保险
  2. 爆笑~做IT业的都不用电脑的
  3. DIV+CSS实现电台列表设计
  4. python使用turtle库绘制一个100长度的十字架_python - 09【turtle库的使用(绘制小猪佩奇)】...
  5. python通过PyYaml库操作yaml文件
  6. HTML5新增的语义化标签
  7. QT软件开发之基础控件--2.4.6 dial刻度盘
  8. 多人对战游戏中的阵营需分与设计
  9. 7大细节预示你面试成功
  10. 我们的下一步目标:Workation