sk-car-bt蓝牙怎么连苹果手机蓝牙不能配对

android蓝牙的调试(博通蓝牙工作 and 低功耗模式)
时间: 17:06:02
首先结合项目从整体上去把握这部分:
蓝牙模块中一个比较核心的文件是bluetooth.c, 在我们上电的时候, 会调用这个文件中bt_enable()这个函数, 在这个函数里面先调用set_bluetooth_power()上电,然后调用property_set(&ctl.start&, &hciattach&), 去启动hciattach这个服务,从而运行brcm_patchram_plus这个进程。这个服务会加载我们firmware等一些工作。这部分工作做完后, 我们会调用property_set(&ctl.start&,&bluetoothd&),这个服务是启动我们的bluz进程。如果以上成功的话,蓝牙芯片将会开始工作。
&蓝牙需要正常工作,简而言之,需要做三部分工作:
i)&&&&&给芯片上电。
ii)& hciattach服务启动,从而加载固件,设置波特率等一系列的操作。(硬)
iii& 启动bluetooth的协议,从而让蓝牙去正常工作。& & & & & & & & &(软)&&
其次来分析下具体的工作流程:
a)&BT管脚介绍
BT_REG_ON 和BT_RESET打开蓝牙时拉高, 关闭蓝牙时候拉低。 平时不需要控制。一般放在RF-KILL里面,可以在命令行里面操作。
UART可以一直配置为UART(TX/RX/RTS/CTS), 也可以只在使用蓝牙的时候配置为UART.
I)相互对应:& TX和RX,RTS和CTS, RTS和CTS用来做硬件流控
II)把自己的RTS(对方的CTS)拉高,对方就不能发数据
III)检测到自己的CTS为高(对方的RTS),就不能给对方发数据
IV)BT上电后(未做初始化),BT_RTS应为低
V)主机串口未打开后应该为低
睡眠控制脚: HOST_WAKE 和BT_WAKE
i) 对于AP来说, 一个是GPO, 一个是中断。
ii) 在BT使用前配置好, 在bluesleep.c中控制。
iii) 如果不使用lpm(低功耗模式), 可以不管这些, 在新板回来验证bt功能时候, 往往不需要低功耗模式。
a)&硬件验证
首先应该做下面的事情:
i)配置好UART的管脚
ii)配置好BT_REG_ON/BT_RESET的管脚, 并改好RFKILL代码
iii)BT_WAKE和HOAT_WAKE可以先不配
其次验证流程
下电:通过RFKILL拉低BT_REG_ON和BT_RESET让BT进入缺省状态
上电:同样通过RFKILL拉高BT_REG_ON和BT_REST让芯片处于上电状态
通过brcm_patchram_plus初始化BT芯片
Hciconfig uart0 up
Hcitool scan搜索设备,如果能够搜索到设备,则说明蓝牙芯片ok.
b)&Brcm_patchram_plus的作用
像我们上面提到的那样, 在启动hciattach服务的时候, 会启动这个brcm_patchram_plus这个进程。这个进程是有brcm_patchram_plus.c这个文件编译而成。
它的作用是初始化蓝牙芯片, 进行基本参数的配置: lpm、PCM等参数
参数解释(brcm_patchram_plus)列出
-d: 显示调试信息
-enable_hci: 启动hci协议
-enable_lpm: 启动lpm模式
-baudrate: 指定工作时的波特率
-patchram: 指定hcd文件
- bd_addr: 加载蓝牙地址
- /dev/ttyxxx: 指定串口
brcm_patchram_plus& -d –bd_addrxx:xx:xx:xx:xx:xx --enable_hci&--enable_lpm& --baudrate3000000& --patchram /etc/bcm4330.hcd& /dev/ttyHS0
进行硬件验证时可以简化:
brcm_patchram_plus-d --enable_hci& /dev/ttyHS0
c)& LowPower Mode
lpm的具体参数设定在brcm_patchram_plu.c代码中
unsignedchar hci_write_sleep_mode[] = { 0x01, 0x27, 0xfc,
0x0c,//command length
0x01,// Sleep_Mode UART
0x01,// Host Idle Threshold, roughly 1*300ms
0x01,// Host Controller Idle Threshold
0x01,// BT_WAKE_Active_Mode, 0-active low, 1-active hgih
0x01,// HOST_WAKE_Active_Mode, 0- active low, 1-active hgih
0x01,// Allow_Host_Sleep_During_SCO
0x01,// Combine_Sleep_Mode_And_LPM
0x00,// Enable_Tristate_Control_Of_UART_Tx_Line
0x00,// Active_Connection_Handling_On_Suspend
0x00,// Resume_Timeout
0x00,// Enable_BREAK_To_Host
0x00//Pulsed_HOST_WAKE
BT芯片的lpm需要与HOST的bluesleep同时工作
在我们测试蓝牙睡眠的时候, 手动往/proc/bcm/asleep/proto写1, 就可以启动睡眠模式。
i)正常代码:
BlueZ:启动BT时,(BlueZ在bluetooth.c的bt_enable里面)
改动init.qcom.rc文件来打开/关闭BT芯片的lpm
servicehciattach /system/bin/brcm_patchram_plus --enable_hci --enable_lpm&&&& --baudrate 3000000 --patchram/etc/firmware/bcm4329.hcd /dev/ttyHS0
ii)AP通过BT_WAKE来控制BT
拉高BT_WAKE: BT不能睡眠,或者必须醒来
拉低BT_WAKE:BT可以睡眠,睡不睡BT自己决定
HOST每次发数据前都要拉高BT_WAKE
BT如果睡眠,会拉高BT_RTS来阻止HOST发数据
iii)Bluesleep.c概述
bluesleep_init: 创建结点,bluesleep_probe: 申请GPIO/INT/WAKE_LOCK资源 ,启动定时器监控主机发送数据(超时即可拉低BT_WAKE),打开中断来监控HOST_WAKE的状态 ,bluesleep_outgoing_data: 拉高BT_WAKE唤醒BT ,bluesleep_hostwake_isr: 中断处理函数,进行wake任务调度。
&&&&&&& 对于新的项目, 我们首先确保HOST_WAKE和BT_WAKE的INT和GPIO能正确的申请到 ,其次确保bluesleep被编译,如下三个结点被创建
/proc/bcm/asleep/proto、/proc/bcm/asleep/hostwake、/proc/bcm/asleep/btwake
三、项目中蓝牙一些bug分析。
i)在传送多个文件过程中, 传输几个文件后, 传输的进度条停止不动。并且内核一直在打印h4_recv: Unknown HCI packet type&
答:&我们申请Host_wake中断类型为高电平。当第一次打开蓝牙时,
Host_wake =1时,此时产生中断。然后就轮番改变中断类型。当我们传输文件过程中,会来好多次中断,从而会响应多次中断处理函数,这个函数会进行反复打开和关闭串口的工作。这就是问题之所在。当bt给
HOST传数据的时候,反复打开、关闭串口,从而会造成一段时间内串口是不工作的。因此会导致bt中的buf溢出。这就是数据的帧检测位出问题的原因:rfcomm_recv_frame:bad
checksum in packet。
我们的做法是:在传输文件过程中,不要让HOST去关闭串口。直到我们文件传输结束,再用内核定时器去关闭串口。
ii)在传输过程中, 在UI上面点击搜索蓝牙设备, 没有任何反应,或弹出蓝牙进程无响应。
答:这样的问题, 一般是处理睡眠代码的流程有问题。在点击搜索蓝牙设备将界面的时候,HOST没有唤醒蓝牙设备。
iii) 在待机的情况下, 其他手机给测试机传输文件, 测试机没有任何反应。
答:经过分析才发现是这样的情况:当其他手机给我们测试机传文件的时候,中断也来了响应,然而刚来了响应后,系统又重新进入suspend状态。
我们的做法:在刚接受文件的时候, &可以尝试着给HOST加wakelock,不要让HOST睡眠。这样可以很好地解决问题。不过不要忘记在最后也加上unwakelock下哦。
iv)蓝牙在某些特定的情况下打不开。概率非常非常低。重启完手机后,蓝牙可以正常打开。
答:一般都是由于蓝牙在patchram_plus加载firmware没有成功,从而造成的。有可能是进程阻塞引起的。在加载固件的时候,尝试着在再次加载固件。
v)某些型号(如kewei)车载蓝牙连上手机待机电流为11MA,分析下原因。
答:手机蓝牙连接上耳机或carkit后,即使在没有打电话及听音乐的状态下,物理链路还是会保持的,也就是蓝牙的射频仍然在工作(这是协议规定的,否则会发生来电时无法用耳机或carkit接听等问题),而不同的耳机或carkit查询链接存在的时间间隔有所不同(主要由双方在链路建立时协商决定),因此在待机电流上则表现为不同的产品不一样,如图1是手机与kewei连接上后的OTA(空中数据包分析仪),OTA表明系统的POLL和NULL交互非常频繁(kewei作为主,主动发起POLL),这是导致手机待机电流上升的主要因素。图2
是和skyworth建立链接后的OTA,其交互频率要比kewei低10倍,因此表现在待机电流上会小些。
$T.total > 0 && $T.page <= $T.pageNum}
{#foreach $T.data as r}
{$T.r.formt_tm}{#if $T.r.nickname}{#else}匿名{#/if}
{$T.r.content}
{#if $T.page > 1 && $T.pageNum > 1)
$T.s_num > 2}
{#for index = $T.s_num to $T.e_num}
$T.pageNum > $T.pageNavSize+ 2 && $T.s_num != $T.pageNum - $T.pageNavSize}
{#if $T.pageNum > 1}
{#if $T.pageNum != $T.page && $T.pageNum > 1}
<a href="javascript:void(0);" page="{$T.page 下一页
您的回应...
也许你感兴趣
(C)2012 本站提供的内容来源于广大网络用户,我们不保证内容的正确性。如果转载了您的内容,希望删除的请联系我们!当前访客身份:游客 [
共同成长,共同进步
:您好,查阅了很多资料发现您写的最详尽易懂,可以...
:楼主,可以发下源代码嘛~
:楼主,可以发下源代码嘛~
:我也想要一份源码,楼主发一份吧@qq.co...
:不好意思,刚才邮箱写错了,是...
:你好,能把源码分享给我吗,我正在学习安卓开发,...
:大神,可以发给我一份源码,我也在学习开发。462...
:求源码,谢谢楼主的分享,...
:楼主大大,求发一份源码学习。。...
:正在学socket,求源码...
今日访问:7
昨日访问:14
本周访问:61
本月访问:164
所有访问:7014
蓝牙小车手机遥控软件
发表于12个月前( 11:27)&&
阅读(327)&|&评论()
0人收藏此文章,
通过手机控制蓝牙小车移动、变速、循迹、避障等。之前写的,现在分享下,共同学习。亲测成功。
BlueTooth_SmartCarActivity.java文件
package&cn.BlueTooth_SmartC
import&java.io.IOE
import&java.io.OutputS
import&java.io.PrintW
import&java.lang.reflect.InvocationTargetE
import&java.lang.reflect.M
import&java.util.A
import&java.util.UUID;
import&android.app.A
import&android.bluetooth.BluetoothA
import&android.bluetooth.BluetoothD
import&android.bluetooth.BluetoothS
import&android.content.C
import&android.content.I
import&android.os.B
import&android.os.V
import&android.util.L
import&android.view.M
import&android.view.MenuI
import&android.view.MotionE
import&android.view.V
import&android.view.View.OnTouchL
import&android.widget.B
import&android.widget.SeekB
import&android.widget.TextV
import&android.widget.T
public&class&BlueTooth_SmartCarActivity&extends&Activity&{
public&byte[]&message&=&new&byte[1];
private&Vibrator&//震动设置
private&BluetoothAdapter&btAdapter&=&BluetoothAdapter.getDefaultAdapter();
BluetoothDevice&btD
BluetoothSocket&bluetoothSocket&=&
OutputStream&tmpOut&=&
private&static&final&UUID&MY_UUID&=&UUID.fromString("AAD-4E9F-88D5-8E417CBF02C3");
private&String&Address&=&"00:12:10:31:04:08";
Button&buttonUP;&&&&&//方向按键
Button&buttonDOWN;
Button&buttonLeftT
Button&buttonRightT
Button&buttonLeftD
Button&buttonRightD
TextView&textViewDeviceN&&
TextView&textViewS
TextView&textViewP
SeekBar&seekB
int&i&=&70;&&&&&//初始速度值
&&&&/**&Called&when&the&activity&is&first&created.&*/
&&&&@Override
&&&&public&void&onCreate(Bundle&savedInstanceState)&{
&&&&&&&&super.onCreate(savedInstanceState);
&&&&&&&&setContentView(R.layout.main);
&&&&&&&&buttonUP=(Button)findViewById(R.id.buttonUP);
&&&&&&&&buttonDOWN=(Button)findViewById(R.id.buttonDOWN);
&&&&&&&&buttonRightTop=(Button)findViewById(R.id.buttonRightTop);
&&&&&&&&buttonLeftTop=(Button)findViewById(R.id.buttonLeftTop);
&&&&&&&&buttonLeftDown=(Button)findViewById(R.id.buttonLeftDown);
&&&&&&&&buttonRightDown=(Button)findViewById(R.id.buttonRightDown);
&&&&&&&&textViewDeviceName=(TextView)findViewById(R.id.textViewDeviceName);
&&&&&&&&textViewSuccessed=(TextView)findViewById(R.id.textViewSuccessed);
&&&&&&&&textViewProgress=(TextView)findViewById(R.id.textViewProgress);
&&&&&&&&seekBar=(SeekBar)findViewById(R.id.seekBar);
&&&&&&&&buttonUP.setOnTouchListener(new&ButtonOnTouchListener());
&&&&&&&&buttonDOWN.setOnTouchListener(new&ButtonOnTouchListener());
&&&&&&&&buttonLeftTop.setOnTouchListener(new&ButtonOnTouchListener());
&&&&&&&&buttonRightTop.setOnTouchListener(new&ButtonOnTouchListener());
&&&&&&&&buttonLeftDown.setOnTouchListener(new&ButtonOnTouchListener());
&&&&&&&&buttonRightDown.setOnTouchListener(new&ButtonOnTouchListener());
&&&&&&&&seekBar.setOnSeekBarChangeListener(new&SeekBarListener());
&&&&&&&&//检测蓝牙适配器
&&&&&&&&if(btAdapter&!=&null){
&&&&&&&& System.out.println("蓝牙设备驱动正常");
&&&&&&&& if(!btAdapter.isEnabled()){
Intent&intent&=&new&Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivity(intent);
System.out.println("适配器不可用");
&&&&&&&& }
&&&&&&&& else&System.out.println("适配器可用");
&&&&&&&&}&else&System.out.println("蓝牙设备驱动异常");
&&&&&&&&textViewProgress.setText("当前速度:"+i);
&&&&&&&&seekBar.setProgress(70);
&&&&/******发送信息方法*********/
&&&&public&void&bluesend(byte[]&msg){
tmpOut&=&bluetoothSocket.getOutputStream();
System.out.println("生成输出流");
Log.d("send",Arrays.toString(msg));
System.out.println("正在把输出流送到缓存区");
tmpOut.write(msg);
System.out.println("成功输出流送到缓存区");
&&&& }catch(IOException&e){
&&&&&&&&&&&e.printStackTrace();
&&&&&&&&&&&System.out.println("无法生成输出流或把输出流送到缓存区");
&&&&/******震动10ms方法******/
&&&&public&void&vibrator(){&&
&&&& vibrator&=&(Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
&&&& vibrator.vibrate(20);
&&&& System.out.println("震动20ms");
&&&&/*****SeekBar********/
&&&&private&class&SeekBarListener&implements&SeekBar.OnSeekBarChangeListener{
&&&& @Override//进度条改变时
&&&& public&void&onProgressChanged(SeekBar&seekBar,&int&progress,
boolean&fromUser)&{
//&TODO&Auto-generated&method&stub
i&=&seekBar.getProgress();
&&&&&&&&&&&&textViewProgress.setText("当前速度:"+i);
&&&& @Override//开始拖动滑块时
&&&& public&void&onStartTrackingTouch(SeekBar&seekBar)&{
//&TODO&Auto-generated&method&stub
i=&seekBar.getProgress();
&&&&&&&&&&&&textViewProgress.setText("当前速度:"+i);
&&&& @Override//结束拖动滑块时
&&&& public&void&onStopTrackingTouch(SeekBar&seekBar)&{
//&TODO&Auto-generated&method&stub
i=&seekBar.getProgress();
textViewProgress.setText("当前速度:"+i);
if(k==10)&k=9;
//将整型转变为字符串型
String&j&=&String.valueOf(k);
&&&& &&&&byte[]&msgBuffer&=&j.getBytes();
&&&& &&&&bluesend(msgBuffer);
&&&&/********按键监听器**************/
&&&&class&ButtonOnTouchListener&implements&OnTouchListener{
public&boolean&onTouch(View&v,&MotionEvent&event)&{
//&TODO&Auto-generated&method&stub
int&action&=&event.getAction();
action&=&event.getAction();
switch(action){
case&MotionEvent.ACTION_DOWN:
switch(v.getId()){
case&R.id.buttonUP:&
message[0]&=&(byte)0x41;//A的ASCII码65;
vibrator();//震动10ms
bluesend(message);
System.out.println("前进");
case&R.id.buttonDOWN:
message[0]&=&(byte)0x42;//B的ASCII码66;
vibrator();//震动10ms
bluesend(message);
System.out.println("后退");
&&&&case&R.id.buttonLeftTop:
&&&& message[0]&=&(byte)0x43;//S的ASCII码69;
vibrator();//震动10ms
bluesend(message);
System.out.println("左上");
&&&&case&R.id.buttonRightTop:
&&&& message[0]&=&(byte)0x44;//F的ASCII码70;
vibrator();//震动10ms
bluesend(message);
System.out.println("右上");
&&&&case&R.id.buttonLeftDown:
&&&& message[0]&=&(byte)0x45;//G的ASCII码71;
vibrator();//震动10ms
bluesend(message);
System.out.println("左下");
&&&&case&R.id.buttonRightDown:
&&&& message[0]&=&(byte)0x46;//H的ASCII码72;
vibrator();//震动10ms
bluesend(message);
System.out.println("右下");
case&MotionEvent.ACTION_UP:
message[0]&=&(byte)0x61;//a的ASCII码;
vibrator();//震动10ms
bluesend(message);
System.out.println("松手停止");
&&&&/*********菜单************/
&&&&@Override
&&&&public&boolean&onCreateOptionsMenu(Menu&menu)&{
&&&& //&TODO&Auto-generated&method&stub
&&&& menu.add(0,&0,&0,&"退出");
&&&& menu.add(0,&1,&1,&"遥控");
&&&& menu.add(0,&2,&2,&"循迹");
&&&& menu.add(0,&3,&3,&"红外");
&&&& menu.add(0,&4,&4,&"金探");
&&&& menu.add(0,&5,&5,&"测温");
&&&& menu.add(0,&6,&6,&"测湿");
&&&& menu.add(0,&7,&7,&"测速");
&&&& menu.add(0,&8,&8,&"避障");
&&&& return&super.onCreateOptionsMenu(menu);
&&&&@Override
&&&&public&boolean&onOptionsItemSelected(MenuItem&item)&{
&&&& //&TODO&Auto-generated&method&stub
&&&& byte[]&msgBufferWay&=&new&byte[1]&;
&&&& if(item.getItemId()==0){
&&&& if(item.getItemId()==1){
msgBufferWay[0]&=&(byte)0x62;//b的ASCII码;
&&&& &&&&bluesend(msgBufferWay);
&&&& if(item.getItemId()==2){
msgBufferWay[0]&=&(byte)0x63;//c的ASCII码;
&&&& &&&&bluesend(msgBufferWay);
&&&& if(item.getItemId()==3){
msgBufferWay[0]&=&(byte)0x64;//d的ASCII码;;
&&&& &&&&bluesend(msgBufferWay);
&&&& if(item.getItemId()==4){
msgBufferWay[0]&=&(byte)0x65;//e的ASCII码;;
&&&& &&&&bluesend(msgBufferWay);
&&&& if(item.getItemId()==5){
msgBufferWay[0]&=&(byte)0x66;//f的ASCII码;;
&&&& &&&&bluesend(msgBufferWay);
&&&& if(item.getItemId()==6){
msgBufferWay[0]&=&(byte)0x67;//g的ASCII码;;
&&&& &&&&bluesend(msgBufferWay);
&&&& if(item.getItemId()==7){
msgBufferWay[0]&=&(byte)0x68;//h的ASCII码;;
&&&& &&&&bluesend(msgBufferWay);
&&&& if(item.getItemId()==8){
msgBufferWay[0]&=&(byte)0x69;//i的ASCII码;;
&&&& &&&&bluesend(msgBufferWay);
&&&& return&super.onOptionsItemSelected(item);
&&&&/******onResume阶段***********/
&&&&@Override
&&&&protected&void&onResume()&{
&&&& //&TODO&Auto-generated&method&stub
&&&& super.onResume();
&&&& btDevice&=&btAdapter.getRemoteDevice(Address);
&&&& System.out.println("根据地址获取到远程蓝牙设备");
&&&& if(btDevice!=null){
textViewDeviceName.setText("你所连接的设备是:"+btDevice.getName());
&&&& try&{
bluetoothSocket&=&btDevice.createRfcommSocketToServiceRecord(MY_UUID);
/*******蓝牙连接***********/
&&&&m&=&btDevice.getClass().getMethod("createRfcommSocket",&new&Class[]&{int.class});
&&&&bluetoothSocket&=&(BluetoothSocket)&m.invoke(btDevice,&Integer.valueOf(1));
&&&&&&&&&&&&&&}&catch&(SecurityException&e1)&{
&&&&&&&&&&&&&&&&&&//&TODO&Auto-generated&catch&block
&&&&&&&&&&&&&&&&&&e1.printStackTrace();
&&&&&&&&&&&&&&}&catch&(NoSuchMethodException&e1)&{
&&&&&&&&&&&&&&&&&&//&TODO&Auto-generated&catch&block
&&&&&&&&&&&&&&&&&&e1.printStackTrace();
&&&&&&&&&&&&&&}&catch&(IllegalArgumentException&e)&{
&&&&&&&&&&&&&&&&&&//&TODO&Auto-generated&catch&block
&&&&&&&&&&&&&&&&&&e.printStackTrace();
&&&&&&&&&&&&&&}&catch&(IllegalAccessException&e)&{
&&&&&&&&&&&&&&&&&&//&TODO&Auto-generated&catch&block
&&&&&&&&&&&&&&&&&&e.printStackTrace();
&&&&&&&&&&&&&&}&catch&(InvocationTargetException&e)&{
&&&&&&&&&&&&&&&&&&//&TODO&Auto-generated&catch&block
&&&&&&&&&&&&&&&&&&e.printStackTrace();
&&&&&&&&&&&}&
System.out.println("根据UUID获取到远程蓝牙设备客户端");
bluetoothSocket.connect();
System.out.println("已连接到远程设备");
textViewSuccessed.setText("设备连接:成功");
}&catch&(IOException&e)&{
//&TODO&Auto-generated&catch&block
textViewSuccessed.setText("设备连接:未成功");
e.printStackTrace();
&&&&/********销毁阶段********/
&&&&@Override
&&&&protected&void&onDestroy()&{
&&&& //&TODO&Auto-generated&method&stub
&&&& super.onDestroy();
&&&& try&{
bluetoothSocket.close();
System.out.println("正在关闭客户端");
}&catch&(IOException&e)&{
//&TODO&Auto-generated&catch&block
e.printStackTrace();
1)">1)">1" ng-class="{current:{{currentPage==page}}}" ng-repeat="page in pages"><li class='page' ng-if="(endIndex<li class='page next' ng-if="(currentPage
相关文章阅读

我要回帖

更多关于 手机蓝牙怎么用 的文章

 

随机推荐