现在的位置: 首页 > 综合 > 正文

蓝牙FAQ

2018年04月16日 ⁄ 综合 ⁄ 共 8268字 ⁄ 字号 评论关闭

[DESCRIPTION]
        BT 4.0主要的一个贡献就是BLE,号称一个纽扣电池可以用几年。那么BLE为什么这么省电呢?
[SOLUTION]
        以下解释中,BT代表传统的BR/EDR模式,BLE则代表BT4.0特有的低功耗模式。
    1). BLE只会在某个特定的时间点传输数据,而其他时间不会传输数据,有些类似BT的sniff mode(睡眠模式)。

    2). BLE改进了一些BT耗电场景,如BLE只有在用户需要建立连线的时候才会发起连线相关的动作并且连接建立时间会在ms级,而BT设备通常情况下会开scan window以便被被人找到或连线且连线建立时间会在s级。这样就将传感器设备设计成需要传输数据时再快速建立连线,如果不需要就直接进入设备省电模式。

    3). BLE只会有一个Piconet,拓扑结构比BT的简单,在应用规范设计的时候就比较注意,例如把需要特别省电的传感器设备设计为slave,与相对不需要这么省电的手机等设计另外一种模式为master,slave可以根据需要在某些场景下不去接收master的数据包。

[DESCRIPTION]

测试时发现MTK Android手机会概率性的连接不上HS3000蓝牙耳机,特别是在第一次配对后,可能会出现配对成功后无法自动连接的情况,手动再点连接也不成功。

[SOLUTION]

这应该是个操作问题。该耳机在打开并进入可发现模式后,会先主动和之前连过的手机进行配对。而在其配对的这段时间中,其他手机可搜索到它,也可以配对上,但是无法连接的

所以很有可能在开始测试时,打开蓝牙耳机并进入可见性,它却自行发起了和周围某只手机(测试人员工作环境周围通常很多设备,并且耳机总是被借来借去)的配对。但那只手机在弹出配对界面后,由于无人操作,所以界面会停留一段时间。

在这段时间内,测试人员如果使用测试机搜索配对蓝牙耳机,是可以配对上的,但无法连接。

这种情况下,只需要等被耳机配对的那只手机配对等待超时后(或者找到它,按取消),再使用测试机连接蓝牙耳机即可。

 [Description]
蓝牙在如下情况下待机电流异常(平均电流,无SIM测试结果).
1.连接上蓝牙耳机,不进行其它任何蓝牙操作(ex,听音乐,打电话,传送文件),一直出现20mA左右待机电流.
2.开启蓝牙待机电流增大2~6mA.
[Solution]
对于1.可能有两种情况:
BT chip不能进入Sleep:这可以用示波器测试BT chip 26M是否有波形输出来验证.有两种情况:
(1.)蓝牙连接(A2DP ,SCO link)没有断开,导致Bt chip不能进入休眠.(程序中为了省电,
A2DP,Sco link连接在一段时间内没有使用的话,手机会主动断开这些连接
)。
(2.)可能该款耳机同手机存在兼容性问题,导致bt chip不能进入省电模式,需要提供耳机
抓蓝牙底层数据包来分析原因。
BB不能进入Sleep: 可能是连接上耳机后把BB sleep disable了,需要提供catcher log分
析,filter 设置: (!)Field Trail sleepMode + MOD_BT(All Classes On) .

对于2.可能是蓝牙power on后,gpio被拉高导致的.可以在函数GPIO_WriteIO 中加
trace把各个管脚打印出来,看是否有拉高

 

[DESCRIPTION]

A2DP和AVRCP

[SOLUTION]

A2DP(Advanced Audio Distribute Profile), 俗称蓝牙立体声,采样频率为16/32/44.1/48 KHz, 相对只有8KHz的非立体声(通过Bluetooth Handfree profile + SCO Link 传送PCM数据,主要应用在通话),采样频率要高很多,音质效果也要好很多。

说到A2DP, 不得不提到AVRCP(Audio/Video Remote Control Profile). AVRCP主要用来控制Audio/Video的播放,常见的功能有:上一首/下一首,播放/暂停。目前业界的流行得做法是,AVRCP的存在与否依赖于A2DP,即耳机根据是否有A2DP连接是否存在,决定连接/断开AVRCP连接,且AVRCP的连接都是由耳机端发起,而不是手机端。

 

[Description]
       实现功能:关闭蓝牙耳机单声道(SCO Link)播放音乐功能,但来电铃声(in-band ring)可以传到蓝牙耳机
[Solution]
1、在Makefile中保持BT_AUDIO_VIA_SCO 为TRUE
2、在Option.mak中关闭__ BT_AUDIO_VIA_SCO__

 

[DESCRIPTION]

蓝牙协议中的主从设备间只支持一条ACL链路和三条SCO链路,是不是就是等价于说在某一时刻,主从服务间只有一个服务使用这个ACL链路???

   举个例子就是,某一时刻文件传输服务和蓝牙上网服务,只能有一个在使用??

