[C#] 編程控制筆記本藍牙與外部藍牙設備通信


 

一、藍牙模塊XLBT232‐D01介紹(外部設備藍牙)

1.1、藍牙模塊簡介

XLBT232-D0101藍牙模塊采用CSR BlueCore 芯片,配置6-8Mbit 的軟件存儲空間,
支持AT 指令,用戶可根據需要更改SPP 角色(主、從模式)以及串口波特率、
設備名稱、配對密碼等參數,使用靈活。

 

1.2、模塊功能介紹

1.2.1、特性

  •  藍牙協議:Bluetooth Specification V2.1+EDR、V2.0+EDR、V2.1、V2.0 V1.2
  • — 工作頻率:2.4GHz ISM band
  • — 調制方式:GFSK(Gaussian Frequency Shift Keying)
  • — 發射 率:≤4dBm, Class 2
  • — 靈 敏 度:≤-84dBm at 0.1% BER
  • — 傳輸速率:Asynchronous: 2.1Mbps(Max) / 160 kbpsSynchronous: 1Mbps/1Mbps
  • — 安全特性:Authentication and encryption
  • — 支持服務:Bluetooth SPP(主模式& 從模式)
  • — 供電電源:+3.3VDC 50mA
  • — 工作溫度:-5 ~ +65 Centigrade
  • — 外觀尺寸:26.9mm x 13mm x 2.2 mm

1.2.2、模塊接線原理圖

PS:當然也能用USB轉TTL模塊進行連接在電腦上調試,畢竟大多數筆記本已經沒有串口啦!

 

1.3、使用說明

[圖:藍牙模塊]

>_<" KEY為輸入管腳,短按控制,或者輸入約100ms 的高電平單次脈沖,可以
實現以下功能:

  • 模塊設置為SPP 主機模式時:

    未連接狀態時:清除配對信息(若存在配對設備信息)

    已連接狀態時:主動發起斷開連接,延時150ms 后重啟,重新搜索
  連接從設備; 在斷開連接時:重新搜索連接從設備。

  • 模塊設置為SPP 從機時:

    在已連接狀態時:主動發起斷開連接,延時150ms 后重啟,重新進入被搜
     索狀態,等待主機配對和連接

    在斷開連接時:延時150ms 后重啟,重新進入被搜索狀態,等待主機配對
     和連接。

>_<" 顯示模塊當前工作狀態:

  • 待機狀態慢閃——重復2s 脈沖;
  • 連接狀態長亮——高電平。

 

1.4、AT指令集

藍牙模塊出廠默認的串口配置為:波特率9600,無校驗,數據位8,停止位1。
PS:接下來說明以上位機為電腦,模塊參數為出廠設置時進行配置說明。
>_<" 將模塊通過USB電平轉換板連接到電腦USB口(USB轉TTL),使用串口調試助手,按
照 9600,N,8,1 進行配置,打開串口后,發送 AT(無\r\n),若返回 OK,說明配置
成功。
PS:設置 AT 指令必須在藍牙模塊未連接或斷開 SPP 鏈接時才可以(上電或配對
后都可以,如果連接 SPP,串口輸入的數據將會直接發送到遠端藍牙設備串口)

1.4.1、測試指令:

1.4.2、查詢\設置波特率指令:

1.4.3、查詢\設置設備名稱指令:

1.4.4、恢復默認設置指令:

1.4.5、模塊復位\重啟指令:

1.4.6、查詢\設置主從模式:

1.4.7、查詢\設置配對密碼:

1.4.8、查詢\設置是否需要密碼鑒權:

PS:為方便使用,默認為不用密碼鑒權連接,搜索到藍牙串口之后,直接連接
可。有安全考慮的客戶請選擇需要密碼鑒權。
PS:此指令只有在從設備時才有效;主設備時不接受此指令,發送此指令沒
有回復,也不執行

1.4.9、清除主設備配對信息指令:

PS:此指令只有在主設備時才有效;從設備時不接受此指令,發送此指令
沒有回復,也不執行。

1.4.10、搜索並連接新的藍牙串口從設備(*)指令:

PS:此指令只有在主設備時才有效;從設備時不接受此指令,發送此指令沒
有回復,也不執行。

1.4.11、連接最后一次連接的藍牙串口從設備(*)指令:

PS:此指令只有在主設備時才有效;從設備時不接受此指令,發送此指令沒
有回復,也不執行。

1.4.12、連接指定藍牙地址的從設備(*)指令:

PS:此指令只有在主設備時才有效;從設備時不接受此指令,發送此指令沒
有回復,也不執行。

1.4.13、查詢、設置軟件版本指令:

1.4.14、系統幫助指令:

1.4.15、查詢本機MAC 地址指令:

>_<: 1:所有參數設置后存儲在模塊內,下次啟動時無需再次設置
         2:AT 指令后標注*號的,表示目前未應用的AT 指令

 

 

二、藍牙模塊配置與筆記本電腦相連

2.1.1、藍牙初始化配置:

將藍牙模塊通過TTL轉USB模塊連接到筆記本,打開串口助手,通過上述AT指令設置為從設備,波特率為9600,然后重啟

[圖:USB轉TTL模塊]

[圖:串口助手]

2.1.2、電腦為主設備搜索建立連接:

點擊筆記本藍牙標志的小圖標,添加藍牙設備:

然后要等一會,筆記本正在裝驅動:

然后右擊藍牙圖標,查看藍牙設備,可見我們的設備已經被電腦發現並添加:

查看該設備屬性,此時筆記本為該設備提供一個串口,就是筆記本藍牙和設備藍牙通信的通道,要記住這個一會編程的時候會用到:

PS:這個COM15也可以在設備管理器中修改為其他通道

 

 

三、C#編程使筆記本藍牙和外部設備藍牙通信:

其實配對以后,藍牙就被模擬成了一個端口,我們可以用最簡單的端口通訊來收發信息。首先,在每次啟動時,需要連接端口:

[FORM初始化時獲取所有的COM口,並加入下拉列表]

 1 public Form1()
 2 {
 3     InitializeComponent();
 4 
 5     //Get all port list for selection
 6     //獲得所有的端口列表,並顯示在列表內
 7     PortList.Items.Clear();
 8     string[] Ports = SerialPort.GetPortNames();
 9 
10     for (int i = 0; i < Ports.Length; i++)
11     {
12         string s = Ports[i].ToUpper();
13         Regex reg = new Regex("[^COM\\d]", RegexOptions.IgnoreCase | RegexOptions.Multiline);
14         s = reg.Replace(s, "");
15 
16         PortList.Items.Add(s);
17     }
18     if (Ports.Length > 1) PortList.SelectedIndex = 1;
19 }

[連接按鈕事件:選中list中的被選中的COM口進行連接,如果連接成功就在狀態欄顯示藍牙連接成功]

 1 private void ConnectButton_Click(object sender, EventArgs e)
 2 {
 3     if (!BluetoothConnection.IsOpen)
 4     {
 5         //Start
 6         Status = "正在連接藍牙設備";
 7         BluetoothConnection = new SerialPort();
 8         ConnectButton.Enabled = false;
 9         BluetoothConnection.PortName = PortList.SelectedItem.ToString();
10         BluetoothConnection.Open();
11         BluetoothConnection.ReadTimeout = 10000;
12         BluetoothConnection.DataReceived += new SerialDataReceivedEventHandler(BlueToothDataReceived);
13         Status = "藍牙連接成功";
14     }
15 }

[藍牙接收數據事件響應函數,在按鈕連接事件中聲明的該事件,用於響應藍牙數據接收]

 1 private void BlueToothDataReceived(object o, SerialDataReceivedEventArgs e)
 2 {
 3     //int length = BluetoothConnection.ReadByte();
 4     Thread.Sleep(1000);
 5     int length = 13;
 6     BlueToothReceivedData = DateTime.Now.ToLongTimeString() + "\r\n";
 7     BlueToothReceivedData += "收到字節數:" + length + "\r\n";
 8 
 9     byte[] data = new byte[length];
10     BluetoothConnection.Read(data,0,length);
11     for (int i = 0; i < length; i++)
12     {
13         BlueToothReceivedData += string.Format("data[{0}] = {1}\r\n", i, data[i]);
14     }
15     //receive close message
16     if (length == 3 && data[0] == 255 && data[1] == 255 && data[2] == 255)
17     {
18         //Stop
19         Status = "正在斷開藍牙設備";
20         BluetoothConnection.Close();
21         BluetoothConnection.Dispose();
22         BluetoothConnection = null;
23         ConnectButton.Enabled = true;
24         Status = "藍牙斷開成功";
25     }
26 }
  • 這里第4行讓程序休息1是因為延時等待從設備把數據發送完全。
  • 這里為了方便我嚴格控制讓發送數據為13Byte。
  • 從設備發送的13Byte數據送至緩沖區,PC端C#程序通過read()函數將緩沖區數據接收到data中,下面是格式輸出一下數據。

[發送數據函數]

 1 private void BlueToothDataSend(byte[] data)
 2 {
 3     //int length = data.Length;
 4     //byte[] readData = new byte[length + 2];
 5     //readData[0] = (byte)(length % 255);
 6     //readData[1] = (byte)(length / 255);
 7     //for (int i = 0; i < length; i++)
 8     //{
 9     //    readData[i + 2] = data[i];
10     //}
11     //BluetoothConnection.Write(readData, 0, length + 2);
12     BluetoothConnection.Write(data, 0, 1);
13     //Status = "發送數據字節數:" + length;
14 }
  • 本來是將data[]數據發送出去,因為我從設備設置為只要有數據發送過來就做出響應發送13Byte數據,所以就直接將data的第一byte發送出去了。

[定時器函數:用於刷新狀態欄,和接收數據顯示]

1 private void MonitorTimer_Tick(object sender, EventArgs e)
2 {
3     StatusMessage.Text = Status;
4     BlueToothMessage.Text = BlueToothReceivedData;
5 }

[發送數據按鈕:將SendMessage中的數據獲得發送出去]

1 private void SendButton_Click(object sender, EventArgs e)
2 {
3     byte n;
4     byte.TryParse(SendMessage.Text, out n);
5 
6     BlueToothDataSend(new byte[] { n });
7 }

 

 

四、PC和51單片機通過藍牙連接展示

4.1.1、51單片機部分程序

一定要用11.0952Mhz的晶振,我用12Mhz結果出現幀丟失!其實這里采用的是52單片機,在此處區別不是很大~

將藍牙模塊的RXD連接單片機的RXD(P3.0),TXD連接單片機的TXD(P3.1),然后就像以前操作串口一樣操作就行啦~

  1 #include <REG52.H>
  2 #include <INTRINS.H>
  3 typedef unsigned char  uchar;
  4 typedef unsigned short ushort;
  5 typedef unsigned int   uint;
  6     
  7 sbit    SCL=P1^0;            //IIC時鍾引腳定義
  8 sbit    SDA=P1^1;            //IIC數據引腳定義
  9 
 10 #define    SlaveAddress    0xD0    //IIC寫入時的地址字節數據,+1為讀取
 11 //**************************************
 12 //延時5微秒(STC90C52RC@12M)
 13 //不同的工作環境,需要調整此函數
 14 //當改用1T的MCU時,請調整此延時函數
 15 //**************************************
 16 void Delay5us()
 17 {
 18     _nop_();_nop_();_nop_();_nop_();
 19     _nop_();_nop_();_nop_();_nop_();
 20     _nop_();_nop_();_nop_();_nop_();
 21     _nop_();_nop_();_nop_();_nop_();
 22     _nop_();_nop_();_nop_();_nop_();
 23     _nop_();_nop_();_nop_();_nop_();
 24 }
 25 //**************************************
 26 //I2C起始信號
 27 //**************************************
 28 void I2C_Start()
 29 {
 30     SDA = 1;                    //拉高數據線
 31     SCL = 1;                    //拉高時鍾線
 32     Delay5us();                 //延時
 33     SDA = 0;                    //產生下降沿
 34     Delay5us();                 //延時
 35     SCL = 0;                    //拉低時鍾線
 36 }
 37 //**************************************
 38 //I2C停止信號
 39 //**************************************
 40 void I2C_Stop()
 41 {
 42     SDA = 0;                    //拉低數據線
 43     SCL = 1;                    //拉高時鍾線
 44     Delay5us();                 //延時
 45     SDA = 1;                    //產生上升沿
 46     Delay5us();                 //延時
 47 }
 48 //**************************************
 49 //I2C發送應答信號
 50 //入口參數:ack (0:ACK 1:NAK)
 51 //**************************************
 52 void I2C_SendACK(bit ack)
 53 {
 54     SDA = ack;                  //寫應答信號
 55     SCL = 1;                    //拉高時鍾線
 56     Delay5us();                 //延時
 57     SCL = 0;                    //拉低時鍾線
 58     Delay5us();                 //延時
 59 }
 60 //**************************************
 61 //I2C接收應答信號
 62 //**************************************
 63 bit I2C_RecvACK()
 64 {
 65     SCL = 1;                    //拉高時鍾線
 66     Delay5us();                 //延時
 67     CY = SDA;                   //讀應答信號
 68     SCL = 0;                    //拉低時鍾線
 69     Delay5us();                 //延時
 70     return CY;
 71 }
 72 //**************************************
 73 //向I2C總線發送一個字節數據
 74 //**************************************
 75 void I2C_SendByte(uchar dat)
 76 {
 77     uchar i;
 78     for (i=0; i<8; i++)         //8位計數器
 79     {
 80         dat <<= 1;              //移出數據的最高位
 81         SDA = CY;               //送數據口
 82         SCL = 1;                //拉高時鍾線
 83         Delay5us();             //延時
 84         SCL = 0;                //拉低時鍾線
 85         Delay5us();             //延時
 86     }
 87     I2C_RecvACK();
 88 }
 89 //**************************************
 90 //從I2C總線接收一個字節數據
 91 //**************************************
 92 uchar I2C_RecvByte()
 93 {
 94     uchar i;
 95     uchar dat = 0;
 96     SDA = 1;                    //使能內部上拉,准備讀取數據,
 97     for (i=0; i<8; i++)         //8位計數器
 98     {
 99         dat <<= 1;
100         SCL = 1;                //拉高時鍾線
101         Delay5us();             //延時
102         dat |= SDA;             //讀數據               
103         SCL = 0;                //拉低時鍾線
104         Delay5us();             //延時
105     }
106     return dat;
107 }
108 //**************************************
109 //向I2C設備寫入一個字節數據
110 //**************************************
111 void Single_WriteI2C(uchar REG_Address,uchar REG_data)
112 {
113     I2C_Start();                  //起始信號
114     I2C_SendByte(SlaveAddress);   //發送設備地址+寫信號
115     I2C_SendByte(REG_Address);    //內部寄存器地址,
116     I2C_SendByte(REG_data);       //內部寄存器數據,
117     I2C_Stop();                   //發送停止信號
118 }
119 //**************************************
120 //從I2C設備讀取一個字節數據
121 //**************************************
122 uchar Single_ReadI2C(uchar REG_Address)
123 {
124     uchar REG_data;
125     I2C_Start();                   //起始信號
126     I2C_SendByte(SlaveAddress);    //發送設備地址+寫信號
127     I2C_SendByte(REG_Address);     //發送存儲單元地址,從0開始    
128     I2C_Start();                   //起始信號
129     I2C_SendByte(SlaveAddress+1);  //發送設備地址+讀信號
130     REG_data=I2C_RecvByte();       //讀出寄存器數據
131     I2C_SendACK(1);                //接收應答信號
132     I2C_Stop();                    //停止信號
133     return REG_data;
134 }
I2C.c
  1 // GY-52 MPU6050 IIC測試程序
  2 // 使用單片機STC89C51 
  3 // 晶振:11.0592M
  4 // 編譯環境 Keil uVision2
  5 
  6 #include <REG52.H>    
  7 #include <math.h>    //Keil library  
  8 #include <stdio.h>   //Keil library    
  9 
 10 typedef unsigned char  uchar;
 11 typedef unsigned short ushort;
 12 typedef unsigned int   uint;
 13 
 14 uchar usart_flag,receive_data;//串口中斷接收標志和串口接收數據
 15 //****************************************
 16 // 定義MPU6050內部地址
 17 //****************************************
 18 #define    SMPLRT_DIV        0x19    //陀螺儀采樣率,典型值:0x07(125Hz)
 19 #define    CONFIG            0x1A    //低通濾波頻率,典型值:0x06(5Hz)
 20 #define    GYRO_CONFIG        0x1B    //陀螺儀自檢及測量范圍,典型值:0x18(不自檢,2000deg/s)
 21 #define    ACCEL_CONFIG    0x1C    //加速計自檢、測量范圍及高通濾波頻率,典型值:0x01(不自檢,2G,5Hz)
 22 #define    ACCEL_XOUT_H    0x3B
 23 #define    ACCEL_XOUT_L    0x3C
 24 #define    ACCEL_YOUT_H    0x3D
 25 #define    ACCEL_YOUT_L    0x3E
 26 #define    ACCEL_ZOUT_H    0x3F
 27 #define    ACCEL_ZOUT_L    0x40
 28 #define    TEMP_OUT_H        0x41
 29 #define    TEMP_OUT_L        0x42
 30 #define    GYRO_XOUT_H        0x43
 31 #define    GYRO_XOUT_L        0x44    
 32 #define    GYRO_YOUT_H        0x45
 33 #define    GYRO_YOUT_L        0x46
 34 #define    GYRO_ZOUT_H        0x47
 35 #define    GYRO_ZOUT_L        0x48
 36 #define    PWR_MGMT_1        0x6B    //電源管理,典型值:0x00(正常啟用)
 37 #define    WHO_AM_I        0x75    //IIC地址寄存器(默認數值0x68,只讀)
 38 
 39 
 40 //****************************************
 41 //函數聲明
 42 //****************************************
 43 void  delay(unsigned int k);                                        //延時                        
 44 void  SeriPushSend(uchar send_data);                                  //串口發送函數
 45 void  InitMPU6050();                                                //陀螺儀初始化
 46 int   GetData(uchar REG_Address);                                    //合成數據並發送原數據
 47 void  init_uart();                                                    //串口初始化
 48 void  SeriPushSend(uchar send_data);                                //串口發送函數
 49 
 50 extern uchar Single_ReadI2C(uchar REG_Address);                        //讀取I2C數據
 51 extern void  Single_WriteI2C(uchar REG_Address,uchar REG_data);        //向I2C寫入數據
 52 
 53 
 54 //****************************************
 55 //延時
 56 //****************************************
 57 void delay(unsigned int k)    
 58 {                        
 59     unsigned int i,j;                
 60     for(i=0;i<k;i++)
 61     {            
 62         for(j=0;j<121;j++);
 63     }                        
 64 }
 65 //**************************************
 66 //初始化MPU6050
 67 //**************************************
 68 void InitMPU6050()
 69 {
 70     Single_WriteI2C(PWR_MGMT_1, 0x00);    //解除休眠狀態
 71     Single_WriteI2C(SMPLRT_DIV, 0x07);
 72     Single_WriteI2C(CONFIG, 0x06);
 73     Single_WriteI2C(GYRO_CONFIG, 0x18);
 74     Single_WriteI2C(ACCEL_CONFIG, 0x01);
 75 }
 76 //**************************************
 77 //合成數據並發送原數據
 78 //**************************************
 79 int GetData(uchar REG_Address)
 80 {
 81     uchar H,L;
 82     H=Single_ReadI2C(REG_Address);
 83     L=Single_ReadI2C(REG_Address+1);
 84     SeriPushSend(H);//發送出去
 85     SeriPushSend(L);
 86     return (H<<8)+L;   //合成數據
 87 }
 88 //**************************************
 89 //串口初始化
 90 //**************************************
 91 void init_uart()
 92 {
 93     TMOD=0x20;    //設置T1定時器工作方式2                
 94     TH1=0xfd;     //T1裝初值                
 95     TL1=0xfd;        
 96     TR1=1;        //啟動T1定時器    
 97     REN=1;        //允許串口中斷接收
 98     SM0=0;        //設置串口工作方式
 99     SM1=1;
100     EA=1;        //開總中斷
101     ES=1;        //開串口中斷
102 }
103 //****************************************
104 //串口發送函數
105 //****************************************
106 void  SeriPushSend(uchar send_data)
107 {
108     SBUF=send_data;  
109     while(!TI);TI=0;      
110 }
111 //****************************************
112 //串口接收函數
113 //****************************************
114 void ser()interrupt 4
115 {
116     RI=0;
117     receive_data=SBUF;
118     usart_flag=1;
119 }
120 //*********************************************************
121 //主程序
122 //*********************************************************
123 void main()
124 { 
125     delay(500);                        //上電延時        
126     init_uart();
127     InitMPU6050();                    //初始化MPU6050
128     delay(150);
129     while(1)
130     {
131         if(usart_flag==1)            //有數據傳過來
132         {
133             ES=0;                    //關閉串口中斷
134             SeriPushSend(0xff);
135             GetData(ACCEL_XOUT_H);    //發送X軸加速度
136             GetData(ACCEL_YOUT_H);    //發送Y軸加速度
137             GetData(ACCEL_ZOUT_H);    //發送Z軸加速度
138             GetData(GYRO_XOUT_H);    //發送X軸角速度
139             GetData(GYRO_YOUT_H);    //發送Y軸角速度
140             GetData(GYRO_ZOUT_H);    //發送Z軸角速度
141      
142             ES=1;
143             usart_flag=0;
144         }
145     }
146 }
main.c

因為我還在P1.0和P1.1連接一個陀螺儀MPU6050所以上面的代碼有點煩,其實可以參考一下我以前發的51單片機串口通信~

http://www.cnblogs.com/zjutlitao/p/3788696.htm

l 

4.1.2、沒有51單片機的情況

可以將藍牙模塊連接在USB轉TTL上,用串口助手和你寫的C#程序相互通信。

4.1.3、運行C#程序進行連接通信

[選擇剛才的那個藍牙端口點擊連接]

[第一次藍牙圖標會給出一個驗證提示:在驗證框內輸入AT指令配置時的你設置的驗證碼]

[然后就可以通信啦,如下:]

 

PS:相關代碼及資料

C#藍牙工程代碼:http://pan.baidu.com/s/1hqHwG4W

51藍牙工程代碼:http://pan.baidu.com/s/1dDqywVZ

藍牙模塊說明書:http://pan.baidu.com/s/1kT61nx1

C#藍牙相關博客鏈接:http://www.diy-robots.com/?p=410%20%E8%93%9D%E7%89%99

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM