我要投搞

标签云

收藏小站

爱尚经典语录、名言、句子、散文、日志、唯美图片

当前位置:双彩网 > 帧尾定界符 >

在mini2440上面搞定CC2500物理层驱动

归档日期:06-01       文本归类:帧尾定界符      文章编辑:爱尚语录

  在linux下面的驱动,在这个过程中遇到了好多问题,特此总结出来和大家分享。但是需要注意的事情是:

  第一,本文不负责程序的具体讲解,诸如每一行程序都讲什么:这个在程序的里面有注释。本篇文章更侧重于从整体结构上让大家对于linux下的CC2500DE驱动有一个整体的了解,如果到时候需要深入研究的时候,再来看具体的代码;

  第二,很多师弟师妹没有习惯在linux下编程,或曰,在操作系统下面写程序;并且,对于本专业的东西理解并不扎实。但是,文章中不可能就每一个涉及到的概念都大加讲解。因此,这篇文章还是需要有一些基础才能来阅读的,如果遇到什么不明白的地方,请及时来问我,或者跟帖,或者自己查资料。毕竟,这个驱动花费了我半个多月的时间,其中遇到的问题,不可能在一篇文章中就讲得清清楚楚。

  如果大家看过实验室的WSN方面的程序,可能会被其中的架构搞得天昏地暗。这里,简单的帮助大家把实验室的WSN的软件、硬件方面捋一捋。

  说到软件,就不能不说硬件。我们的节点由两部分组成,一个是单片机,一个是CC2500的射频模块。射频模块通过SPI接口和单片机进行通信。除了SPI模块用到的4条线还需要告诉单片机“我接收到一个数据”,这个地方CC2500可以通过配置GDO来实现。我们这里采用的CC2500的GDO0作为单片机的一个外部中断,当接收到数据的时候,GDO0就会变为低电平,然后触发CC2500的中断,从而接收数据。

  那么,CC2500究竟是如何来进行数据发送、接收的呢?其实很简单。如果大家稍微用过一点可以控制的芯片就会知道,很多芯片内部都有寄存器,CC2500之所以能够完成发送、接收的功能,就是通过配置寄存器来完成的。比较重要的配置有信道、波特率、信号强度等等,另外,CC2500还有64bytes的RXFIFO和64bytes的TXFIFO,他们的作用就是用来发送和接收。当配置CC2500结束之后,如果用来发送,那么就把数据放在TXFIFO里面,然后把CC2500的状态变为发射状态,数据就自动发送出去了。同样的道理,当RXFIFO里面接收到了数据之后,CC2500就会如前所说,发出一个中断,通知单片机来读取数据。

  简单的讲,因为是无线通信,没有一个时钟的存在,因此本质上所有的无线通信都是一个异步的通信。那么,就需要发送和接收的双方首先对数据进行同步这个就是同步头的作用。随后的是PHY的头,很简单,就是一个长度。换句线个)。随后就是负载的内容了,简单吧?另外,由于CC2500是一个802.15.4兼容的芯片,这一部分内容都已经固化在芯片里面了,像同步头这种东西,都是芯片帮我们完成(当然也可以自行配置)。我们只需要把写入的数据大小和数据内容写入即可。

  虽然简单,但是还有一个问题:每次从CC2500中读取了数据,存放到哪里呢?有的同学可能想的比较简单,比如建立一个大数组,收到多少个数,放在里面就行了。但是,这样就会遇到问题:如果收到了两个包,上层来不及处理怎么办?建立两个大数组?更多的包呢?当然,我们可以通过建立好多个数组来解决这个问题。但是,从效率上讲,这个是非常笨的一个办法。因此,我们建立了一个环形缓冲区PHY_RX_BUFFER,来解决这个问题。环形缓冲区的具体原理不过多涉及,可以自行百度。

  另外一个问题就是,如果我们从CC2500中接收到了数据,那么应该怎样才能告诉上层来进行处理呢?这里就要用到操作系统的消息机制了。如果确定接收到了一个数据,那么就给上层发送一个消息,来通知上层。上层接收到这个消息,就会知道接收到了数据。

  具体内容可以参见老师的《无线传感器网络技术与工程应用》这本书,这里不再详细的讲,大概内容就是,会有一系列的帧头,然后是帧数据,最后有校验。而我们最关心的就是帧的内容。但是,帧头也比较麻烦,因此我们需要首先对帧头进行处理,把数据给“剥离”出来,这也是基本上所有的协议栈解析协议的方法。

  硬件上,我们采用的是mini2440开发板,和实验室的CC2500节点(把单片机焊掉,然后把mini2440的相应管脚接到上面)。

  Common.h主要是包含了很多linux的头文件,并且对一些数据类型做了定义

  Driver.h主要是定义了很多和CC2500进行通信,并且利用CC2500进行发送和接收的内容

  Phy.h主要是完成了一些诸如信道设定、通信速率等功能,并且把CC2500里的数据读到环形缓冲区里面

  CC2500.c这个就是完成设备注册、读写函数、iocontrol等功能

  在应用程序中read/dev/CC2500这个文件,如果有数据,会返回相应的数据。其中,返回的数据中第一个字节为数据的长度(不包括该字节本身),后面为相应的数据。

  如果是写文件的话,只需要向/dev/CC2500中写入相应的数据即可。写入的时候需要注意,第一个字节同样为数据长度(不包括该字节本身),后面跟相应的数据。当写入的字节合适的时候,驱动会自动执行发送函数。如果写入的字节数量和写入的数据第一个字节不匹配的时候,会返回错误。

  封装,接收回来的包进行包的解析。这一部分的内容还不全面,仅仅是将原来的程序移植过来,还有很多需要改动的地方,有待补充。因此,这里只是提供源代码,具体的说明请参见程序内部

  CC2500inuse-objs这句线inuse.ko是由哪几个文件组成的。这样就实现了模块化的处理。

  需要注意的是,CC2500inuse-objs和冒号之间需要有个空格,不然会出错误。这个地方我搞了好久。

  第一,在调试的过程中,发现板子和2500没有办法进行通信。一开始怀疑是2500芯片的问题,后来确认2500芯片没有问题之后,用

  示波器看了一下波形,发现SPI引脚上没有输出。进而发现,对SPI寄存器进行读写的时候,无论写入是什么,读出的都是0。后来发现,原来是PCLK(也就是SPI模块的时钟)没有使能,囧。设置了寄存器之后,问题就解决了。第二,CC2500驱动没有办法自动在/dev/目录下面创建节点。这个问题可以参考下面几篇文章:

  我们通过udev来创建节点。但是,udev是应用层的东东,不要试图在内核的配置选项里找到它;加入对udev的支持很简单,只要在驱动初始化的代码里调用class_create为该设备创建一个class,再为每个设备调用class_device_create创建对应的设备。

  换句话说,首先要为每一个设备创建一个类。然后用这个类去申请一个设备节点。

  第三,在调试的过程中,发现只要一启动CC2500,那么液晶屏就熄灭了。调试了半天也没有找到原因。

  最后发现,在配置S3C2440中GPGCON寄存器的时候,对寄存器直接进行了覆盖性的修改;而该寄存器还管理着LCD的电源...于是,对寄存器进行覆盖性修改的时候,悲剧了...

  总结一下吧,在linux下2500驱动编写的过程中,如果涉及到寄存器级别的操作,和单片机一样,必须十分注意各个模块之间的关系,以及相关模块的寄存器配置,不要认为linux会全部给你配好!

本文链接:http://passion2017.com/zhengweidingjiefu/5.html