一,概述SimpliciTI
在分析代码之前,先说一下SimpliciTI的组成,详细的在官方说明文档里面已经很清楚了,在这我简单说一下。
1.1,它提供了三个硬件对象:终端设备(End Device)、AP(Access Point)、信号范围扩展器(Range Extender)
这个在例程目录就能看出:
、
终端设备就是该网络的节点设备,访问由AP设备组成的网络,当然也可以peer 2 peer;
AP设备是组成星型网络的中心,负责转发接受信息,这个例程作为HUB连接各个ED设备,接收各个ED上传的信息;
信号范围扩展器,其实就是数据包的转发,为了扩大AP与ED的通信范围,文档中说同一网络能4个RE,具体的还没测试过;
1.2,它的软件结构为下图:
PHY层:MRFI为硬件层,控制RF芯片有的是SPI通信,有的是片内集成的SOC控制;
网络层:NWK这是组成网络的核心,具体的通信交互操作都在此完成;
应用层:这是工程师编写的应用程序,使用NWK开放出来的api接口完成通信操作及其他功能;
二,代码分析
这里我也只能大概说明一下,也是根据个人的理解,可能有些出入
以下是AP的main函数:
void main (void)
{
bspIState_t intState;
memset(sSample, 0x0, sizeof(sSample));
/*这边是关于硬件的一些基本的初始化,包括(TA定时器的初始化,这是NWK必须要有的;
*还有LED及BUTTON的设置,这是针对具体硬件IO设置的,在BSP文件夹中可以进行修改,
*SimpliciTI仅对LED和BUTTON进行了抽象处理,其他usart等功能需要自行添加)
*/
BSP_Init();
/* 这边是需要自行修改RAMAddr的地方,每个设备有一个ROMAddr和一个RAMAddr,
*ROMAddr是在configuration中对应的dat文件中进行修改的,是在编译是就确定的,
*而你也可以在这边修改RAMAddr,但是必须在 SMPL_Init()之前,因为SMPL_Init()中会加载
*Addr进行相应设置,这是Addr就不能改变了,修改RAMAddr就是使用“SMPL_Ioctl
*(IOCTL_OBJ_ADDR, IOCTL_ACT_SET, &lAddr)”,具体操作追进去看一下就明白了
*/
#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 */
/*这边是硬件层和网络层(MRFI及NWK)的初始化
*有一点需要注意,sCB是一个回调函数,当有新的ED或者已经加入的ED发送数据来时触发
*新ED加入sJoinSem ++;已加入的ED则sPeerFrameSem++
*后面有相应的处理
*/
SMPL_Init(sCB);
/* 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)
{
/* 当有新EDjion入网络时且已加入ED还未超出NUM_CONNECTIONS时执行
* 执行SMPL_LinkListen操作,对应的ED是SMPL_Link操作
*/
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);
}
/* 这边是处理已加入ED的操作
*执行SMPL_Receive,对所有ED进行轮询
*sNumCurrentPeers是以加入的ED数量
*/
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);
}
}
}
/*这边是通过按键进行变换通信Channel的操作或者自动切换channel
*起到避免干扰的作用,
*”checkChangeChannel()“中的代码:
* SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_RSSI, (void *)&dbm);
* sSample[i] = dbm;
*获取当前rssi值,且没有ED信息时,出现有三个连续的大于-70的干扰信号 就切换信道
*当dat文件中定义FREQUENCY_AGILITY之后才起作用
*/
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);
}
}
其他的ED的代码流程可以自行分析,大致流程都一样;
通信流程参考下图: