最近公司准备搞蓝牙,从年前折腾环境到年后开发板上折腾应用,搞了好久,看了好多资料跟请教大神,终于搞定了。项目情况:有个远程蓝牙设备(服务端)会发送数据,现有一个外接蓝牙适配器,要在开发板开发应用程序,通过蓝牙适配器连接那个蓝牙设备,接收蓝牙设备发送的数据。前期开发板的环境搭建,参考这个博客,很详细了
http://blog.csdn.net/gatieme/article/details/48751743现在重点讲下开发板上蓝牙应用的开发,之前碰壁了很多。后面直接参考bluz蓝牙源代码,下载最新的bluz 5.48版本,下载地址:
http://www.bluez.org/download/。之前蓝牙应用写完后运行,看蓝牙连接函数返回都是连接成功,但是看那个远程蓝牙设备实际上是并未连接上。后面关键问题就是连接服务端蓝牙时,
蓝牙的频道号没设置正确,导致一直不行,这个频道号一定要查看远程蓝牙设备所拥有的频道号是多少,进行对应设置。后面参考bluz源码tools文件夹下的rctest.c的demo,里面有函数可以获取目标蓝牙所支持的频道号。附上我开发板上蓝牙客户端的源码
#include "bluetooth.h"
#include "hci.h"
#include "hci_lib.h"
#include "l2cap.h"
#include "rfcomm.h"
#include "sdp.h"
#include "sdp_lib.h"
//蓝牙地址及名称结构体
typedef struct REMOTE_BLUE_INFO
{
char bdaddr[28];
char name[30];
}PACKED Sct_Remote_BlueInfo;
static int g_blue_sk=0; //连接标识符
static int g_channel=0; //全局目标蓝牙频道号
static uint16_t uuid = SERIAL_PORT_SVCLASS_ID;
//蓝牙搜索
int appBlue_scan(Sct_Remote_BlueInfo *allBlue)
{
inquiry_info *ii = NULL;
int max_rsp, num_rsp;
int dev_id, sock, len, flags;
int i;
printf("-------------蓝牙设备搜索------------
");
dev_id = hci_get_route(NULL); //指定Dongle Device ID。如果此值小于0,则会使用第一个可用的Dongle。
sock = hci_open_dev(dev_id);
if (dev_id < 0 || sock < 0) {
printf("打开本地蓝牙失败
");
return -1;
}
len = 6; //此次inquiry的时间长度(每增加1,则增加1.25秒时间)
max_rsp = 10; //此次搜索最大搜索数量,如果给0。则此值会取255。
flags = IREQ_CACHE_FLUSH; //使用IREQ_CACHE_FLUSH,则会真正重新inquiry。否则可能会传回上次的结果
ii = (inquiry_info*)malloc(max_rsp * sizeof(inquiry_info));
num_rsp = hci_inquiry(dev_id, len, max_rsp, NULL, &ii, flags);
printf("搜索到的蓝牙设备个数:%d
", num_rsp);
if( num_rsp < 0 )
{
printf("未搜索到蓝牙设备
");
return 0;
}
for (i = 0; i < num_rsp; i++)
{
ba2str(&(ii+i)->bdaddr, allBlue[i].bdaddr);
if (hci_read_remote_name(sock, &(ii+i)->bdaddr, sizeof(allBlue[i].name), allBlue[i].name, 0) < 0)
strcpy(allBlue[i].name, "[unknown]");
printf("%s %s
", allBlue[i].bdaddr, allBlue[i].name);
}
free(ii); //释放空间
close(sock);
//返回搜索到的蓝牙数目
return num_rsp;
}
//蓝牙客户端
int Blue_client_connect(char *dest)
{
struct sockaddr_rc addr;
int status=0;
g_channel = get_channel(dest, uuid);
printf("获取到的频道号:%d
", g_channel);
//如果之前有连接其他蓝牙,则断开重连
if (g_blue_sk > 0)
{
close(g_blue_sk);
}
// allocate a socket
g_blue_sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
printf("socket结果:%d
", g_blue_sk);
/* Bind to local address 绑定本地蓝牙地址*/
memset(&addr, 0, sizeof(addr));
addr.rc_family = AF_BLUETOOTH;
bacpy(&addr.rc_bdaddr, BDADDR_ANY);
if (bind(g_blue_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
printf("绑定本地蓝牙地址失败
");
return 0;
}
// connect to server
memset(&addr, 0, sizeof(addr));
addr.rc_family = AF_BLUETOOTH;
str2ba( dest, &addr.rc_bdaddr );
addr.rc_channel = (uint8_t) g_channel; //重点,一定要选对频道号,根据目标蓝牙设备所支持的频道进行设置
status = connect(g_blue_sk, (struct sockaddr *)&addr, sizeof(addr));
printf("连接结果:%d
", status);
if( status == 0 )
{
//连接成功
return 1;
}
else
return 0;
}
//蓝牙初始化
int appBlue_init()
{
char destAddr[20]="34:81:F4:12:41:97"; //目标蓝牙地址
int rst=0, blueNum=0, i=0;
Sct_Remote_BlueInfo allBlue[12];
//搜索蓝牙
blueNum = appBlue_scan(allBlue);
printf("蓝牙搜索到的个数:%d
", blueNum);
for (i=0; i//蓝牙连接读取数据
int appBlue_read_date()
{
int readLen=0;
char buf[256]={0};
int step=1;
while(1)
{
switch (step)
{
case 1:
memset(buf, 0, sizeof(buf));
readLen = read(g_blue_sk, buf, sizeof(buf));
printf("readLen=%d
", readLen);
if( readLen > 0 ) {
printf("
%s", buf);
//Trace_HEX(buf, readLen, "读到的数据");
appBlue_date_analy(buf, readLen);
}
else
{
step = 2;
}
break;
case 2:
//重连蓝牙
if (Blue_client_connect("34:81:F4:12:41:97"))
{
step = 1;
}
break;
default:
break;
}
}
}