-
Arduino nano连接HC-05蓝牙Android手机app控制两路舵机
2021-02-25 23:07:10什么是脉冲 脉冲我理解呢就是拉闸放水的这么一个过程:比如说一个水龙头,我们打开开关,水龙头出水,关上开关,水龙头不出水。如果我们在 一个固定的时间内将水龙头开关上拉0-t,那么水龙头出水,然后在 ...什么是脉冲
脉冲我理解呢就是拉闸放水的这么一个过程:比如说一个水龙头,我们打开开关,水龙头出水,关上开关,水龙头不出水。如果我们在
一个固定的时间内将水龙头开关上拉0-t,那么水龙头出水,然后在
另一个固定时间内将水龙头开关下拉t-T,那么水龙头不出水,
如果我们描述出水是1,不出水是0的话,如此循环,那么就可以生成如下的图形。
以上从0-T的这个时间里就形成了一个脉冲,学术定义:在短持续时间内突变,随后又迅速返回其初始值的物理量变化过程称之为脉冲。
如果把水龙头换成电路,接通电路为1,断开电路为0,这样就形成了一个电脉冲。
这中间就有一个变量,那就是时间,根据时间的不同可以改变脉冲的波形。
让舵机改变角度
那么舵机是如何能够自动转向到某一个角度的呢?
你买舵机的时候,某宝,拼某某老板都会告诉你(每个舵机可能都不太一样)。如下图
我买的这个是MG995,当然还有996
并且我还发现了一句话工作死区:4微秒
,为什么会有死区呢,我也不懂,估计是到达一定角度就动不了了吧。
之前从网上下载了好多实例,但是有一个servo.h库文件我是看不懂,后来人家说最好不要用头文件,有bug你也不知道怎样调,后来我就打算不用头文件,自己写,当理解了什么是脉冲,我就知道怎么写了。测试一下成功了。int servopin=4;//定义数字接口4 连接伺服舵机信号线 void setup() { pinMode(servopin,OUTPUT);//设定舵机接口为输出接口 } void loop() { digitalWrite(servopin,HIGH); //将舵机接口电平至高 delayMicroseconds(1500); //能控制这里面的数字就能控制舵机的角度 digitalWrite(servopin,LOW); //将舵机接口电平至低 delay(20); }
就这么简单几句就够了,接好线后,上传代码舵机停在了90°的位置(可能会有所偏差,可以自己摸索)
首先,20ms时基脉冲的意思就是上面提到的,返回其初始值的物理量,也就是下拉电平(关上开关or断开电路)的意思,总间隔2ms的意思是0.5ms至2.5ms这些上拉电平区段,都可以进行设置。当设置上拉电平的时候设置0.5ms,舵机角度就停止在0°,如果是设置2.5ms,舵机角度就停止在180°,同理可证设置1.5ms舵机就转向90°。
那么每增加1°要增加多少ms呢?
(2.5-0.5)/180=0.0111111111111111无限循环小数,换算成微秒约等于11微秒
那么现在控制delayMicroseconds(500);
里面的数字就可以控制角度了,500微秒是初始值,那么0°就等于 0(角度)×11+500=500,45°就等于 45×11+500=995,将角度设置成为变量,改变这个变量,我们就可以控制舵机转向。
定义一个脉冲函数,以上内容可以改写为int servopin=4; //定义数字接口9 连接伺服舵机信号线 int pulsewidth; //定义脉宽变量 int myangle; //定义角度变量 void setup() { pinMode(servopin,OUTPUT); //设定舵机接口为输出接口 } void loop() { pulse(45); } //定义一个脉冲函数 void pulse(int myangle){ pulsewidth=(myangle*11)+550; //(实际测量角度偏差50微秒)将角度转化为550-2530的脉宽值 digitalWrite(servopin,HIGH); //将舵机接口电平至高 delayMicroseconds(pulsewidth); //延时脉宽值的微秒数 digitalWrite(servopin,LOW); //将舵机接口电平至低 delay(20); }
让舵机0°-180°,180°-0°来回动就可以这样写
int servopin=4; //定义数字接口9 连接伺服舵机信号线 int pulsewidth; //定义脉宽变量 int myangle; //定义角度变量 int i=0; void setup() { pinMode(servopin,OUTPUT); //设定舵机接口为输出接口 } void loop() { for (i=0;i<=180;i++){ pulse(i); } for (i=180;i>=0;i--){ pulse(i); } } //定义一个脉冲函数 void pulse(int myangle){ pulsewidth=(myangle*11)+550; //(实际测量角度偏差50微秒)将角度转化为550-2530的脉宽值 digitalWrite(servopin,HIGH); //将舵机接口电平至高 delayMicroseconds(pulsewidth); //延时脉宽值的微秒数 digitalWrite(servopin,LOW); //将舵机接口电平至低 delay(20); }
从以上实例可以看出,我们控制了
myangle
变量就等于控制了舵机串口控制舵机旋转角度
-
蓝牙模块 HC系列资料 HC05 HC06 Android开发包
2011-09-26 16:07:23蓝牙模块,HC系列较全的资料 附一个Android的应用程序,这是原厂家提供的,自己开发的话可以参考Android蓝牙类.如果是单片机开发的话就是用串口通信,数据量不大的近距离传输可以选择. -
(Android Studio)Android 手机设备与HC05 蓝牙设备的通信(成功案例+源码)
2018-03-19 17:18:50代码我忘了在哪找的,只记得是把别人网上的代码稍微整理了一下,之后再加上自己的一些东西就成功了,对,反正就是成功了。很感谢我的一个哥们帮我组建了单片机和蓝牙...一,Android 手机蓝牙 与 Android 手机蓝牙 ...代码我忘了在哪找的,只记得是把别人网上的代码稍微整理了一下,之后再加上自己的一些东西就成功了,对,反正就是成功了。很感谢我的一个哥们帮我组建了单片机和蓝牙设备硬件方面的东西,服务器那边也是他写的,灰常感谢...
在上次的博客中写的手机设备向蓝牙设备中发送消息,代码很乱不是很容易整理,这次我会把源码的地址放到文末,大家可以测试一下。
一,Android 手机蓝牙 与 Android 手机蓝牙
从网上抠下来的那个代码,在一个APP中写了接受和发送,也就是说,两部手机用一个APP就可以通信,
很清楚的看到,两个手机一个APP,在未连接之下点击目标蓝牙会先配对,配对成功之后就可相互发送消息了。
二,Android 手机蓝牙向HC05设备发送数据
在这里之前有一个问题导致APP无法使用,最后看到有博客这样写,我是这样理解的,你的目标设备可以分几类,每一类又有几个专门的UUID,使得匹配,差不多就是这个意思。最后也成功了,也是用这个APK ,那接受的部分就交给我哥们了,啊哈哈哈.
下载地址:https://download.csdn.net/download/h2677lucy/10295861
layout_buletooth_seacher.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <LinearLayout android:id="@+id/l1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="2" android:orientation="vertical"> <ListView android:id="@+id/lvDevices" android:layout_width="match_parent" android:layout_height="250dp" /> <TextView android:id="@+id/text_1" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="[CURRENT ORDER]" android:textSize="18sp" /> <TextView android:id="@+id/receive_text" android:layout_width="match_parent" android:layout_height="40dp" android:background="#EEEEEE" android:gravity="center" android:textSize="20dp" /> </LinearLayout> <LinearLayout android:layout_below="@id/l1" android:id="@+id/l2" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_weight="3"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <Button android:id="@+id/red" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_weight="1" android:text="红灯" android:textSize="10dp" /> <Button android:id="@+id/green" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:textSize="10dp" android:layout_weight="1" android:text="绿灯"/> <Button android:id="@+id/blue" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:textSize="10dp" android:layout_weight="1" android:text="蓝灯" /> <Button android:id="@+id/breath" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:textSize="10dp" android:layout_weight="1" android:text="呼吸灯" /> <Button android:id="@+id/close_all_led" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:textSize="10dp" android:layout_weight="1" android:text="关灯" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:padding="5dp" android:layout_height="50dp"> <TextView android:id="@+id/textView" android:layout_width="50dp" android:layout_height="match_parent" android:gravity="center" android:background="#31555555" android:text="亮度" /> <SeekBar android:id="@+id/seekBar" style="@style/AlertDialog.AppCompat.Light" android:layout_width="match_parent" android:layout_height="50dp" android:layout_gravity="center_vertical" android:max="800" android:background="#31555555" android:progress="50" /> </LinearLayout> <Button android:id="@+id/button" android:layout_width="fill_parent" android:layout_height="wrap_content" android:onClick="onClick_Search" android:text="搜索" /> </LinearLayout> <LinearLayout android:layout_below="@id/l2" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <TextView android:id="@+id/text_2" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="[RECEIVE ORDER]" android:textSize="18sp" /> <TextView android:id="@+id/msg" android:layout_width="match_parent" android:layout_height="40dp" android:background="#EEEEEE" android:gravity="center" android:textSize="20dp" /> </LinearLayout> </RelativeLayout>
BuletoothClientActivity
最后感谢我的好哥们和那个网友。package com.managesoft.nullchen.buletoothdemo; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.UUID; import android.graphics.Color; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothServerSocket; import android.bluetooth.BluetoothSocket; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.ListView; import android.widget.SeekBar; import android.widget.TextView; import android.widget.Toast; public class BuletoothClientActivity extends Activity implements OnItemClickListener{ // 获取到蓝牙适配器 private BluetoothAdapter mBluetoothAdapter; // 用来保存搜索到的设备信息 private List<String> bluetoothDevices = new ArrayList<String>(); // ListView组件 private ListView lvDevices; // ListView的字符串数组适配器 private ArrayAdapter<String> arrayAdapter; // UUID,蓝牙建立链接需要的 private final UUID MY_UUID = UUID .fromString("00001101-0000-1000-8000-00805F9B34FB"); // 为其链接创建一个名称 private final String NAME = "Bluetooth_Socket"; // 选中发送数据的蓝牙设备,全局变量,否则连接在方法执行完就结束了 private BluetoothDevice selectDevice; // 获取到选中设备的客户端串口,全局变量,否则连接在方法执行完就结束了 private BluetoothSocket clientSocket; // 获取到向设备写的输出流,全局变量,否则连接在方法执行完就结束了 private OutputStream os; // 服务端利用线程不断接受客户端信息 private AcceptThread thread; //定义按钮 //定义按钮 private Button close_all_led; private Button red1 = null; private Button green1 = null; private Button blue1 = null; private Button breath = null; private TextView receive1; private SeekBar seekBar; private String LED_STATE = "A 红灯亮"; private TextView re_msg; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout_buletooth_seacher); red1 = (Button)findViewById(R.id.red); green1 = (Button)findViewById(R.id.green); blue1 = (Button)findViewById(R.id.blue); receive1 = (TextView)findViewById(R.id.receive_text); close_all_led = (Button)findViewById(R.id.close_all_led); breath = (Button)findViewById(R.id.breath); seekBar = (SeekBar)findViewById(R.id.seekBar); re_msg = (TextView)findViewById(R.id.msg); red1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { LED_STATE = "R"; receive1.setText(LED_STATE); } }); green1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { LED_STATE = "G"; receive1.setText(LED_STATE); } }); blue1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { LED_STATE = "B"; receive1.setText(LED_STATE); } }); close_all_led.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { LED_STATE = "E"; receive1.setText(LED_STATE); } }); breath.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { LED_STATE = "H"; receive1.setText(LED_STATE); } }); seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int i, boolean b) { if (b){ LED_STATE ="{0:"+i+"}"; receive1.setText(LED_STATE); } } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }); // 获取到蓝牙默认的适配器 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); // 获取到ListView组件 lvDevices = (ListView) findViewById(R.id.lvDevices); // 为listview设置字符换数组适配器 arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, bluetoothDevices); // 为listView绑定适配器 lvDevices.setAdapter(arrayAdapter); // 为listView设置item点击事件侦听 lvDevices.setOnItemClickListener(this); // 用Set集合保持已绑定的设备 将绑定的设备添加到Set集合。 Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices(); if (devices.size() > 0) { for (BluetoothDevice bluetoothDevice : devices) { // 保存到arrayList集合中 bluetoothDevices.add(bluetoothDevice.getName() + ":" + bluetoothDevice.getAddress() + "\n"); } } // 因为蓝牙搜索到设备和完成搜索都是通过广播来告诉其他应用的 // 这里注册找到设备和完成搜索广播 IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); registerReceiver(receiver, filter); filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); registerReceiver(receiver, filter); // 实例接收客户端传过来的数据线程 thread = new AcceptThread(); // 线程开始 thread.start(); } //搜索蓝牙设备 public void onClick_Search(View view) { setTitle("正在扫描..."); // 点击搜索周边设备,如果正在搜索,则暂停搜索 if (mBluetoothAdapter.isDiscovering()) { mBluetoothAdapter.cancelDiscovery(); } mBluetoothAdapter.startDiscovery(); } // 注册广播接收者 private BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context arg0, Intent intent) { // 获取到广播的action String action = intent.getAction(); // 判断广播是搜索到设备还是搜索完成 if (action.equals(BluetoothDevice.ACTION_FOUND)) { // 找到设备后获取其设备 BluetoothDevice device = intent .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); // 判断这个设备是否是之前已经绑定过了,如果是则不需要添加,在程序初始化的时候已经添加了 if (device.getBondState() != BluetoothDevice.BOND_BONDED) { // 设备没有绑定过,则将其保持到arrayList集合中 bluetoothDevices.add(device.getName() + ":" + device.getAddress() + "\n"); // 更新字符串数组适配器,将内容显示在listView中 arrayAdapter.notifyDataSetChanged(); } } else if (action .equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) { setTitle("搜索完成"); } } }; // 点击listView中的设备,传送数据 @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // 获取到这个设备的信息 String s = arrayAdapter.getItem(position); // 对其进行分割,获取到这个设备的地址 String address = s.substring(s.indexOf(":") + 1).trim(); Log.d("TAG",address); // 判断当前是否还是正在搜索周边设备,如果是则暂停搜索 if (mBluetoothAdapter.isDiscovering()) { mBluetoothAdapter.cancelDiscovery(); } // 如果选择设备为空则代表还没有选择设备 if (selectDevice == null) { //通过地址获取到该设备 selectDevice = mBluetoothAdapter.getRemoteDevice(address); } // 这里需要try catch一下,以防异常抛出 try { // 判断客户端接口是否为空 if (clientSocket == null) { // 获取到客户端接口 clientSocket = selectDevice .createRfcommSocketToServiceRecord(MY_UUID); // 向服务端发送连接 clientSocket.connect(); // 获取到输出流,向外写数据 os = clientSocket.getOutputStream(); } // 判断是否拿到输出流 if (os != null) { // 需要发送的信息 //String text = "我传过去了"; // 以utf-8的格式发送出去 os.write(LED_STATE.getBytes("UTF-8")); } // 吐司一下,告诉用户发送成功 Toast.makeText(this, "发送信息成功,请查收", 0).show(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); // 如果发生异常则告诉用户发送失败 Toast.makeText(this, "发送信息失败", 0).show(); } } // 创建handler,因为我们接收是采用线程来接收的,在线程中无法操作UI,所以需要handler Handler handler = new Handler() { @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super.handleMessage(msg); // 通过msg传递过来的信息,吐司一下收到的信息 // Toast.makeText(BuletoothClientActivity.this, (String) msg.obj, Toast.LENGTH_SHORT).show(); re_msg.setText((String)msg.obj); } }; // 服务端接收信息线程 private class AcceptThread extends Thread { private BluetoothServerSocket serverSocket;// 服务端接口 private BluetoothSocket socket;// 获取到客户端的接口 private InputStream is;// 获取到输入流 private OutputStream os;// 获取到输出流 public AcceptThread() { try { // 通过UUID监听请求,然后获取到对应的服务端接口 serverSocket = mBluetoothAdapter .listenUsingRfcommWithServiceRecord(NAME, MY_UUID); } catch (Exception e) { e.printStackTrace(); } } public void run() { try { // 接收其客户端的接口 socket = serverSocket.accept(); // 获取到输入流 is = socket.getInputStream(); // 获取到输出流 os = socket.getOutputStream(); // 无线循环来接收数据 while (true) { // 创建一个128字节的缓冲 byte[] buffer = new byte[128]; // 每次读取128字节,并保存其读取的角标 int count = is.read(buffer); // 创建Message类,向handler发送数据 Message msg = new Message(); // 发送一个String的数据,让他向上转型为obj类型 msg.obj = new String(buffer, 0, count, "utf-8"); // 发送数据 handler.sendMessage(msg); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } } }
-
Android实现HC-05蓝牙舵机云台控制
2019-10-13 20:58:34蓝牙舵机云台控制花了两天时间实现简单的APP蓝牙舵机云台设置Android蓝牙协议分为两种,SPP协议和BLE(Bluetooth low energy)本项目采用的HC-05蓝牙4.0模块。BLE协议主要适用低功耗,具体其他的概念我暂时也不太明白...蓝牙舵机云台控制
花了两天时间实现简单的APP蓝牙舵机云台设置
首先说下遇到的问题,一开始调试,始终是通信不上,就是能检测到设备,但是始终提示
newState == BluetoothProfile.STATE_DISCONNECTED Disconnected from GATT server
根据大佬们介绍,这是报133错误。需要进行
close(); connect(mBluetoothDeviceAddress);
然而并没有彻底解决问题。
探究问题的根本,实际上是协议选择的不对。Android蓝牙协议分为两种,SPP协议和BLE(Bluetooth low energy)
不知道的同鞋请自行科普。协议的选取实际上和蓝牙硬件设备也是有关系的。
本项目采用的HC-05蓝牙4.0模块。
BLE协议主要适用低功耗,具体其他的概念我暂时也不太明白。而SPP协议时候数据传输,点对点的收发,与串口收发数据很相似。
采用SPP协议后,问题很快就得到解决。在前人基础上造车,使我的进步得到很大的提升。这里感谢这位博主qiqiwowo2
下面介绍下,我主要修改了下数据传输和保存的相关的操作。SPP蓝牙数据传输具体细节就不具体研读了,前辈说的也很仔细。
由于与硬件通信采用的是数据帧的格式,因此要实现字符串与16进制相关的转换。
获取十六进制
private String getHexString(String s) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')) { sb.append(c); } } if ((sb.length() % 2) != 0) { sb.deleteCharAt(sb.length()); } return sb.toString(); }
字符串转字节数据
private byte[] stringToBytes(String s) { byte[] buf = new byte[s.length() / 2]; for (int i = 0; i < buf.length; i++) { try { buf[i] = (byte) Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16); } catch (NumberFormatException e) { e.printStackTrace(); } } return buf; }
字节数组到16进制的转换
public static String bytes2Hex(byte[] b) { String ret = ""; for (int i = 0; i < b.length; i++) { String hex = Integer.toHexString(b[i] & 0xFF); if (hex.length() == 1) { hex = '0' + hex; } ret += hex.toUpperCase(); } return ret; }
通过SharedPreferences 进行读写操作
读操作
SharedPreferences sp = getApplicationContext().getSharedPreferences("setting", Context.MODE_PRIVATE); valueDegree=sp.getInt("setvalue",0);
写操作
SharedPreferences sp = getApplicationContext().getSharedPreferences("setting", Context.MODE_PRIVATE); SharedPreferences.Editor editor = sp.edit(); editor.putInt("setvalue",valueDegree); editor.commit();
页面布局
前人栽树后人乘凉!!
感谢的就不说了放个工程文件
-
Android蓝牙2.0,HC05,HC06
2016-04-19 10:29:36Android蓝牙2.0app,若需要蓝牙2.0和蓝牙4.0的源码,可以去百度云盘下载。链接:http://pan.baidu.com/s/1eSygHLg 密码:knm6。这里面有介绍和相应蓝牙2.0和蓝牙4.0的源码和app的下载链接 -
51单片机使用HC-05蓝牙模块向Android手机发送数据程序编写
2018-05-07 18:17:02HC-05蓝牙模块为主从一体的蓝牙模块,并可与手机实现实时的通信。将单片机的串口通信通过HC-05进行扩展从而实现无线通信,更可使用手机来控制单片机完成工作。 要完成单片机与Android手机的无...51单片机是市面上比较普及的单片机种类,同时也深受广大电子爱好者的青睐。在51单片机的众多功能中串口通信占据了重要的地位,通过串口通信,我们可以实现51单片机与其他设备的互联,增加了学习的趣味性。
HC-05蓝牙模块为主从一体的蓝牙模块,并可与手机实现实时的通信。将单片机的串口通信通过HC-05进行扩展从而实现无线通信,更可使用手机来控制单片机完成工作。
要完成单片机与Android手机的无线通信,首先我们要在写好单片机的控制程序,因为HC-05只是对串口通信功能进行延伸, 并不能独立完成通信。
编写串口通信的程序中首先我们要对串口的配置进行初始化
void UartConfigurationInit() { TMOD=0x20; //设置定时器1工作方式为方式2 TH1=0xfd; //波特率9600 TL1=0xfd; TR1=1; //启动定时器1 SM0=0;SM1=1; //串口方式1 REN=1; //允许接收 PCON=0x00; //关倍频 ES=1; //开串口中断 EA=1; //开总中断 }
配置好串口后,在编写发送函数前我们需要对串口发送数据的原理有个了解:
转码过程:
发送十进制数:查询ASCII码表后发送相应的字符 ,如SBUF=65;则会收到字符‘A’;
发送字符:原样输出
发送字符串:强行对SBUF传递字符串会造成输出乱码,得不到想要的结果。想要发送字符串则需要运用指针,每次发送时发送指针指向的那个字符,因为发送频率很快,最后输出时组合起来还是一条字符串。
实现整数转为字符串发送:
0x30对应的字符‘0’,当我们要发送一个整数时,需要将该整数按最高位到最低位得到顺序依次发送,发送时需要在原始数据上加上0x30或者48,则会输出相应的数字字符。
字符发送函数:
void PostChar(uchar character) { SBUF=character; //发送单个字符 while(!TI);TI=0; //发送完成标志 }
字符串的发送需要依靠字符发送函数来实现:
这里加了一个延时函数delay(),因为在实际与手机通信中我发现发送速度过快会产生严重的数据丢失,因此加上一个延时可以较好的保证数据的准确度,具体延时数据根据大家实际需要调整。
void PostString(uchar *p) { while(*p) //若指针指向的地址为空,则跳出循环 { PostChar(*p); //指针第一次默认指向首地址 delay(20); //延时,作用为提高发送准确度 p++; } }
十进制数据发送:
因为十进制数据不能直接发送,所以要先加上0x30或者48后再转为字符型。
void IntConversionChar(uint number) { uint model; //模 uint numberByte; //十进制数据不同位上的值 for(model=1000;model>=1;model=model/10) //model的取值根据实际需要选择,选择过大会浪费资源 { numberByte = number/model; //相除取整 //当取到整数数据的最高位时,将其加上0x30或者48并转为字符型后发送 if(numberByte >=1 ) PostChar((uchar)(numberByte%10+0x30)); //if(numberByte >=1 ) PostChar((unsigned char)(numberByte%10+48)); } }
以上就是51单片机使用HC-05蓝牙模块与Android手机通信的程序的要点和原理。
完整程序:
https://download.csdn.net/download/qq_41570228/10398277
-
android蓝牙通讯连接Hc-05模块.zip
2020-02-24 11:45:57android蓝牙通讯连接Hc-05模块 -
51单片机使用HC-05蓝牙模块与Android手机通信程序
2018-05-07 18:11:31程序完成了51单片机和手机的字符和数字通信,并有完整的注释,原理介绍可查看我的其他文章。 -
【Android开发 蓝牙通信】手机蓝牙与下位机HC-05蓝牙模块通信系统
2016-10-22 13:06:55【周记-Android移动端开发】手机蓝牙与下位机HC-05蓝牙模块通信系统 很久没有写博客了,计划一直都有,但总是被这样或者那样的事情给耽搁了,在此写下文字监督自己:不论长短,每周至少一篇!本文根据自己的实践... -
树莓+HC-05蓝牙模块+android数据通信
2017-03-17 08:14:14引脚2连接蓝牙模块vcc,引脚6连接蓝牙模块GND端,引脚8连接RXD端,引脚10连接TXD端。如下图所示 树莓端配置 步骤简介: 1. 配置树莓派的baud rate 默认情况下,树莓派读写串口的boud rate是115200,而HM-05... -
Android手机蓝牙与手机,HC05设备通信
2020-01-31 01:00:38APP作为信息的发送者与接受者,可以实现手机与手机的通信,手机向HC05发送数据(HC06就不知道了)。解压用AS打开生成APK就可以使用。 -
Android手机HC-05蓝牙连接Arduino nano获取DHT-11温湿度传感器数据
2021-02-24 13:50:49Android手机HC-05蓝牙连接Arduino nano获取DHT-11温湿度传感器数据 我以为的串口输出等于蓝牙输出,其实并不是 起初我所理解的,应该是这样连接 HC-05 nano TX----RX RX----TX 5V----5V GND----GND HT-05... -
完整版51单片机使用HC-05蓝牙模块与Android手机通信程序.c
2019-12-19 14:59:09d手机通信程序 程序完成了51单片机和手机的字符和数字通信,并有完整的注释,原理介绍可查看我的其他文章 前找了很久才找到了,传上来更大家共享下,希望对大家有帮助,欢迎下载或者永久保存。 -
单片机蓝牙通讯hc-05,兼容android6.0
2019-05-05 13:13:45官网代码不能兼容Android6.0以上版本,本人修改后可兼容使用,本代码是基于AndroidStudio开发 -
Android studio 2.2 安卓端与传统蓝牙HC05/06的通信APP
2017-03-01 11:25:36Android studio 2.2 安卓端与传统蓝牙HC05/06的通信APP,刚写,亲测可用。 -
蓝牙(基于android与hc-05连接)
2019-03-16 20:46:47可用于stm32的蓝牙数据传输,内部只有单工,没有手机端到android端口 -
QT on Android 编写蓝牙使用HC-05
2018-03-01 16:06:36前言: 由于17年机械创新设计大赛要使用蓝牙通讯,被迫缺少一个触摸显示器,所以只有在手机上开发界面来进行控制,其中最主要的就是蓝牙...这个蓝牙配置只可在Android上运行! 首先的就是配置一个蓝牙的类... -
请教关于HC05蓝牙速传模块中间无法传输数据的问题
2016-07-21 13:08:19/*这是一个Android里的进度条,模拟飞机的油门推杆,当进度条被改变时获取改变后的值,然后通过蓝牙发送给Arduino扩展的蓝牙模块*/ private OnSeekBarChangeListener verticalSeekBarChangeListener = new ...