Simpliciti协议栈移植笔记一
来源:互联网 发布:如何开淘宝店详细步骤 编辑:程序博客网 时间:2024/06/05 10:01
第一次写博客,觉得应该把学习的心得体会记下来!长期更新。希望能帮助到新手少走弯路,也希望能提出问题,大家一起讨论,一起进步。转载请标明出处。谢 谢 http://blog.csdn.net/libin55/article/details/51203727
简要说明:
SimpliciTI 是TI针对简单低射频网络的低功耗射频协议。
支持两种网络拓扑结构,小型星型网络与点对点通信,星型网络最大支持30个节点,相对Zigbee协议栈而言,该协议栈资源小,仅需8KFlash左右,(本人大概占用10K)移植也很简单。可以很好的兼容小数据低功耗应用场合。
本章主要讲解SimpliciTI星型网络应用部分。
一、协议栈组网原理
现科普一下星型组网的原理吧!首先,射频模块之间能进行正常的数据收发。我们规定在网络中只允许存在一个中心节点,他可以与网络中任一子节点通信,这样便实现了对网络的监控与管理!
子节点与子节点是不能直接通信的,必须通过中心节点才能实现通信。下图为星型网络拓扑结构图,看图就比较好理解了
二、星型网络结构
星型网络由三部分组成。
中心节点(AP):星型网络的管理节点,是长供电的设备。单个网络仅可允许存在一个AP,协议栈中不同网络是通过宏定义JoinToken进行区分。
传感节点(ED):传感设备子节点,可进入睡眠模式(主要电池供电方式)。
范围扩展(RE):扩展网络的无线距离(路由功能),实际就是在转发数据帧,以扩展发送者的有效距离。目前网络最大支持4个RE,也属于长供电设备。
二、协议栈移植
协议栈源码可以到TI官网下载,可能官网下载比较慢,这里就我直接上传了。
下载地址http://download.csdn.net/detail/libin55/9499966
安装后会在根目录生成Texas Instruments文件夹,里面有对应的例程源码与英文文档。里面对应的是IARfor8051与IARforMPS430的工程。这里我就以8051的工程进行解读把。
针对IAR上面的目录文件讲解一下吧
bsp:板级支持包,主要是板载的一些外围器件的初始化与MCU寄存器的配置。
mrfi:射频驱动的代码,CC2530是嵌入射频部分,内核是8051的。该文件内核心代码为mrfi_radio.c,关于射频的配置接口都在这里面。
nwk:网络层底层数据发送与接收的接口,主要为协议层部分。
nwk applications:网络层上层应用代码,实际开发中使用的接口。
我们如果需要移植其他平台的话,其实只需要修改bsp与mrfi里面的部分代码,而网络协议层是不需要进行修改的。
三、协议栈应用部分
好了,开始讲应用部分!直接进入main函数,这段针对代码讲解。
void main (void){ bspIState_t intState;#ifdef FREQUENCY_AGILITY memset(sSample, 0x0, sizeof(sSample));#endif BSP_Init(); /* If an on-the-fly device address is generated it must be done before the * call to SMPL_Init(). If the address is set here the ROM value will not * be used. If SMPL_Init() runs before this IOCTL is used the IOCTL call * will not take effect. One shot only. The IOCTL call below is conformal. */#ifdef I_WANT_TO_CHANGE_DEFAULT_ROM_DEVICE_ADDRESS_PSEUDO_CODE { addr_t lAddr; createRandomAddress(&lAddr); SMPL_Ioctl(IOCTL_OBJ_ADDR, IOCTL_ACT_SET, &lAddr); }#endif /* I_WANT_TO_CHANGE_DEFAULT_ROM_DEVICE_ADDRESS_PSEUDO_CODE */ SMPL_Init(sCB); //初始化通信系统和simpliciti的协议栈 /* green and red LEDs on solid to indicate waiting for a Join. */ if (!BSP_LED2_IS_ON()) { toggleLED(2); } if (!BSP_LED1_IS_ON()) { toggleLED(1); } /* main work loop */ while (1) { /* manage FHSS schedule if FHSS is active */ FHSS_ACTIVE( nwk_pllBackgrounder( false ) ); /* Wait for the Join semaphore to be set by the receipt of a Join frame from a * device that supports an End Device. * * An external method could be used as well. A button press could be connected * to an ISR and the ISR could set a semaphore that is checked by a function * call here, or a command shell running in support of a serial connection * could set a semaphore that is checked by a function call. */ if (sJoinSem && (sNumCurrentPeers < NUM_CONNECTIONS)) { /* listen for a new connection */ while (1) { if (SMPL_SUCCESS == SMPL_LinkListen(&sLID[sNumCurrentPeers])) { break; } /* Implement fail-to-link policy here. otherwise, listen again. */ } sNumCurrentPeers++; BSP_ENTER_CRITICAL_SECTION(intState); sJoinSem--; BSP_EXIT_CRITICAL_SECTION(intState); } /* Have we received a frame on one of the ED connections? * No critical section -- it doesn't really matter much if we miss a poll */ if (sPeerFrameSem) { uint8_t msg[MAX_APP_PAYLOAD], len, i; /* process all frames waiting */ for (i=0; i<sNumCurrentPeers; ++i) { if (SMPL_SUCCESS == SMPL_Receive(sLID[i], msg, &len)) { processMessage(sLID[i], msg, len); BSP_ENTER_CRITICAL_SECTION(intState); sPeerFrameSem--; BSP_EXIT_CRITICAL_SECTION(intState); } } } if (BSP_BUTTON1()) { SPIN_ABOUT_A_QUARTER_SECOND; /* debounce */ changeChannel(); } else { checkChangeChannel(); } BSP_ENTER_CRITICAL_SECTION(intState); if (sBlinky) { if (++sBlinky >= 0xF) { sBlinky = 1; toggleLED(1); toggleLED(2); } } BSP_EXIT_CRITICAL_SECTION(intState); }}
main函数最开始是初始化板级支持包Bsp_Init();
接着初始化协议栈SMPL_Init(sCB);
这里sCB对应的是回调函数,针对AP来说这个是必须加的,因为AP(协调器)是肯定要接收ED(节点)的数据的。而对于只上报的节点设备,sCB就可以忽略。
整个程序的核心在接收中断里,很庞大,简单解说就是通过数据帧剥离出端口,后面调用回调函数sCB,向应用层提示本帧数据是Join帧还是通用的数据帧。在main.c里面定义了两个全局变量。
static volatile uint8_t sPeerFrameSem = 0; /* 数据帧标识,每接收到一桢新数据就会通过回调加一,然后主循环查询进行数据的读取
static volatile uint8_t sJoinSem = 0; /* Join帧标识变量,ED请求加入时会通过回调加一,主循环查询后进行LINK的监听*/
static uint8_t sCB(linkID_t lid){ if (lid) { sPeerFrameSem++; sBlinky = 0; } else { sJoinSem++; } /* leave frame to be read by application. */ return 0;}
所以在mian函数里面,一直轮询sPeerFrameSem和sJoinSem两个变量。
smplStatus_t SMPL_Receive(linkID_t lid, uint8_t *msg, uint8_t *len)
读取数据帧接口函数,lid针对ED而已是唯一的,AP的话是根据ED申请LINK时按顺序分配的。*msg与*len就是接收数据的缓存与长度了
发送其实是一样的意思
smplStatus_t SMPL_Send(linkID_t lid, uint8_t *msg, uint8_t len)
从上面的代码来看,sCB函数内确实是这样做的!其实TI代码分层,程序模块化写的很好(很有借鉴意义),对于只关心应用的用户来说,不需要关心具体底层的实现方法。主函数代码可读性比较高!降低代码之间耦合性。
最后我们只需要根据变量标识去读写数据就可以了。
实际API接口比较多,下章我会细讲接收中断与协议栈本身的代码。先上传分中英文的API文档把~英文不好的小伙伴们可以下载看看http://download.csdn.net/detail/libin55/9500682
2 0
- Simpliciti协议栈移植笔记一
- simpliciTI 协议栈移植
- Simpliciti协议栈移植笔记二(组网的实现)
- SylixOS ICAN 协议移植笔记
- UIP协议栈笔记·一
- OK2440 uboot移植笔记【一】
- ARM bluez协议栈移植
- Diameter协议学习笔记一(协议介绍)
- 学习TCP协议笔记一
- CANopen协议学习笔记一
- XMPP协议学习笔记一
- upnp协议学习笔记一
- CANopen协议学习笔记一
- RTSP 协议学习笔记一
- CANopen协议学习笔记一
- Http协议学习笔记一
- XMPP协议学习笔记一
- XMPP协议学习笔记(一)
- 2016阿里巴巴测试开发实习笔试题
- 给Button添加边框
- HDU 1808(鸽巢原理)
- Android Volley完全解析(一),初识Volley的基本用法
- C#线程同步的几种方法
- Simpliciti协议栈移植笔记一
- JVM调优总结(这个总结得比较全面)
- 内存管理
- 关于EnumerateObjectsUsingBlock和for-in之间的较量
- 打印1到最大的n位数
- Java 字节流与字符流的区别
- Android API Guides---Supporting Multiple Screens
- 自己实现简单shell的小例子
- 进制转换---由任意进制转为任意进制---NOJ1592