《ZigBee教学方针教育材料.doc》由会员分享,可在线阅读,更多相关《ZigBee教学方针教育材料.doc(135页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、.*ZigBee学习之1点灯我用的编译环境是IARfor51 7.30B,再介绍一下我的开发板的情况,ZigBee模块用的是CC2430.这块芯片是一款Soc的芯片,集成了8051内核和ZigBee射频部分,只要很少的外部电路就可以搭建一个射频模块。因为其中的是8051的内核,所有对于熟悉8051系列的同学们来说,基本的一些操作就很简单了,这里我们在温习一下,顺便对CC2430芯片进行一下熟悉。嵌入式的一大特点是其底层的软件和硬件紧密相关,如果没有数字电路的知识,那么作起来是很困难的。我们先介绍一下基本的管脚分配情况:P0的2和3接到了一个232电压转换芯片上,可以用来和PC进行通信,LCD_
2、RST,LCD_CS,接的是LCD的复位和片选端,这里我用到的LCD是兼容PCD8544的NOkia5110的LCD,为SPI总线LCD,84X48点阵。CC2430_MOSI,CC2430_CLK都接到LCD上了。P1_0接到一个调试LED上面,为高电平点亮。下面的第一个实验就很简单了,我们只要把P1_0配置为通用IO,输出方式,然后从这里输出高电平,那么就可以点亮这个LED了。用到的寄存器为:P1配置寄存器P1SEL,P1方向寄存器P1DIR程序如下:#include#define DEBUG_LED P1_0void delay(unsigned int n)/26 cycles del
3、aywhile(-n)asm(NOP);void LEDInit()P1SEL &= 0XFE; /P1_0 defined General purpose I/OP1DIR |= 0X01; /P1_0 defined Outputmain()LEDInit();while(1)DEBUG_LED = 1; /Led lightdelay(50000);DEBUG_LED = 0;delay(50000);编译通过以后就用TI的官方工具SmartRF Flash Programmer将生成的HEX文件,烧录到CC2430吧,激动的时刻,呵呵如果点亮了这个小小的LED那么恭喜你,你的硬件因该是
4、没有问的了,一个小小的胜利后我们就有更多的勇气和信心前进咯!ZigBee学习之2SPI&LCD今天的任务是用SPI总线方式点亮LCD屏幕,呵呵这里要涉及到两个内容,一个是SPI总线,一个LCD。CC2430的话已经集成了SPI总线,只要将IO口配置为外设,然后将USART配置成SPI方式就可以了。关于LCD其实也很简单,很多没有接触过的同学可能将其想象的太过复杂了,就是将字或者图像转换为一个一个的点,如果要这点显示东西呢,就把这点点亮,否则则不点亮。其实PCD8544已经将很多细节的东西做好了,我们要做的呢,就是发送一串命令序列,然后发送要显示的数据就可以了。看看PCD8544的芯片资料,我们
5、还会发现在最后它竟然给出了操作实例,呵呵相信大家都能看懂的吧,如果有看不懂的可以给我留言或者是QQ联系我哦,我如果知道的话一定给大家详细的答复!CC2430的SPI的是放在USART外设里面的,和UART放在一起,同一个USART即可以配置成UART也可以配置成SPI,SPI的主从模式通过相关的寄存器来选择。关于管脚的分配也不难,这里就不多说了,其实这里还算是8051的基础实验,对于8051很熟悉的同学肯定觉得我是在说废话了,哈哈!这里只提一下关于SPI应该注意的一点问题:1、PCD8544 的SPI是高电平采样,所以,主机端必须是高电平之前要把数据准备好。所以主机端的发送(MOSI)因该设为
6、下降沿采样。当用SPI和PCD8544通信时,速率不能太低,否则点不亮LCD,或者是出来乱码下面是引用网友的SPI总线心得,我觉得看看很有益处:SPI接口时钟配置心得:在主设备这边配置SPI接口时钟的时候一定要弄清楚从设备的时钟要求,因为主设备这边的时钟极性和相位都是以从设备为基准的。因此在时钟极性的配置上一定要搞清楚从设备是在时钟的上升沿还是下降沿接收数据,是在时钟的下降沿还是上升沿输出数据。但要注意的是,由于主设备的SDO连接从设备的SDI,从设备的SDO连接主设备的SDI,从设备SDI接收的数据是主设备的SDO发送过来的,主设备SDI接收的数据是从设备SDO发送过来的,所以主设备这边SP
7、I时钟极性的配置(即SDO的配置)跟从设备的SDI接收数据的极性是相反的,跟从设备SDO发送数据的极性是相同的。下面这段话是Sychip Wlan8100 Module Spec上说的,充分说明了时钟极性是如何配置的:The 81xx module will always input data bits at the rising edge of the clock,and the host will always output data bits on the falling edge of the clock.意思是:主设备在时钟的下降沿发送数据,从设备在时钟的上升沿接收数据。因此主设备这
8、边SPI时钟极性应该配置为下降沿有效。又如,下面这段话是摘自LCD Driver IC SSD1289:SDI is shifted into 8-bit shift register on every rising edge of SCK in the orderof data bit 7, data bit 6 data bit 0.意思是:从设备SSD1289在时钟的上升沿接收数据,而且是按照从高位到地位的顺序接收数据的。因此主设备的SPI时钟极性同样应该配置为下降沿有效。时钟极性和相位配置正确后,数据才能够被准确的发送和接收。因此应该对照从设备的SPI接口时序或者Spec文档说明来正确
9、配置主设备的时钟。老规矩,上程序:先来一个不用SPI方式控制LCD显示的实例:#include periodef.h#include void delay(uint n)/26 cycles delaywhile(-n)asm(NOP);void LCD_IOInit()P0SEL &= 0X03;P0DIR |= 0X03;P1SEL &= 0XF0;P1DIR |= 0XF0;void LCD_WriteOneByte(uchar data)uchar i = 0;for(i=0;i8;i+)LCD_SCK = 0;if(datai)&0x80)LCD_SIN = 1;elseLCD_SI
10、N = 0;LCD_SCK = 1;void LCD_WriteMByte(uchar *data,uint num)while(num-)LCD_WriteOneByte(*data);data+;void LCD_Init()LCD_nCS = 0;delay(100);LCD_nRES = 0;delay(100);LCD_nRES = 1;delay(100);LCD_DnC = 0;LCD_WriteOneByte(0x21);LCD_WriteOneByte(0xC8);LCD_WriteOneByte(0x06);LCD_WriteOneByte(0x13);LCD_WriteO
11、neByte(0x20);LCD_WriteOneByte(0x0C);LCD_DnC = 1;main()uint i = 0;uchar Hello=0x00,0x7E,0x10,0x10,0x7E,0x00,/*H,0*/* (6 X 8 , 楷体_GB2312 )*/0x00,0x7E,0x52,0x52,0x42,0x00,/*E,1*/* (6 X 8 , 楷体_GB2312 )*/0x42,0x7E,0x42,0x40,0x40,0x00,/*L,2*/* (6 X 8 , 楷体_GB2312 )*/0x42,0x7E,0x42,0x40,0x40,0x00,/*L,3*/* (
12、6 X 8 , 楷体_GB2312 )*/0x00,0x3C,0x42,0x42,0x3C,0x00,/*O,4*/* (6 X 8 , 楷体_GB2312 )*/;LCD_IOInit();LCD_Init();/for(i=0;i30;i+)/LCD_WriteOneByte(Helloi);/LCD_WriteMByte(Hello,30);LCD_nCS = 1;下面是采用SPI总线方式控制LCD显示的例子:/=/This file is applicable to Eshine EXBEE-DK V1/Function:LCD test,the LCD use SPI BUS.The
13、 SPI BUS occupation P1-USART1-ALT.2/InPut :/OutPut :/Created :longfan,2010.1.10/Modify :/=#include periodef.h#include font.h#include TestBMP.h#include void delay(uint n)/26 cycles delaywhile(-n)asm(NOP);void LEDInit()P1SEL &= 0XFE; /P1_0 defined General purpose I/OP1DIR |= 0X01; /P1_0 defined Output
14、DEBUG_LED = 1; /LED light up/=/Initial P1-USART1-SPIvoid SPIInit_U1_P1(void)PERCFG |= 0X02; /USART1.alt.2,P1P1SEL |= 0XE0; /P1,ISP,P1_4(LCD_DnC) defined general IOP2SEL |= 0X40; /USART1 has priorityU1GCR |= 0x20; /MSB first,Negative clock polarity,Data is output on MOSI on the falling edge of CLKU1G
15、CR |= 19; /MAX Baud rate(17),falling edgeU1BAUD = 0;UTX1IF = 0; /Clear interrupt/=/P1-USART1-SPI Send One Bytevoid SPI_SendOne_U1_P1(uchar data)U1DBUF = data;while(!UTX1IF);UTX1IF = 0;/=/P1-USART1-SPI Send Multily Bytevoid SPI_Send_U1_P1(uchar *data,uint length)while(length)SPI_SendOne_U1_P1(*data);
16、data+;length -= 1;/=/LCD Use SPI BUS,Set the first display piex./When after call this function can direct call SPI data output function/0X83,0Y5void SPI_LCDSetPos(uchar X,uchar Y)LCD_DnC = 0;SPI_SendOne_U1_P1(0x80 | X);SPI_SendOne_U1_P1(0x40 | Y);LCD_DnC = 1;/=/LCD Use SPI BUS,Clear the LCD Display
17、and its RAM.void SPI_ClearLCD()uint i;SPI_LCDSetPos(0,0);for (i=0; i504; i+)SPI_SendOne_U1_P1(0);/=/LCD Use SPI BUS,Send one LCD Commandvoid SPI_LCDWriteOneComm(uchar command)LCD_DnC = 0;SPI_SendOne_U1_P1(command);/=/LCD Use SPI BUS,Send More than one LCD Commandvoid SPI_LCDWriteMulComm(uchar *comma
18、nd,uchar num)LCD_DnC = 0;SPI_Send_U1_P1(command,num);/=/LCD Use SPI BUS,Send More than one datavoid SPI_LCDWriteData(uchar *data,uchar length)LCD_DnC = 1;SPI_Send_U1_P1(data,length);/=/LCD Use SPI BUS,Display a english character Without set position,The inverse argument control/the inverse video mod
19、e.When use font library call this function to display./InPut :character:The character want to display/ inverse :Inverse video mode(1) or not(0)/OutPut :/Created :longfan,2010.1.10/Modify :/=void SPI_LCDWriteChar(uchar character,uchar inverse)uchar line;LCD_DnC = 1;if(inverse)for(line=0;line6;line+)S
20、PI_SendOne_U1_P1(font6x8character-32line);elseSPI_Send_U1_P1(uchar *)font6x8character-32,6);/=/LCD Use SPI BUS,Display a english character at (X,Y),The inverse argument control/the inverse video mode.When use font library call this function to display./InPut :character:The character want to display/
21、 X,Y :The position want to display/ inverse :Inverse video mode(1) or not(0)/OutPut :/Created :longfan,2010.1.10/Modify :/=void SPI_LCDDISPChar(uchar character,uchar X,uchar Y,uchar inverse)uchar line;SPI_LCDSetPos(X,Y);if(inverse)for(line=0;line6;line+)SPI_SendOne_U1_P1(font6x8character-32line);els
22、eSPI_Send_U1_P1(uchar *)font6x8character-32,6);/=/LCD Use SPI BUS,Display a english string at (X,Y)void SPI_LCDWriteEnString(uchar *EnString,uchar X,uchar Y,uchar inverse)uchar line;SPI_LCDSetPos(X,Y);while(*EnString)uchar chara = *EnString;chara -= 32;if(inverse)for(line=0;line6;line+)SPI_SendOne_U
23、1_P1(font6x8charaline);elseSPI_Send_U1_P1(uchar *)font6x8chara,6);EnString+;/=/LCD Use SPI BUS,Draw a AREA use Horizontal(thus the High pixel must be a multiple of 8)./When use dot matrix to display use this function./InPut :data :The dot matrix of the data want to display/ X,Y :The position want to
24、 display/ wide,high:The pixel of wide and high/OutPut :/Created :longfan,2010.1.10/Modify :/=void SPI_LCDDrawArea_H(uchar *data,uchar X,uchar Y,uchar wide,uchar high)uchar row;uchar i;SPI_LCDSetPos(X,Y); /Set positionrow = high/8; /calculate the row numberfor(i=0;irow;i+)SPI_Send_U1_P1(data+(i*wide)
25、,wide);Y += 1;SPI_LCDSetPos(X,Y); /Set position/=/LCD Use SPI BUS,Initial LCDvoid SPI_LCDInit()P0DIR |= 0X03; /P00(LCD_nCS),P01(LCD_nRES) Defined outputP1DIR |= 0X10; /P1_4(LCD_DnC) defined OutpuP2DIR |= 1; /LCD_BKLLCD_nCS = 0; /LCD Enabledelay(100);LCD_nRES = 0; /LCD RESERTdelay(100);LCD_nRES = 1;d
26、elay(100);LCD_BKL = 0; /D5 light up/Send Initial command/LCD_DnC = 0;/SPI_SendOne_U1_P1(0x21); /Chip is active,Horizontal addressing,Use extended instruction set/SPI_SendOne_U1_P1(0xC8); /Set Vop/SPI_SendOne_U1_P1(0x06); /Temperature coefficient/SPI_SendOne_U1_P1(0x13); /1:48/SPI_SendOne_U1_P1(0x20)
27、; /Use basic instruction set/SPI_SendOne_U1_P1(0x0C); /Display mode is Normal modeuchar Init_Comm=0x21,0xC8,0x06,0x13,0x20,0X0C;SPI_LCDWriteMulComm(Init_Comm,6);SPI_ClearLCD(); /Clear Display RAMSPI_LCDWriteOneComm(0X0C);LCD_DnC = 1; /Send Display Datamain()uchar Hello=0x00,0x7E,0x10,0x10,0x7E,0x00,
28、/*H,0*/* (6 X 8 , 楷体_GB2312 )*/0x00,0x7E,0x52,0x52,0x42,0x00,/*E,1*/* (6 X 8 , 楷体_GB2312 )*/0x42,0x7E,0x42,0x40,0x40,0x00,/*L,2*/* (6 X 8 , 楷体_GB2312 )*/0x42,0x7E,0x42,0x40,0x40,0x00,/*L,3*/* (6 X 8 , 楷体_GB2312 )*/0x00,0x3C,0x42,0x42,0x3C,0x00,/*O,4*/* (6 X 8 , 楷体_GB2312 )*/0x00,0x7E,0x10,0x10,0x7E,
29、0x00,/*H,0*/* (6 X 8 , 楷体_GB2312 )*/0x00,0x7E,0x52,0x52,0x42,0x00,/*E,1*/* (6 X 8 , 楷体_GB2312 )*/0x42,0x7E,0x42,0x40,0x40,0x00,/*L,2*/* (6 X 8 , 楷体_GB2312 )*/0x42,0x7E,0x42,0x40,0x40,0x00,/*L,3*/* (6 X 8 , 楷体_GB2312 )*/0x00,0x3C,0x42,0x42,0x3C,0x00,/*O,4*/* (6 X 8 , 楷体_GB2312 )*/;uchar *tring = Hell
30、o,CC2430! i LOVE THIS!;uchar *tring1= Hello,CC2430!;LEDInit();SPIInit_U1_P1();SPI_LCDInit();/SPI_Send_U1_P1(uchar *)EshineLOGO,sizeof(EshineLOGO)/sizeof(uchar);/delay(50000);/delay(50000);/delay(50000);/delay(50000);/delay(50000);/SPI_ClearLCD();/PI_Send_U1_P1(Hello,sizeof(Hello)/sizeof(uchar);/SPI_
31、LCDDISPChar(Q,0,0,1);/SPI_LCDWriteEnString(tring,10,0,0);/SPI_LCDWriteEnString(tring,0,2,1);/SPI_LCDDrawArea_H(Hello,40,4,30,16);/SPI_ClearLCD();/SPI_LCDSetPos(0,0);/SPI_Send_U1_P1(uchar *)LOGO,sizeof(LOGO)/sizeof(uchar);/SPI_LCDWriteData(uchar *)LOGO,sizeof(LOGO)/8);SPI_LCDWriteData(uchar *)LOGO,si
32、zeof(LOGO)/sizeof(uchar);ZigBee学习之3USART之UARTUART在现在的PC是不常见了,但是在嵌入式领域里面依然是不可或缺的一个接口,不管是调试,红外还是其他基本的通信,用UART相对于其他总线来说总是来的简单方便一下,而且由于技术成熟开发起来也更加快捷。CC2430自带了USART,可以配置成UART或者SPI模式,由于CC2430管脚的限制,所以只能同时使用两个外设,我就搞不懂为啥chipcon将CC2430的管脚的USART还非设个位置1位置2干什么,只要固定一个位置,可以配置不是一样的灵活好用么?加了位置可变反而要写更多的代码进行更多的配置不是变的麻烦
33、了么?关于CC2430的UART使用其实前面一节SPI&LCD已经有过涉及了,这里主要是要注意一下UART的数据传输格式和波特率的配置,配置的波特率一定要和自己的串口调试助手是一样的不然的话出来乱码可不要怪我没有提醒啊,呵呵!关键代码主要是UART的发送部分:void UART_SEND_U0(uchar *data,int length)/UART Send datawhile(length-)U0DBUF = 0X90;U0DBUF = *data+;while(!UTX0IF);UTX0IF = 0;我这里是通过查询传输完成中断标志来进行的,如果打开中断的话可以在中断服务程序中进行数据的
34、处理,也就没必要通过查询的方式来判断UART是否发送完数据了! ZigBee学习之4DMADMA(直接内存控制),DMA可以在外设之间传递数据而不要CPU的干预,节约了大量的CPU时间,并且减轻了CPU的负担,是一种快速高效的通信方式,在CC2430中集成了DMA控制器,提供5个DMA通道,并且官方推荐使用DMA方式传送RF寄存器中的数据,而且为了方便DMA对数据进行传输CC2430中对RF寄存器,硬件寄存器等进行了映射,全部映射到了XDATA区域,这样就可以用DMA来读取寄存器的数据,给操作带来了很大的方便。下面我们就对CC2430中集成的DMA进行试验。关于DMA的寄存器并不多,但是DMA
35、的操作和其他单片机寄存器的操作有一些不同的地方,就是DMA市通过读配置的方式来实现DMA的初始化的,所有的配置信息都存放在一个固定的地址中,当药启动DMA时只要先读入配置的地址然后启动相应地通道就可以了。关于DMA的传输方式,在CC2430中集成的DMA控制器有四种传输模式:单模式:触发一次只能传送一个字节(字),直到传送完指定的长度后通知CPU,并且解除DMA通道工作状态;块模式:当触发一到就传输指定的长度,直到完成后就通知CPU;重复单一模式和重复块模式和非重复模式的区别在于当完成指定长度数据的传输并通知CPU后并不解除DMA通道的工作状态,而是DMA通道重新进入工作状态。关于DMA的触发
36、时个很灵活的东西,比如我可以用某个特定的触发条件,那么在程序中我就要确保这个触发条件在一定的情况下能够得到满足,否则得话DMA永远也不能进行传输,不过通过手动来第一次的启动DMA好像也是个不错的方法哦,呵呵!DMA处理流程:1、写DMA配置参数数据结构;2、设置DMA配置的读取地(将配置参数数据结构作为第几个DMA通道的配置);3、关闭将要使用的通道;4、启动相应的通道;5、清除相应通道的DMA传输中断标志;(6、手动触发相应的通道开始传输;)6、等待DMAIRQ变化。不管是什么设备中的DMA基本上都是这个流程。前几天帮同学调试赛灵思平台的SOC上的DMA也是这样做的,可惜一直出现总线错误,找
37、不到原因!只是不同的平台可能程序库的集成度不同,越高级的可能使用起来就越方便。ZigBee学习之5无线电今天终于发了第一篇跟CC2430无线电有关的文章了,哈哈。其实无线单片机还是挺简单的,只要把相关的东西配置好,然后按部就班的发送接收就OK了。对于包的处理无非就是封包和解包,怎么封就怎么解好了。CC2430的无线电提供了灵活的配置,可以兼容IEEE802.15.4,也可以自己写一个协议,当然我们一般是用它来做ZigBee的,当然是采取兼容IEEE802.15.4罗!手册中有CC2430的无线电控制状态图,我觉得还是应该好好看看的,其实把那个图搞明白了,无线电的控制就没有问题了,剩下的就是按标
38、准封包解包和功率控制的问题了。我看了下官方的例子程序,再加入自己的与开发板相关的代码,烧录进去就能够很好的运行了。其中一个开发板按键,对应于另一个开发板显示相应的控制,当然只能点对点的,没有加入路由的东西在里面,也没有加入安全控制。不过TI的例子程序里面是有简单的路由和安全控制的,感兴趣的朋友们可以自己加上,关于CC2430的无线电有几点自己觉得应该记下来的:1、数据的发送首先是每字节分为两个符号,然后每个符号映射为32个芯片(其实一个芯片就是1bit),然后芯片以2MChips/s的速度发送,且低位在前。2、RF的控制多数是通过CSP命令选通来实现的,而CSP指令的实现,其实就是对RFST寄
39、存器写入不同的值来实现的。对其他寄存器的操作一般是配置RF传输参数。3、SFD中断用来监测帧,FIFO中断可以用来监测数据是否读完。下面我们来看一看无线电控制状态图首先是打开模拟稳压器对无线电的供电,只要把RFPWR.RREG_RADIO_PD位清零即可,然后等待稳压器的稳定,当稳压器稳定后会发送CPU中断,所以可以通过检测中断标志RFIF.IRQ_RREG_ON是否设置来判断稳压器是否稳定。然后就是设置使用32Mhz的高速晶体振荡器,因为要使用无线电的话就必须使用32MHz的晶体振荡器,一直等到晶体振荡器稳定工作,可以通过检测SLEEP.XOSC_STB位是否设置来实现。当然前面的部分不拘泥
40、于先后顺序,有可能在使用无线电之前就使用的是32Mhz的晶振了。在空闲或者接收状态时通过发送STXON或者STXONCCA后812个符号周期后就可以进入发送状态,TX_CALIBRATE下面的数字好像说到是每个状态在整个图中的顺序,然后就是发送帧前导和帧首界定符,这些都是自动加在帧前发送的,只要在相关的寄存器中设置好就可以。然后就是发送FIFO中的数据,这里要注意FIFO的数据一般是整个MPDU+帧长度域。发送完成后可以进入空闲模式也可以进入接收模式。通过SRXON命令选通进入接收状态,然后CC2430会自动查找帧首界定符,当找到就进入帧接收状态,如果FSMTC1.RX2RX_TIME_OFF
41、为1,即不发送应答,或者地址识别失败或者应答发送失败,则重新进入帧首界定符查找状态。帧接收完成后进入发送应答帧状态,在1230个符号周期后发送应答帧首,然后发送应答帧。这就是关于控制状态图的一些概要分析了。总的看来只要设置好各个控制寄存器然后通过发送CSP指令就可以完成无线电传送了。ZigBee学习之6无线电2今天把TI的例子程序里的基本RF看了下,有的地方还没有完全看懂,发上来和大家分享一下/*Filename:basic_rf.cDescription:Basic RF library*/* INCLUDES*/hal_int.h包含了控制中断的宏#include hal_int.h/ U
42、sing halMcuWaitUs(),hal_mcu.h中是一些延时函数#include hal_mcu.h/通道编程的宏,以及硬件RF初始化,SECURITY_CCM宏是用来控制安全MAC的#include hal_rf.h#ifdef SECURITY_CCM#include hal_rf_security.h#endif/basic_rf.h中定义了RF配置用的数据结构#include basic_rf.h#ifdef SECURITY_CCM#include basic_rf_security.h#endif#include util.h/ Using min()#include s
43、tring.h/* CONSTANTS AND DEFINES*/ Packet and packet part lengths#define PKT_LEN_MIC8#define PKT_LEN_SECPKT_LEN_UNSEC + PKT_LEN_MIC#define PKT_LEN_AUTH8#define PKT_LEN_ENCR24/ Packet overhead (frame control field, sequence number, PAN ID,/ destination and source) + (footer)/ Note that the length byte itself is not included included