蓝牙通讯程序设计.docx
《蓝牙通讯程序设计.docx》由会员分享,可在线阅读,更多相关《蓝牙通讯程序设计.docx(15页珍藏版)》请在冰豆网上搜索。
蓝牙通讯程序设计
通信原理
课
程
设
计
课题:
蓝牙通信程序设计
学号:
*********
姓名:
蓝牙通信程序设计
1.引言:
课题背景及意义
随着微电子技术、通信技术和计算机技术的发展,计算机发展已经进入移动时代。
以掌上电脑(PDA)为代表的移动式计算系统已日益普及。
特别是工业高度发展的今天,对工业现场的通信与数据实时处理要求越来越高。
在环境恶劣与布线不便的工业场所,设备间无线通讯与PDA辅助处理成了工业现场的最佳选择。
蓝牙是一种低成本、高可靠性的无线传输技术,蓝牙通信是实现PDA与工业接入点通信的首要环节。
蓝牙技术是用微波无线通信技术取代数据电缆来完成点对点或点对多点短距离通信的一种新型无线通信技术。
而蓝牙芯片则是蓝牙技术的基础和关键。
2.蓝牙技术与蓝牙系统结构简介:
2.1蓝牙技术简介
蓝牙是一种支持设备短距离通信(一般10m内)的无线电技术。
能在包括移动电话、PDA、无线耳机、笔记本电脑、相关外设等众多设备之间进行无线信息交换。
利用“蓝牙”技术,能够有效地简化移动通信终端设备之间的通信,也能够成功地简化设备与因特网Internet之间的通信,从而数据传输变得更加迅速高效,为无线通信拓宽道路。
蓝牙采用分散式网络结构以及快跳频和短包技术,支持点对点及点对多点通信,工作在全球通用的2.4GHzISM(即工业、科学、医学)频段。
其数据速率为1Mbps。
采用时分双工传输方案实现全双工传输。
截止2009年4月,蓝牙共有五个版本V1.1/1.2/2.0/2.1/3.0。
以通讯距离来在不同版本可再分为ClassA
(1)/ClassB
(2)。
蓝牙
2.2蓝牙协议(HCI)介绍
蓝牙SIG开发了蓝牙协议规范,已发布版本包括1.0,1.0b,1.1和2.0。
蓝牙协议规范允许开发人员开发基于可互操作的无线模块和数据通信协议的交互式服务和应用,目的是使符合该规范的各种应用之间能够实现互操作。
蓝牙协议栈体系结构如图1所示。
蓝牙1.0标准由两个文件组成。
一个是核心部分(FoundationCore),它规定的是设计标准。
另一个叫协议子集部分(FoundationProfile),它规定的是运作性准则。
蓝牙协议可以分为4层,即核心协议层、电缆替代协议层、电话控制协议层和采纳的其它协议层。
由于篇幅的限制,本文只介绍核心协议。
蓝牙的核心协议包括基带(baseband)、链路管理(LMP)、逻辑链路控制与适应协议(SDP)等四部分。
基带层:
蓝牙采用跳频扩频技术,每秒1600跳,从时间域看即每个时隙长度是625μs,即每个时隙从79个信道中选择一个。
蓝牙既支持电路型数据,也支持分组型数据;既支持点对点连接,也支持点对多点连接。
在一个微微网络(Pieconet)中,一个单元作为主节点,其他作为从节点,最多可以有7个从节点;但是允许有更多从节点与主节点保持在Park状态。
从节点对信道的接入由主节点控制。
微微网络在覆盖上可以有重叠:
每个网络有各自的跳频方案,一个网络的主节点可以同时作为另一个网络的从节点;一个从节点可以属于多个网络。
主节点向从节点发送数据只能占用偶时隙,反之从节点只能在奇时隙才能向主节点发送数据。
一个分组(Packet,实际上更习惯的说法是帧,因为在基带层其地位类似于OSI的第2层、部分涉及物理层,分组的确切用法在第3层,但是蓝牙基带层规范中采用Packet术语)的传送最多可以占用5个时隙,在一个分组的传送期内,维持初始时隙所占用的信道而不再跳频。
链路管理(LMP)负责蓝牙组件间连接的建立。
通过连接的发起、交换、核实,进行身份鉴权和加密等安全方面的任务;通过协商确定基带数据分组大小;它还控制无线单元的电源模式和工作周期,以及微微网内蓝牙组件的连接状态。
逻辑链路控制与适应协议(L2CAP)位于基带协议层之上,属于数据链路层,是一个为高层传输和应用层协议屏蔽基带协议的适配协议。
其完成数据的拆装、基带与高协议间的适配,并通过协议复用、分用及重组操作为高层提供数据业务和分类提取,它允许高层协议和应用接收或发送长过64K字节的L2CAP数据包。
业务搜寻协议(SDP)是极其重要的部分,它是所使用模式的基础。
通过SDH,可以查询设备信息、业务及业务特征,并在查询之后建立两个或多个蓝牙设备间的连接。
SDP支持3种查询方式:
按业务类别搜寻、按业务属性搜寻和业务浏览(browsing)。
2.3蓝牙系统结构简介
MT1020基带控制器和PH2401无线收发器分别由MITEL公司和PHILSAR公司提供,两者配合可构成完整的低功耗的蓝牙模块,提供高至HCI(主机控制接口)层的功能。
它们在蓝牙系统中的位置如图2所示。
MT1020基带控制器负责蓝牙基带部分的功能,完成基带以及链路的管理,包括对SCO(同步)和ACL(异步)连接方式的支持、差错控制、物理层的认证与加密、链路管理等;PH2401实现数据的无线接收和发送;虚线以上部分由用户根据不同的应用需求来实现,分为用户主机端和用户PDA端。
特别值得一提的是,在该蓝牙模块解决方案中,即将推出的改进型基带控制器MT1020B可提供20K的用户ROM,使用户可以利用其内嵌的低功耗、高性能的32位ARM7TDMI内核,从而简化用户设计,实现最低楞耗、最高集成度的蓝牙产品。
2.4MT1020A基带控制器和PH2401无线收发器介绍
工业现场接入点通过传感器将信号传入MT1020A中再经PH2401无线收发器将信号发射给上位机处理,本章主要介绍基带控制器与无线收发器的结构与原理。
2.4.1MT1020A基带控制器的结构与原理
MT1020A是MITEL公司推出的低成本、微功耗蓝牙基带控制器芯片。
它和其它的无线收发器一起可以构成一个完整的低功耗小于蓝牙技术系统。
MT1020A采用CMOS工艺制作,是低功耗无线通信应用系统中理想的蓝牙基带微处理器件。
它的引脚排列如图3所示:
MT1020A采用11×11球形焊珠阵列121脚SSBGA封装形式。
图3为其引脚排列图。
MT1020由嵌入式微处理器和蓝牙基带外设组成,如图4示。
在该芯片中,系统内部时钟可以低至5MHz、内核供电电压为2V、硬件解码、支持DMA传输,所有这些使得该芯片具有超低功耗。
MT1020A的基带外围电路主要由主机接口、总线接口、蓝牙链路控制器、12kB缓冲RAM、队列管理器、音频编解码器以及音频和其它通信接口电路功能块组成。
该部分可用最小的软硬件开销完成各种重要的蓝牙系统操作。
基带外围电路中的总线接口主要用于完成微处理器与基带外围电路之间的各种通信,而外围电路内部各部分之间的数据传输则使用外围电路中的BT总线来完成。
键路控制器用来完成与外部无线收发器之间的通信,以实现数据发送时的装配、加同步字、帧头和CRC校验以及数字接收时的解码和检错等。
缓冲RAM是专门存储蓝牙数据包和变量的存储器,容量为12kB。
队列管理器可实现缓冲RAM与链路控制器以及主机接口与音频或其它通信接口之间的DMA传输。
音频解码器是一个全双工的解码器,内含麦克风放大器和耳机驱动器,其中的数字转换器可进行线性PCM、A律PCM、μ律PCM和CVSD间的相互转换。
2.4.2PH2401无线收发器与嵌入式控制内核功能介绍
PH2401单片无线收发器用砷化镓工艺制造,具有高集成度、超低功耗、体积小等优点,专门优化用于2.4GHz无线个人系统,完全兼容蓝牙规范“BluetooothV1.0”。
它工作于2.4GHz的ISM频段,以每秒1600次的速度在79个频道(2.402GHz-2.408GHz)上快速跳频,最大位传输速率可达1Mbit/s。
PH2401采用调制指数为0.3的高斯频移键控制(GFSK)调制方式,信道带宽为1MHz,频偏在140kHz-175kHz之间,满足蓝牙2级和3级操作,送功率可在-10dBm-+2dBm之间编程设定,发射范围为10-100m。
接收器由RF-IF下变频器、自动增益控制(AGC)、滤波器、双通道模/数转换器及调制器组成。
基带控制器通过串行总线与PH2401接口。
通过对其内部寄存器的读写实现跳频、调谐等其它控制。
工业现场,MT1020A和PH2401所组成的蓝牙系统框图如图5所示:
蓝牙系统的具体接线:
本文用该芯片的串行异步收发器1,也就是E3(U1txd):
UART1——数据发送端,和F3(U1rxd):
UART1——数据接收端与工业现场接入点的传感器信号或控制仪表相连;用蓝牙外围电路的无线接口J6(Ri_spi_misod):
(无线电串行接口数据输入)L6(Ri_spi_misod):
(无线电串行接口数据输出)与PH1024无线收发器相连;用C11(Gpio<0>):
通用I/O口,D9(Gpio<1>):
通用I/O口,D10(Gpio<2>):
通用I/O口,E8(Gpio_<3>):
通用I/O口或芯片USB唤醒输出引脚,这四个通用I/O端口连接一个液晶显示屏,以显示接收到的数据。
其它再具体的接线本文限于篇幅不再赘述。
3.USB蓝牙适配器介绍
蓝牙USB适配器采用CSRBlueCore04,可去市场购买,价格大概在三十到四十元左右,用时先向PC机里面装相应的驱动程序,再将USB适配器插入PC机的USB接口中即可与MT1020A端和PDA端进行通信。
至此工业现场通信的三方通信硬件平台的搭建已基本完成,三方通信框图如图6所示:
蓝牙适配器图片
4.VisualStdio2008环境下的PDAWindows应用程序设计
4.1MT1020A端的软件设计
单片机端的软件在Keil平台下进行嵌入式C编程实现,传输层采用UART,单片机通过UART控制蓝牙模块。
软件包括初始化,蓝牙交互,处理数据三个模块。
4.1.1初始化
初始化包括系统初始化和蓝牙初始化。
系统初始化包括CPU时钟初始化,管脚分配,串口初始化等,蓝牙初始化是通过UART给蓝牙模块发送一系列初始化命令,蓝牙模块返回事件,交互完成一系列的复位,鉴权,读地址等初始化操作。
初始化程序主函数如下:
main.c
main()主函数
sys_init()系统初始化,包括设置看门狗,初始化时钟,键盘及液晶,配置端口
bt_init()蓝牙初始化
uart.c
uart_init()串口0初始化,包括设工作方式,开中断,设波特率,开定时器1
限于篇幅,具体主程序的编写不再赘述。
4.1.2蓝牙交互
通信就是初始化完成后若本地蓝牙作从设备,则等待远端蓝牙设备的建链请求,如果接受请求,则继续等待建链成功,获得一个连接句柄,从而进行数据交换,若本地蓝牙作主设备,则通过一系列主动查询,建链,发送数据,断链等操作处理数据就是将数据显示在与单片机相连的LCD上等一系列后续操作。
程序流程图如图8示。
蓝牙交互部分的程序主函数如下:
bt_inquiry()搜索附近蓝牙设备
bt_create_connection(...)与指定蓝牙设备建立连接
bt_send_acl_data(...)发送ACL数据
bt_disconnection(...)与指定蓝牙设备断开连接
4.1.3处理数据
数据结构方面,程序按照HCI规范构造了HCI指令分组cmd_pkt,HCI事件分组event_pkt和HCIACL数据分组acl_pkt的数据结构,并设计了用于标识当前蓝牙设备的hci_device结构体,包括蓝牙设备配置信息hci_info,蓝牙连接信息hci_con和用于存储返回分组信息的接收缓冲区hci_buf[1000],具体如图9所示。
软件采用前后台的方式实现,前台运行主程序,后台定时循环调用HCI状态机。
HCI状态机是一个子程序,用来专门处理蓝牙模块返回的HCI事件分组和HCI数据分组。
状态机通过分析HCI事件分组来决定相应操作,获取相关信息,通过分析HCI数据分组,来接收实际传输数据并存储到接收缓冲区。
具体的HCI状态机的处理流程如图10所示:
HCI状态机初始状态置为IDLE_STATE,根据HCIUART传输层格式规范,按字段取蓝牙模块返回的各个字节,每个字节为一个十六进制数,不同的数代表不同的含义。
第一个字节为分组指示器,标识分组的类型。
ACL数据分组为ACL_PKT(0x02),SCO数据分组为SCO_PKT(0x03),事件分组为EVT_PKT(0x04),另外指令分组为CMD_PKT(0x01),蓝牙模块只返回ACL,SCO和事件分组。
取出第一个字节判断出分组类型。
若为事件分组,则状态机转换为EVENT_HDR_STATE状态,继续取字节,读出事件码和参数长度后,转换到EVENT_DATA_STATE状态,表示再来的字节即为事件参数,读取事件参数,并调用process_event()处理事件,完成后回到IDLE_STATE状态。
若为ACL数据分组,则先转换为ACL_HDR_STATE状态,取出连接句柄,转换为ACL_DATA_STATE状态,处理后续来的数据,即为实际接收到的数据,完成后回到IDLE_STATE状态。
若为SCO数据分组,类同ACL数据分组的处理过程。
HCI状态机要通过系统预先设定的一个定时器定时循环调用,虽然HCI从UART得到的数据流是一块一块的,有可能刚好是一个分组,有可能是几个分组,还可能是一个分组的部分数据,但状态机对接收到的一块数据流的处理是连续进行的,数据流的间断只会造成状态机的暂时等待,而不会影响其正确处理返回分组。
如中途出现分组丢失或错误的字段,状态机会报错并重新置回初始态。
状态机数据处理部分的程序主函数如下:
hci.c
hci_state_machine()hci状态机,定时器3定时10ms中断调用
hci_buf_put_ch()uart0中断接收蓝牙模块返回数据,放入hci_data_buf[1000]
hci_buf_get_ch()从hci_data_buf[1000]读取一个字符待状态机分析
hci_reset(...)复位命令,组合命令分组,调用send_cmd()发送给蓝牙模块
⋯类同hci_reset,hci共4大类命令:
链路管理/链路策略/主机控制器/信息参数
get_opcode(...)将ogf和ocf组合成操作码opcode
le_u16_to_u16(...)实现反位序即大小模式转换
send_cmd(...)将指定长度的hci指令送入指令发送缓冲区并调用uart_send_str()发送出去
uart.c
uart_send_ch(...)发送一个字符
uart_send_str(...)发送一个指定长度的字符串
4.2PDA端的软件设计
C#环境下单片机与PDA无线通信的实现
目前,国内PDA基本采用WindowsMobile操作系统。
WindowsMobile系统是Microsoft公司为智能移动终端设备设计的嵌入式操作系统,基于WindowsMobile操作系统的智能终端设备分SmartPhone和PocketPC两大类。
其中,SmartPhone为智能手机系统,PocketPC为个人掌上电脑。
现在,很多PocketPC也加入电话功能成为PocketPCPhone。
WindowsMobile2003中内置.NetCompactFrameworkCF,方便开发人员对Windows智能移动终端设备的开发。
Microsoft也为WindowsCE提供了很多设备开发工具,如近年来发展迅速的VisualStudio2008中的VisualC#。
VisualC#2008为开发在基于WindowsCE的智能设备(如PocketPC和Smartphone)上运行的软件提供丰富的集成支持,可以使用开发PC程序时所使用的相同代码编辑器、设计器和调试器界面,它还提供仿真程序,让我们可以在开发计算机上运行和调试编写的代码;VisualC#2008中的SerialPort类控制串口资源非常方便,因此,本文选用VisualC#2008来编写蓝牙串口通信程序。
蓝牙串口通信的基本流程包括配置资源参数、打开串口资源、通信读写操作和关闭串口资源。
4.2.1配置资源参数
在WindowsCE系统中,串口与其他通信设备是作为文件进行处理的。
本文对蓝牙串口进行操作用到了C#2008中的SerialPort类,此类在.NETFramework2.0版本中是新增的,用于控制串口文件资源。
初始化SerialPort类实例和配置资源参数方法如下:
namespaceBlueTooth_RS232_
{
publicpartialclassFormMain:
Form//窗体
{
publicFormMain()
{
InitializeComponent();//窗体初始化
}
privateComPortcomPort=newComPort();//COM端口实例化
privatevoidFormMain_Load(objectsender,EventArgse)
{
this.SetMenu(Port);//设置菜单
}
privatevoidSetMenu(ComPortcomPort)
{
switch(comPort.PortName)//选择COM端口
{
case"COM1":
this.menuCOM1.Checked=true;
this.menuCOM2.Checked=false;
this.menuCOM3.Checked=false;
this.menuCOM4.Checked=false;
this.menuCOM5.Checked=false;
this.menuCOM6.Checked=false;
this.menuCOM7.Checked=false;
this.menuCOM8.Checked=false;
break;
……
default:
this.menuCOM1.Checked=true;//默认值设为COM1
this.menuCOM2.Checked=false;
this.menuCOM3.Checked=false;
this.menuCOM4.Checked=false;
this.menuCOM5.Checked=false;
this.menuCOM6.Checked=false;
this.menuCOM7.Checked=false;
this.menuCOM8.Checked=false;
break;
}……
波特率、停止位、校验位等参数的设置方法和com端的设置基本类似,限于篇幅,不再赘述。
4.2.2打开串口资源
打开串口资源在串口参数配置正确的情况下,只需调用SerialPort类的Open方法即可打开串口连接。
方法如下:
try
{
if(!
this.serialPort.IsOpen)
this.serialPort.Open();//打开串口
}
4.2.3PDA通信读写操作
在成功设置通信参数并打开串口连接后,可采取事件触发的方式对数据进行接收与发送处理。
本文使用SerialPort类的DataReceived事件方法来处理SerialPort对象的数据接收事件,同时还要用到SerialDataReceivedEventHandler委托来处理SerialPort对象的DataReceived事件,使用SerialPort类中的DataWrite事件方法来处理数据的发送。
由于MT1020A端、PC端与PDA端所发送或接收的信号均为二进制所转化成的ASCII码,所以发送与接收信号时存在一个数据的编码与解码的过程[12]。
具体方法如下:
privateStringBuilderbuffer=newStringBuilder();//缓存实例化
privatevoidserialPort_DataReceived(objectsender,System.IO.Ports.SerialDataReceivedEventArgse)
{
byte[]recBytes=newbyte[this.serialPort.BytesToRead];
this.serialPort.Read(recBytes,0,recBytes.Length);//读取ASCII码数据
stringrecString=ASCIIEncoding.ASCII.GetString(recBytes,0,recBytes.Length);//数据解码
this.buffer.Append(recString);//将数据重载入缓存
}
privatevoidtimer_Tick(objectsender,EventArgse)//将数据从缓存传送到接收区
{
if(this.cBox.Checked)//如果该项选中,则转化为unicode字符显示
{
char[]chars=this.buffer.ToString().ToCharArray();
for(inti=0;i{
this.textReceive.Text+=((byte)chars[i]).ToString("X")+"";}
}
else
{
this.textReceive.Text+=this.buffer.ToString();//如果不选中该项则为字符串显示
}
this.buffer.Remove(0,this.buffer.Length);//清空缓存
}
privatevoidtextSend_GotFocus(objectsender,EventArgse)
{
this.inputPanel.Enabled=true;
}
privatevoidbtnSend_Click(objectsender,EventArgse)//发送串口数据
{
stringsendString=this.textSend.Text;
byte[]sendBytes=newbyte[sendString.Length];
ASCIIEncoding.ASCII.GetBytes(sendString,0,sendString.Length,sendBytes,0);//将数据转换成ASCII码
this.serialPort.Write(sendBytes,0,sendBytes.Length);//将ASCII码写入串口