SimpliciTI底层接口
函数名 |
描述 |
使用的全局变量 |
void MRFI_SetLogicalChannel (uint8_t chan) |
设置通信频率。 设置完信道后将根据全局变量[1]的值决定是否将系统设置为接收状态。 |
1.mrfiRadioState |
void MRFI_SetRFPwr (uint8_t idx) |
设置功率因子。 设置完信道后将根据全局变量[1]的值决定是否将系统设置为接收状态。 |
1.mrfiRadioState |
uint8_t MRFI_SetRxAddrFilter (uint8_t * pAddr) |
设置接收数据帧的地址过滤。 |
|
void MRFI_EnableRxAddrFilter (void) |
使能接收数据帧地址过滤。 该操作将会使全局变量[1]被置位。 |
1.mrfiRxFilterEnabled |
void RFI_DisableRxAddrFilter (void) |
失能接收数据帧地址过滤。 该操作将会使全局变量[1]被清零。 |
1.mrfiRxFilterEnabled |
void MRFI_Init(void) |
初始化。主要指初始化底层接口专用的接收数据缓冲区[1];初始化通讯过程需要使用到的相关IO;根据配置初始化通信频率等特征值;初始化需要向上层提供的随机数种子[2];初始化系统状态[3]为IDLE;获取系统通信速率并据此初始化[4]。 |
1.mrfiIncomingPacket 2.mrfiRndSeed 3.MrfiRadioState 4.sReplyDelayScalar |
uint8_t MRFI_Transmit (mrfiPacket_t * pPacket, uint8_t txType) |
根据输入参数使用相应模式发送数据。 数据发送完毕后将根据[1]设置通信状态。 |
1.mrfiRadioState |
void MRFI_Receive (mrfiPacket_t * pPacket) |
将底层独有的接收数据缓冲区内的数据拷贝到pPacket指向的缓冲区中。 |
|
void MRFI_WakeUp(void) |
如果系统处于RADIO_STATE_OFF状态则将其唤醒并将[1]设置为IDLE状态。 |
1.mrfiRadioState |
int8_t MRFI_Rssi(void) |
读取通信通道的RSSI值,转换后返回。 |
|
uint8_t MRFI_RandomByte (void) |
对随机数种子[1]进行一次迭代更新产生新产生一个随机数。 |
1.mrfiRndSeed |
void MRFI_DelayMs (uint16_t milliseconds) |
软件延时函数。 |
|
void MRFI_ReplyDelay(void) |
数据发送后等待接收所调用的延时函数。该函数将启动[1]以使中断函数可以操作[2]。当[2]被置位证明数据接收正常,提前退出。 |
1.sReplyDelayContext 2.sKillSem |
void MRFI_PostKillSem(void) |
根据[1]赋予的权限对[2]操作以终止接收数据等待。 |
1.sReplyDelayContext 2.sKillSem |
uint8_t MRFI_GetRadioState (void) |
返回当前的系统通讯状态。 读取[1]并返回。 |
1.mrfiRadioState |
static void Mrfi_SyncPinRxIsr (void) |
该函数由中断触发并调用,模拟物理层对数据进行接收。主要完成的工作是对帧完整性进行验证;对数据帧的校验和进行验证;根据自身地址和功能开关对地址进行过滤(地址过滤操作将允许广播地址通过);转换帧信号标识(RSSI,LQI转换为DB位计量单位的量)。 如果接收到数据,该数据将会填充到[1]内。 |
1.mrfiIncomingPacket |
SimpliciTI应用层接口
1.1 smplStatus_t SMPL__Init(uint8_t (*callback)(linkID_t))
功能描述:该函数主要初始化通信系统和simpliciti的协议栈。完成的工作包括有:
A.直接调用驱动层函数MRFI_Init完成通讯硬件设备初始化,随机数种子初始化,物理层数据接收缓冲区初始化等工作。
B.调用网络层函数nwk_nwkInit注册用户接收数据处理函数并初始化连接表数据结构,初始化最大连接数,初始化下一个连接将使用到的接收和发送端口号,初始化下一个连接号;将中心节点地址设置为0,并从ROM中获取自身地址并搬移到RAM中;初始化设备类型,数据接收和发送的方式,初始化TRACE ID,将数据接收处理函数注册给nwk_frame.c 文件(而nwk_nwkInit则继续调用nwk_frameInit初始化本设备帧的固有数据结构并向下注册用户接收数据处理函数,nwk_frameInit注册用户数据处理函数的过程是根据预编译宏RX_POLLS来完成的,这个宏设置了用户程序对接收数据的处理方式。当其被置一,则表明用户程序将采用查询的方式来处理数据,底层用户数据处理函数注册被放弃。这种情况下接收到用户程序需要处理的数据时,该数据被保存在网络层的接收数据队列sInFrameQ中,等待应用程序来查询获取。反之,用户数据处理程序被注册给底层函数供中断调用处理。获取自身地址,并初始化nwk_frame.c文件的TID );初始化应用层接收和发送数据处理队列sInframeQ和sOutFrameQ,这两个数据队列在逻辑层次上刚刚高于物理层的数据接收缓冲区;同时nwk_nwkInit还将初始化网络层内置的一些应用的TID以及相应的默认信标;初始化广播用到的连接号和端口号。
C.如果不是end device则使通信系统处于接收状态
D.如果是end device 则开启地址过滤
E.调用nwk_join启动一次连接AP的过程。该过程通过广播地址使用JOIN端口发起一次向AP的加入请求。加入成功将获得AP的地址和新的连接信标。
1.2 输入参数:
uint8_t (*callback)(linkID_t)--用户数据处理函数的函数指针,用户数据处理函数只有在end device上才能生效
1.3 返回值:
SMPL_SUCCESS--初始化成功
SMPL_NO_JOIN--因为没有收到AP返回,加入AP失败
SMPL_NO_CHANNEL--频率信道扫描失败,这种情况只有跳频条件编译功能开关打开才会发生。
2.1 smplStatus_t SMPL_Link(linkID_t *lid)
功能描述:用广播地址发起一个连接请求,如果收到回复则成功建立起一个连接,同时会生成一个连接号供应用程序使用该连接。连接建立过程受到等待时间的限制,等待超时将返回连接失败。等待时间是在初始化系统时根据通信速率,自动计算获取的。该函数可以被重复多次条用以获得多个连接。这些连接可以基于同一个设备也可以建立在不同设备之间。
执行过程:首先从连接表中选取一个空连接(选取空链接的时候需要更新连接表的下一个连接号)
SimpliciTI接收数据处理机制
Simpliciti接收数据的最小单位为数据帧,因为其外接的射频收发芯片是按帧为单位进行数据收发的。在适当的配置之下,射频芯片接收到数据帧后将发生一个中断告之MCU,MCU对响应这个中断并处理接收数据。Simpliciti中断调用并处理这个数据帧结构非常复杂,异常庞大,它几乎将除了用户应用程序外的所有simpliciti内部协议的接收处理都放在了中断函数中。
Mrfi_SyncPinRxIsr:该函数由中断触发并调用,模拟物理层对数据进行接收。主要完成的工作是对帧完整性进行验证;对数据帧的校验和进行验证;根据自身地址和功能开关对地址进行过滤(地址过滤操作将允许广播地址通过);转换帧信号标识(RSSI,LQI转换为DB位计量单位的量)。
该函数涉及到的一个全局变量:mrfiIncomingPacket。这个变量专门用于对存放接收到的单帧数据。
nwk_QfindSlot:寻找一个空余数据帧空隙,将接收到的数据放入该数据帧。如果所有数据帧都满了,那么将最老的那个数据帧去掉。
该过程涉及到的全局变量是:sInFrameQ[],这个变量时由结构体frameInfo_t定义的。
MRFI_Receive:该函数实现将接收到的数据填充到刚刚找到的空隙中。这里有一个技巧,原代码设计时使用了结构体变量之间,直接赋值!
dispatchFrame:检测信息类型,并更具信息类型进行投递到相应的应用层处理函数。主要完成工作是:检测信息是否是自身的回声(这种情况一般来至extender的转发);根据获取到的端口判断是否调用内部网络层固有处理函数;根据网络层内部处理函数结果判断是否转发;根据端口判断是否存在相应的服务程序;
SimpliciTI的缺点
1.能够构建的网络相对较简单,网络容量小
2.不具备路由管理功能,每一次通讯都依靠RE进行侦听转发,比较浪费时间。这应该算是simpliciti最大的一个缺点了。
3.转发跳数限制在4跳,极大地限制了通信距离
4.每一个网络里边最大允许出现四个RE,这虽然可以减少数据发送过程带来的冲突,但是也使网络规模受到限制,传输距离受到限制。
5.设备分了三种类型,为安装带来麻烦
SimpliciTI的启迪
1.编写代码的时候每一个独立文件所独有的变量尽量使用static进行修饰,这样在设计功能类似的代码可以取一致的变量名。
2.在外部线程操作中断内可改变的变量时需要关闭中断。
3.中断内部可改变的变量需要用volatile定义。
4.学会使用assert功能
5.每一个应用线程独立的维护自己的TID
6.学会使用函数指针数组来完成对函数的调用
7.每一个文件内部的变量都是静态的,属于本文件的,这些变量的操作均借助于该文件内专用的操作函数来完成。(它的优点目前我还未能领悟)
8.学会使用memcpy,memset以及memcmp函数,将极大的简化代码
9.启用工程对项目进行管理的时候,通过不同的工程配置文件达到一个工程管理多个平台的目的。具体细节是,不同工程配置文件配置不同的包含路径,在工程的驱动层c文件中通过包含的方式包含底层驱动,由于不同配置不同包含路径导致配置变了以后自动包含了不同的驱动,从而实现一个工程管理多个平台。
10.用枚举定义所有函数的返回类型,并且包括所有可能出现的异常。