本文主要介紹了針對android的藍牙序列槽上位機開發。
程式下載下傳位址:點選打開連結
一、幀定義
androidclient依照一定的資料幀格式通過藍牙序列槽發送資料到連接配接到MCU的藍牙從機。MCU接收到資料後。依照幀格式的定義,接收資料幀。并解析資料幀,得到須要的資料。
androidclient依照下面幀格式來發送和接收資料。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLi8CX2UjN3ITM1EzX19CXt92Yu8GdjFTNuc2bsJ2Lc9CX6MHc0RHaiojIsJye.jpg)
1.1client發送的資料幀内容
發送頻率:10Hz
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLi8CX2UjN3ITM1EzX19CXt92Yu8GdjFTNuc2bsJ2Lc9CX6MHc0RHaiojIsJye.jpg)
幀校驗的和是從幀長開始到幀校驗前全部資料的和對256取餘。
即sum%256。
pitch roll yaw資料各16位,由高低8位組成。MCU接收資料時須要将其再複合成一個16位資料。
0x5A:幀頭
14:針長度
0xA1:幀功能,标明這幀資料是pitch yaw roll内容。
pitch_set_H:pitch高8位
pitch_set_L:pitch低8位
...
幀校驗:(幀長+幀功能+資料)%256
0xA5:幀尾。
(注:幀是這麼定義的,但實際上編寫接收程式的時候。我将幀尾0xA5當作了一幀資料的幀頭。
這樣幀頭就變成了 0xA5 0x5A。此時就不存在幀尾了)
以下是androidclient發送位元組資訊的程式:
<span style="white-space:pre"> </span>b[0] = (byte)0XA5; //幀頭
b[1] = (byte)14; //幀長
b[2] = (byte)0xA1; //幀功能
b[3] = (byte)(pitchSet>>8); //資料
b[4] = (byte)(pitchSet);
b[5] = (byte)(rollSet>>8);
b[6] = (byte)(rollSet);
b[7] = (byte)(yawSet>>8);
b[8] = (byte)(yawSet);
b[9] = (byte)0;
b[10] = (byte)0;
b[11] = (byte)0;
b[12] = (byte)0;
int temp = 0;
for(int j=1;j<13;j++)
{
temp = temp+b[j];
}
b[13] = (byte)(temp%256); //校驗
b[14] = (byte)0x5A; //幀結束
1.2MCU接收幀資料
因為序列槽是依照一個一個位元組的格式發送資料,是以MCU接收資料時,要依照client發送的幀格式的定義。找到一幀資料的開始與結束,确認一幀資料接收無誤後,再将當中的資料解析出來。
使用一個為來标志(狀态機)接收程式對一陣資料的接收狀态。
編寫的DSP2808接收程式例如以下:
定義資料類型
typedef struct
{
int status; //data status
int Rx_Data; //the receivced data
int data[15]; //
int rx_buf[13];
int buf_index;
int sum;
int yawSet;
int pitchSet;
int rollSet;
}Sci_Data;
Sci_Data sci_data;
interrupt void SCIB_RX_ISR() //以中斷的方式接收資料
{
//接收程式
sci_data.Rx_Data = ScibRegs.SCIRXBUF.all;
ScibRegs.SCIFFRX.bit.RXFFOVRCLR = 1; //clear overflow flag
ScibRegs.SCIFFRX.bit.RXFFINTCLR = 1; //clear the interrupt flag
PieCtrlRegs.PIEACK.all |= PIEACK_GROUP9; //enable more interrupt from PIE group 9
Decode_Frame(sci_data.Rx_Data); //資料幀解碼
}
void Decode_Frame(int rx_data)
{
if(sci_data.status==0 && rx_data == 0x5A) //推斷幀尾 假設找到幀尾,status=1
{
sci_data.status = 1;
}
else if(sci_data.status == 1 &&rx_data == 0xA5) //幀尾下一個字元是幀頭。status=2
{
sci_data.status = 2;
}
else if(sci_data.status ==2) //幀頭後是13個位元組資料 從幀長到幀校驗
{
if(sci_data.buf_index<13)
{
sci_data.rx_buf[sci_data.buf_index] = rx_data; // 0-12 to save data length function data... sum
if(sci_data.buf_index<12) //求取校驗和
{
sci_data.sum += sci_data.rx_buf[sci_data.buf_index];
}
sci_data.buf_index++;
}
if(sci_data.buf_index >= 13)
{
if(sci_data.rx_buf[12] == sci_data.sum%256)
{
int j=0;
for(j=0;j<10;j++)
{
sci_data.data[j] = sci_data.rx_buf[j+2]; //save data to the data buf
}
sci_data.pitchSet = sci_data.data[0]<<8|sci_data.data[1];
}
sci_data.buf_index = 0;
sci_data.status = 0;
sci_data.sum = 0;
}
}
else
{
sci_data.buf_index = 0;
sci_data.status = 0;
sci_data.sum = 0;
}
}
這樣DSP2808就接收到了從client發送來的資料。儲存在sci_data.pitchSet、sci_data.rollSet、sci_data.yawSet三個變量中。
二、androidclient開發流程
問題:檢測藍牙的連接配接狀态
android藍牙序列槽程式狀态機
在程式中,通過broadcast來檢測藍牙的連接配接狀态,根絕藍牙的連接配接狀态來決定操作。
打開藍牙---掃描裝置---選擇裝置---連接配接裝置---連接配接正常---發送資料---