藍(lán)牙(bluetooth)技術(shù)是一種低功耗短距離的無線通信技術(shù),被廣泛應(yīng)用于10米以內(nèi)的嵌入式設(shè)備通信當(dāng)中。其最高傳輸速度根據(jù)藍(lán)牙協(xié)議的版本不同,有1Mbps(BR、LE)、2-3Mbps(EDR)、24Mbps(HS)之分。在工業(yè)現(xiàn)場(chǎng),藍(lán)牙技術(shù)可以代替串行線纜,實(shí)現(xiàn)無線通信。在智能手機(jī)普及的今天,通過藍(lán)牙與手機(jī)建立連接,手機(jī)作為上位機(jī)發(fā)送指令給下位機(jī),可以實(shí)現(xiàn)低成本的UI控制方案。
BlueZ是當(dāng)前比較成熟的藍(lán)牙協(xié)議棧,作為Linux系統(tǒng)的官方協(xié)議棧,集成在Linux內(nèi)核之中。英創(chuàng)公司在ESM928x的Linux系統(tǒng)中,又移植了BlueZ用戶空間協(xié)議棧和相關(guān)工具,使得ESM928x Linux平臺(tái)能夠支持藍(lán)牙技術(shù),通過socket編程實(shí)現(xiàn)藍(lán)牙無線連接,代替串行線纜進(jìn)行通信。
圖1ESM928xW系列主板+底板
用戶使用藍(lán)牙串口功能主要分為兩個(gè)步驟:藍(lán)牙功能配置和socket應(yīng)用程序編寫。
1、藍(lán)牙功能配置
1、加載ap2610藍(lán)牙模塊上電驅(qū)動(dòng)
insmod /lib/modules/4.1.14/ap6210_bt_bcm20710.ko
2、加載藍(lán)牙固件,設(shè)定波特率、藍(lán)牙地址、使能hci等
brcm_patchram_plus --patchram /lib/firmware/ap6210/bcm20702a.hcd --baudrate 3000000 --enable_hci --bd_addr aa:00:55:44:33:22 --no2bytes --tosleep 5000 /dev/ttyS5 1> /dev/null&
3、啟動(dòng)dbus后臺(tái)服務(wù)
dbus-daemon --system --nofork --nopidfile &
4、以兼容模式啟動(dòng)bluetooth后臺(tái)服務(wù)
/libexec/bluetooth/bluetoothd -C &
5、啟動(dòng)hci0,并設(shè)置name和可見屬性
hciconfig hci0 up
hciconfig hci0 name esm9287
hciconfig hci0 piscan
hciconfig hci0 reset
以上5個(gè)步驟已經(jīng)寫成一個(gè)shell腳本set_bluetooth.sh,用戶也可以直接運(yùn)行該腳本完成以上設(shè)置。至此,完成了對(duì)藍(lán)牙的設(shè)置,可以通過hciconfig hci0 -a來查看藍(lán)牙信息,如圖2。這時(shí),其他藍(lán)牙設(shè)備就可以搜索到esm9287,圖3所示是android手機(jī)搜索到esm9287藍(lán)牙設(shè)備,點(diǎn)擊即可完成配對(duì)。
圖2使用hciconfig查看藍(lán)牙信息
圖3搜索esm9287并配對(duì)
2、Socket應(yīng)用編程
藍(lán)牙協(xié)議棧中的RFCOMM協(xié)議實(shí)現(xiàn)了對(duì)串口RS232的仿真,最多能提供兩個(gè)藍(lán)牙設(shè)備之間60路的連接。應(yīng)用程序中,可以使用socket進(jìn)行服務(wù)端和客戶端的編程,其過程與TCP/IP的socket通信沒有太大區(qū)別。
a)環(huán)境配置
開發(fā)bluez協(xié)議棧的藍(lán)牙應(yīng)用需要用到libbluetooth.so和相關(guān)頭文件,需要添加到eclipse對(duì)應(yīng)的藍(lán)牙項(xiàng)目中。libbluetooth.so是編譯bluez協(xié)議棧生產(chǎn)的動(dòng)態(tài)鏈接庫(kù),提供了頭文件bluetooth.h、hci_lib.h、sdp_lib.h中的函數(shù)實(shí)體,實(shí)現(xiàn)藍(lán)牙地址與常用數(shù)據(jù)類型的轉(zhuǎn)換、hci設(shè)備和sdp服務(wù)的一系列操作函數(shù)。
1、在項(xiàng)目中新建文件夾include/bluetooth,其中放入藍(lán)牙協(xié)議相關(guān)頭文件;新建文件夾lib,其中放動(dòng)態(tài)鏈接庫(kù)libbluetooth.so。
圖4新建include和lib文件夾
2、進(jìn)入項(xiàng)目Properties設(shè)置,添加項(xiàng)目下的include文件夾為GCC C++ Compiler和GCC C Complier編譯器的頭文件路徑(下圖是GCC C++ Compiler的設(shè)置,GCC C Compiler設(shè)置步驟相同)。
圖5添加頭文件搜索路徑
3、為Sourcery G++ Lite C++ Linker鏈接器添加libbluetooth.so庫(kù)文件及搜索路徑,如下圖。
圖6添加編譯庫(kù)及搜索路徑
b)服務(wù)端程序
1、申請(qǐng)藍(lán)牙RFCOMM socket
s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
2、綁定本地適配器,BDADDR_ANY默認(rèn)為第一個(gè)可用藍(lán)牙適配器
loc_addr.rc_family = AF_BLUETOOTH;
loc_addr.rc_bdaddr = *BDADDR_ANY;
loc_addr.rc_channel = (uint8_t) 1;
bind(s, (structsockaddr *)&loc_addr,sizeof(loc_addr));
3、設(shè)置socket監(jiān)聽模式,這里只允許建立一個(gè)連接
listen(s, 1);
4、等待連接
client = accept(s, (structsockaddr *)&rem_addr, &opt);
5、select模式讀取socket數(shù)據(jù)流
while(1)
{
FD_ZERO(&working_set);
max_sd = client;
FD_SET(client, &working_set);
timeout.tv_sec = 3 * 60;
timeout.tv_usec = 0;
// Call select() and wait 5 minutes for it to complete.
printf("Waiting on select() %ld sec...\n", timeout.tv_sec);
intrc_select = select(max_sd + 1, &working_set, NULL, NULL, &timeout);
// Check to see if the select call failed.
if(rc_select < 0)
{
perror(" select() failed");
break;
}
elseif(rc_select > 0)
{
if(FD_ISSET(max_sd,&working_set))
{
// read data from the client
bytes_read = read(client, buf,sizeof(buf));
if( bytes_read > 0 ) {
printf("received: [%s]\n", buf);
}
else
{
break;
}
write(client,ack,sizeof(ack));
}
}
// Else if rc_select == 0 then the 5 minute time out expired.
else
{
printf(" select() timed out.\n");
break;
}
}
6、關(guān)閉套接字
close(client);
close(s);
c)客戶端
1、申請(qǐng)藍(lán)牙RFCOMM socket
s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
2、設(shè)置藍(lán)牙連接服務(wù)器的地址
structsockaddr_rc addr = { 0 };
// set the connection parameters (who to connect to)
addr.rc_family = AF_BLUETOOTH;
addr.rc_channel = (uint8_t) 1;
str2ba( dest, &addr.rc_bdaddr );
3、連接藍(lán)牙服務(wù)器
// connect to server
status = connect(s, (structsockaddr *)&addr,sizeof(addr));
4、讀寫socket數(shù)據(jù)流
for(i = 0; i < 3; i++)
{
// send a message
write(s, message[i], strlen(message[i])+1);
printf("write "%s" to %s\n", message[i],dest);
bytes_read = read(s, buf,sizeof(buf));
if( bytes_read > 0 ) {
printf("received: [%s]\n", buf);
}
}
其中,message[i]為發(fā)送內(nèi)容的地址。
5、關(guān)閉socket
close(s);
在一張板子上運(yùn)行藍(lán)牙rfcomm服務(wù)程序,在另一張板子上運(yùn)行藍(lán)牙rfcomm客戶端程序,如圖6、圖7所示:
圖7服務(wù)端程序
圖8客戶端程序
通過socket編程,藍(lán)牙應(yīng)用程序可以像tcp/ip的網(wǎng)絡(luò)編程一樣,建立連接,實(shí)現(xiàn)無線通信。如果有用戶對(duì)藍(lán)牙的串口socket編程感興趣,可以聯(lián)系我們。我們將提供驅(qū)動(dòng)文件、藍(lán)牙庫(kù)文件及相應(yīng)的示例程序。
-
嵌入式主板
+關(guān)注
關(guān)注
7文章
6087瀏覽量
35661 -
安卓
+關(guān)注
關(guān)注
5文章
2139瀏覽量
57690
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論