[SOLUTION]

我了解到的是,同一个蓝牙配对只能同时使用一个蓝牙服务,
比如要使用FTP文件传输服务,就必须先断开DUN蓝牙拨号上网服务等其他服务。

无连接(ACL)方式:主要用于分组数据传输。
面向连接(SCO)方式:主要用于话音传输;

蓝牙基带技术支持两种连接类型:同步定向连接(SCO)类型和异步无连接(ACL)类型。前者主要用于同步话音传送,后者主要用于分组数据传送。

    蓝牙技术支持一个异步数据通道,或3个并发的同步话音通道,或一个同时传送异步数据和同步话音的通道。每一个话音通道支持64kbps的同步话音;异步通道支持最大速率721kbps、反向应答速率为57.6kbps的非对称连接,或者是432.6kbps的对称连接。

    蓝牙服务中FTP、OBEX、DUN都是采用的ACL链接方式,而非SCO链接,所以只能同时使用其中一种服务了。
    如果LZ有USB蓝牙设备,可以配合BlueSoleil这个软件与自己的蓝牙手机配对,就会发现每次连接另一个服务时,之前的服务就会自动断开。

对于主设备而言,根据EDR标准,可以同时连接最多7台从设备,同时提供7个ACL连接和3个SCO连接。而每一个主从设备连接支持1个ACL连接和3个SCO连接,因此主设备可以最多同时给7台从设备提供ACL连接服务,就不存在LZ所说的问题了。不过要注意,在ACL方式下使用的轮询机制:由主设备控制链路带宽,负责从设备带宽的分配,从设备依轮询发送数据。

 

[DESCRIPTION]

蓝牙setting界面,已配对的蓝牙耳机设备下面“已连接”,“已连接(无手机)”,“已连接(无媒体)”字样的含义

[SOLUTION]

“已连接”,表示该蓝牙耳机设备与手机之间,已有建立ACL link,并且有连接handsfree profile和AVRCP(A2DP) profile。
“已连接(无手机)”,表示该蓝牙耳机设备与手机之间,已有建立ACL link;但是,只连接上AVRCP(A2DP) profile,而没有连接handsfree profile.
“已连接(无媒体)”,表示该蓝牙耳机设备与手机之间,已有连接ACL link;但是,只连接上Handsfree profile,而没有连接AVRCP (A2DP) profile.

需要额外注意的是:
“已连接(无手机)”,是在进行配对连接或重新连接的过程中,出现Handsfree profile没有连接上时,才会出现;
“已连接(无媒体)”,是在进行配对连接或重新连接的过程中,出现AVRCP(A2DP) profile没有连接上时,才会出现;
对于蓝牙耳机设备来说,如果将Handsfree profile和AVRCP profile都断开的话,则BT protocol stack会认为该蓝牙耳机设备已断开连接,从而主动发起ACL link的短线。此时,设备下面的字样也会同时消失。

[DESCRIPTION]
蓝牙耳机通话声音传输过程
[SOLUTION]

手机在跟蓝牙耳机建立HFP连接后,如果此时需要进行通话,通话声音的传输需要经过以下流程:

1、手机跟蓝牙耳机建立SCO(eSCO)物理链路

2、Modem通过Audio模块下行的语音送到蓝牙芯片

3、蓝牙芯片对语音进行CVSD编码

4、蓝牙芯片把编码后的数据通过SCO(eSCO)物理链路发送给蓝牙耳机

5、蓝牙耳机进行解码,并把声音播放出来

 

[DESCRIPTION]
手机是怎样连接上蓝牙耳机AVRCP
[SOLUTION]

AVRCP(AUDIO/VIDEO REMOTE CONTROL PROFILE),实现了从蓝牙耳机端控制手机

播放、暂停音乐等一些操作,敝司手机实现了AVRCP的target (TG)角色蓝牙耳机实现了

controller(CT)角色,在手机连接上蓝牙耳机A2dp(媒体音频)时,蓝牙耳机会判断后续可能

会有音乐播放,这时蓝牙耳机都会主动发起avrcp 的连接过程,所以avrcp连接过程一般都是在

A2dp连接成功后进行。

 

[Description]
1、菜单—附加功能--蓝牙:与蓝牙耳机连接
         2、用蓝牙耳机听立体声音乐,在音乐播放器界面按蓝牙耳机暂停键,音乐暂停
         3、此时来电话,用蓝牙耳机接听然后挂断,然后在按蓝牙耳机的播放键播放音乐
        结果:音乐播放器不能播放音乐,蓝牙耳机播放按键也没有起作用
[Solution]
       这类问题主要是SCO Link有影响到耳机端对AVRCP的响应,具体怎样影响到,需
要了解耳机端的做法。比较可能的原因是耳机端认为SCO Link还存在,不应该有A2DP的操
作。
为了解决此问题,可以将BT_SCO_CONNECT_TIMEOUT_DURATION的值改短,建议
为3s。Nokia的做法是,如果SCO Link超过1s不用,则Disconnect.
      PS. BT_SCO_CONNECT_TIMEOUT_DURATION值表示允许SCO Link空闲的时间
