嵌入式 linux 蓝牙 C开发

2019-07-12 16:21发布

最近公司准备搞蓝牙,从年前折腾环境到年后开发板上折腾应用,搞了好久,看了好多资料跟请教大神,终于搞定了。项目情况:有个远程蓝牙设备(服务端)会发送数据,现有一个外接蓝牙适配器,要在开发板开发应用程序,通过蓝牙适配器连接那个蓝牙设备,接收蓝牙设备发送的数据。前期开发板的环境搭建,参考这个博客,很详细了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; } } }