一、藍牙模塊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 }

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 }
因為我還在P1.0和P1.1連接一個陀螺儀MPU6050所以上面的代碼有點煩,其實可以參考一下我以前發的51單片機串口通信~
http://www.cnblogs.com/zjutlitao/p/3788696.htm
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