K CONFIDENTIA

[DESCRIPTION]
在11A1112以及之前的版本上,有些蓝牙耳机无法通过耳机上面的快进/快退键控制手机上音乐的快进/快退,而有些蓝牙耳机可以。原因是:有些蓝牙耳机被按下快进之后,发过来的cmd是MMI_AVRCP_POP_FAST_FORWARD,而在11A1112之前不支持这个cmd。对于快进/快退功能,一般蓝牙耳机发送过来的cmd都是MMI_AVRCP_POP_FORWARD,LONGPRESS。
[SOLUTION]
如要兼容此蓝牙耳机,请修改mmi_medply_bt_avrcp_cmd_hdlr如下:
U8 mmi_medply_bt_avrcp_cmd_hdlr(U8 command, mmi_avrcp_key_events key_events) {
    ......
            else if(g_medply.fullscreen)
            {
                switch (command)
                {
                    case MMI_AVRCP_POP_PLAY:
                    case MMI_AVRCP_POP_STOP:
                    case MMI_AVRCP_POP_PAUSE:
                    case MMI_AVRCP_POP_FORWARD:
                    case MMI_AVRCP_POP_BACKWARD:
                    case MMI_AVRCP_POP_FAST_FORWARD:  //添加这行
                    case MMI_AVRCP_POP_REWIND:        //添加这行
                    {
                        result = MMI_AVRCP_CR_REJECT;
                        mmi_medply_toggle_full_screen();
                        goto avrcp_finish;
                        break;
                    }
                    default :
                        break;
                }
                break;
            }
    .......
            #ifdef __MMI_TVOUT__
            else if(g_medply.tvout_fullscreen)
            {
                switch (command)
                {
                    case MMI_AVRCP_POP_PLAY:
                    case MMI_AVRCP_POP_STOP:
                    case MMI_AVRCP_POP_PAUSE:
                    case MMI_AVRCP_POP_FORWARD:
                    case MMI_AVRCP_POP_BACKWARD:
                    case MMI_AVRCP_POP_FAST_FORWARD:  //添加这行
                    case MMI_AVRCP_POP_REWIND:        //添加这行
                    {
                        result = MMI_AVRCP_CR_REJECT;
                        mmi_medply_toggle_tvout_full_screen();
                        goto avrcp_finish;
                        break;
                    }
                    default :
                        break;
                }
                break;
            }
        #endif
    ......
        if (key_events == MMI_AVRCP_KEY_CANCELED)
    {
        switch (command)
        {
            case MMI_AVRCP_POP_PLAY:
            case MMI_AVRCP_POP_STOP:
            case MMI_AVRCP_POP_PAUSE:
            case MMI_AVRCP_POP_FORWARD:
            case MMI_AVRCP_POP_BACKWARD:
            case MMI_AVRCP_POP_FAST_FORWARD://添加这行
            case MMI_AVRCP_POP_REWIND://添加这行
                mmi_medply_press_button_canceled();
                break;
            default :
                break;
        }
        /*the return value do not mean anything in key canceled event*/
        result = MMI_AVRCP_CR_REJECT;
        goto avrcp_finish;
    }
    ......
      case MMI_AVRCP_POP_FORWARD:
        case MMI_AVRCP_POP_FAST_FORWARD://添加这行
            if (key_events == MMI_AVRCP_KEY_UP)
            {
                mmi_medply_press_next_button_up();
            }
            else if (key_events == MMI_AVRCP_KEY_DOWN)
            {
                mmi_medply_press_next_button_down();
            }            
            else if(key_events == MMI_AVRCP_KEY_LONGPRESS)
            {
                if(GetActiveScreenId() == SCR_ID_MEDPLY_MAIN_SCREEN )
                {
                    mmi_medply_fast_forward();
                }
                else
                {
                    result = MMI_AVRCP_CR_REJECT;
                }
            }
            else
            {
                result = MMI_AVRCP_CR_REJECT;
            }
            break;
        case MMI_AVRCP_POP_BACKWARD:
        case MMI_AVRCP_POP_REWIND://添加这行
            if (key_events == MMI_AVRCP_KEY_UP)
            {
                mmi_medply_press_prev_button_up();
            }
            else if(key_events == MMI_AVRCP_KEY_DOWN)
            {
                mmi_medply_press_prev_button_down();
            }
            else if(key_events == MMI_AVRCP_KEY_LONGPRESS)
            {
                if(GetActiveScreenId() == SCR_ID_MEDPLY_MAIN_SCREEN )
                {
                    mmi_medply_rewind();
                }
                else
                {
                    result = MMI_AVRCP_CR_REJECT;
                }
            }
            else
            {
                result = MMI_AVRCP_CR_REJECT;
            }
            break;
}

抱歉!评论已关闭.