查看: 7022|回复: 2

SimpliciTI入门——从零开始实现SimpliciTI无线通信(网友懒兔...

[复制链接]
  • TA的每日心情
    奋斗
    2020-9-28 10:10
  • 签到天数: 1018 天

    连续签到: 1 天

    [LV.10]以坛为家III

    发表于 2012-8-24 15:22:36 | 显示全部楼层 |阅读模式
    分享到:
    本帖最后由 xinxincaijq 于 2012-8-24 15:39 编辑

    (网友懒兔子作品)

    这段时间折腾了一下SimpliciTI,有些个人理解,和大家讨论一下,希望有这方面经验的人不吝赐教,一个人闷头搞确实听没意思的。同时也在考虑从现有的MSP430向更强的M3平台移植(比如Stellaris),有兴趣的朋友可以一起讨论一下呀。
    一、搭建SimpliciTI环境
    一个MCU和一个RF模块,这就是搭建SimpliciTI环境的硬件需求(TI的SoC也是在芯片内部集成了RF模块)。当然了,这个协议栈是有版权的,当你用作商业用途时需要向TI缴纳一定的费用,而用于学习时,TI也会要求你至少用他的RF芯片。
    这里使用的是TI的eZ430-RF2500套件,板载MSP430F2274和CC2500射频芯片,使用芯片天线,传输距离并不远,如果离开一段距离或者有遮蔽物就会出现丢包,这个我们会在后面进行测试。电路图如下(点击看大图),2274和CC2500之间通过SPI和两个IO(中断方式)通信,一般网上卖的模块也会留出这些接口。如果对RF PCB设计没有信心,淘宝上有10块钱的CC2500模块,虽然是白菜价,但是PCB天线一般都是低于0dB的,通信距离可想而知。
    500_400-1324130994_5fac8f05.jpg
    TI官方的开发套件,$49
    500_400-1324131019_1dc47fc5.jpg

    淘宝上可以找到的CC2500模块,¥10

    500_400-1324130873_d693dc5b.jpg
    原理图
    同时,此平台也对外开放一个USB调试接口(包括UART和SBW)。
    500_400-1324131247_b1d2e989.jpg
    接口定义
    二、SimpliciTI协议栈结构与移植
    SimpliciTI协议的一大特点就是简单,所以在极大简化开发过程的同时也带了很多限制,比如缺少完备的路由协议,最多4个RE(使通信距离受限),即使低功耗也是在ED关闭RF接收功能的前提下实现的(限制双向通信)。不过即使如此,也丝毫不影响它为无线网络通信带来的便利,你可以根据应用需求在ZigBee和SimpliciTI之间取舍。
    想要使用它你需要下载协议栈代码,下面是及针对RF2500套件的演示代码:


    通用协议栈SimpliciTI-IAR1.1.1可以在TI官网上下载:
    安装后在安装目录下可以找到代码和说明文档,建议看一下Developers Notes、Sample Application User's Guide和API文档,如果需要涉及加密、调频等应用,这里还有相应的Application Note。
    SimpliciTI本身的软件分为3层,即BSP、MRFI和NWK:
    500_400-1324131476_58109cb6.jpg
    BSP是一个轻量级板级支持包,包含了MCU、SPI(这个必须有)、LED和Button,简单吧,TI的意思是尽可能的减少协议栈本身的硬件内容,因此如果想要用串口或者ADC,就要自行解决,我们暂且将这些额外添加的硬件控制代码称为Driver吧。
    MRFI是最小射频接口,主要是与BSP中的SPI对接以及射频芯片的控制代码。如果要移植协议栈,就需要更改与MCU定义、中断、IO和SPI相关的代码,不过只要你使用MSP430或CC系列SoC作为MCU可以直接在代码中找到相近的Board从而减少工作量。当然啦,如果你是高手或者兼有求知和耐心的美德,甚至可以自己写底层而只保留NWK和APP层,不过这不是我们现在的目的,至少目前不是。
    NWK网络层负责数据收发队列,同时包含很多网络层应用,注意区分NWK Applications与用户的应用代码(Customer Applications)的区别,这些网络层应用是以端口作为标识的(如Ping是0x01,Link是0x02),相应的函数以nwk_作为前缀,而我们通常将用户代码称作应用层。SimpliciTI的端口(Port)与TCP/IP的端口神似(similar in spirit ^_^),每个端口对应一种应用,用户也可以定义自己的网络层应用。网络层为用户提供了API函数,以SMPL_为前缀,如SMPL_Link等,我们的工作就是利用这些API实现组网及无线通信。
    三、建立第一个简单双向通信程序
    1)配置工程
    打开演示代码eZ430-RF2500 WirelessSensorMonitor中的Sensor_Demo_AP_as_Data_Hub工程,如果你使用的是eZ430-RF2500套件,直接修改其中的Application文件就好了,如果不是TI的官方套件,可以选择一个硬件组成相近的工程,修改MCU定义和按键、LED等配置,这里不再深究,以后可以专门开贴讨论。
    500_400-1324131667_a833f708.jpg
    【Tips】在下载程序时可能出现这个错误,具体描述为:
    Fatal error: The Object file contains features not suported by the driver.   Session aborted!
    Failed to load debugee: …
    500_400-1324131685_848264b1.jpg
    这是因为在新版本的IAR中同时使用了选项配置和命令行,Debugger的版本较旧不识别,只需要取消命令行即可。
    500_400-1324131703_3cd59863.jpg
    打开工程后可以看到两种器件,AP(Access Point)和ED(End Device)。AP是组网的关键,负责网络的建立和维护,同时负责对外通信,有点类似于ZigBee中的协调器。网络中最多只能有一个AP,在某些模式下(如P2P)可以不需要AP,但是这样的网络需要固定参数而缺少灵活性。ED是终端设备,在TI的演示中负责入网后通过片上温度传感器采集自身的温度,并发送给AP,由AP将接收到的数据转换成字符串后通过串给上位机。
    在左侧的WorkSpace栏选择AP或者ED进行选择编译。
    500_400-1324131729_6121812b.jpg
    和网络相关的设置可以在几个配置文件中修改,其中smpl_config_AP.dat和smpl_config_ED.dat文件定义了设备类型、最大连接数、发送和接收帧队列长度等内容,smpl_nwk_config.dat文件则定义了基本的网络参数如网络和应用层负载长度、最大跳数等,这些配置可以在不同的应用中灵活选择,这里我们采用默认配置。
    2AP节点
    首先,通过BSP_Init函数初始化BSP,然后初始化需要的外围设备如串口、定时器、AD等,这里的串口函数并不包含在SimpliciTI中,而是以virtual_com_cmds.c文件的形式添加到工程中,也可以像我那样写自己的串口函数(参见我的SED430-RF2500一贴),甚至加入printf和scanf。
    在设备初始化完成后,需要初始化SimpliciTI网络,AP中对应的函数为:
    SMPL_Init(sCB);
    这里的sCB是一个回调函数,本例中用来在接收到帧时区分是入网还是数据,并分别处理,它会在CC2500 RX接收中断后调用。想要研究协议结构的童鞋可以一路Go to definition找到函数调用的地方,现在我们只需定义该函数而无须理会调用机制。
    回调函数的原型如下,当lid为0时,表示有设备入网,此时sJoinSem++,在主函数的sJoinSem子过程中进行处理,建立连接并为其分配LinkID。如果lid不为零则表示该设备已经入网并分配了LinkID,这个数据帧被作为通信数据在主函数的sPeerFrameSem子过程中通过SMPL_Recieve函数接收。
    static uint8_t sCB(linkID_t lid)
    {
      if (lid)
      {
        sPeerFrameSem ;
      }
      else
      {
        sJoinSem ;
      }
      return 0;
    }
    至此整个初始化工作完成,然后AP进入while(1)循环,这个循环中包含几个子过程,这里我们只需要sJoinSem和sPeerFrameSem两个过程。
    sJoinSem过程内容如下:
        if (sJoinSem && (sNumCurrentPeers < NUM_CONNECTIONS))
        {
          while (1)
          {
            if (SMPL_SUCCESS == SMPL_LinkListen(&sLID[sNumCurrentPeers]))
            {
              break;
            }
          }
          sNumCurrentPeers ;
          BSP_ENTER_CRITICAL_SECTION(intState);
          sJoinSem--;
          BSP_EXIT_CRITICAL_SECTION(intState);
        }
    一旦进入这个过程(有设备入网),软件将持续通过SMPL_LinkListen函数监听ED发起的链接,在链接建立后会为该链接分配一个LinkID,以后数据收发就考这个LinkID作为标识。该函数的实参就是一个用来存放LinkID的数组。sNumCurrentPeers是当前连接设备计数器,这里要注意的是在处理完入网帧后,需要减少sJoinSem的值,而sJoinSem是一个公共变量,同时受回调函数的控制。sCB是一个在中断中执行的函数,所以要通过BSP_ENTER_CRITICAL_SECTION进行临界保护,参数intState其实是一个unsigned short型变量,在主函数中定义,用于保存相关寄存器,在退出临界状态时恢复。
    对接收到的通信数据的处理则要靠sPeerFrameSem:
        if (sPeerFrameSem)
        {
          uint8_t     msg[MAX_APP_PAYLOAD], len, i;
          for (i=0; i
          {
            if (SMPL_SUCCESS == SMPL_Receive(sLID, msg, &len))
            {
              USCI0_SendDataString(msg, len);
              BSP_ENTER_CRITICAL_SECTION(intState);
              sPeerFrameSem--;
              BSP_EXIT_CRITICAL_SECTION(intState);
            }
          }
        }
    SMPL_Receive函数读取接收到的数据帧,将APP_PAYLOAD分离出来保存在msg数组中,len作为实参保存msg的长度,最后通过USCI0_SendDataString发送给上位机。
    void USCI0_SendDataString(uint8_t *msg, uint8_t len)
    {
      int i;
      for(i=0;i
        USCI0_PutChar(msg);
    }
    其中USCI0_PutChar这个函数需要自己写,如果是带有USCI模块的430可以使用我的SED430-RF2500中的UART.c,若是USART模块的430则参见SED430中的串口文件。传送门上面已经给出。
    那么如果要给ED发数据怎么办呢,依然只要一个函数即可:
    定义一个msg数组,写入要发送的数据,然后:
    SMPL_Send(lid, msg, len);
    lid是要目的设备的LinkID,len是要发送数据的长度,这里len和接收函数不同是形参,注意不要超过最大负载长度哦。
    这就是AP的部分,可以完成入网,数据接收发送功能,另外还有一些跳频和信号强度检测的功能,可以自己研究一下。
    3ED节点
    修改代码之前,需要给ED设置一个32位地址,这个地址相当于TCP/IP中的IP地址,由于SimpliciTI没有MAC层,所以设备就要靠这个地址识别数据包是不是发给自己的。网络中每一个设备的地址都应当是唯一的,否则会发生冲突。可以在对应设备的.dat配置文件中修改这条语句:
    -DTHIS_DEVICE_ADDRESS="{0x7A, 0x56, 0x34, 0x12}"
    若不想一个一个设置,可以参考范例共给出的产生随机地址的方法,通过ADC或者VLO采集一个真随机数(虽然是真随机数不过不知道是什么分布的),换算成地址并写入Flash。
    ED和AP的设备初始化过程一样,初始化完成后,开始检测是否存在网络并,直到检测到AP建立的网络并入网。__bis_SR_register函数的作用是休眠并等待TA中断,如果不想采用这种方式,也可以通过__delay_cycles函数或自己编写Delay函数实现延时。
      //搜寻并加入网络
      while (SMPL_SUCCESS != SMPL_Init(sCB))
      {
        BSP_TOGGLE_LED1();  //LED闪烁
        BSP_TOGGLE_LED2();
        __bis_SR_register(LPM0_bits GIE);
      }
    如果ED不需要接收数据,SMPL_Init时可以不要回调函数:SMPL_Init(0)。如果需要接收数据,则应当开启RX:
    SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_RXON, 0);
    ED的回调函数中只处理数据帧而没有入网帧,其形式如下:
    static uint8_t sCB(linkID_t lid)
    {
      if (lid)
      {
        sPeerFrameSem ;
      }
      return 0;
    }
    ED在加入网络后还不能直接和AP通信,首先需要建立一个连接(Link):
      //向AP发起Link
      BSP_TOGGLE_LED1();
      while (SMPL_SUCCESS != SMPL_Link(&LID_AP))
      {
        BSP_TOGGLE_LED1();
        BSP_TOGGLE_LED2();
        __bis_SR_register(LPM0_bits GIE); //替换成你自己的延时函数
      }
    连接建立好以后,AP的LinkID被保存在LID_AP变量中,因为我们只需要和一个固定的AP通信,所以不需要数组来保存多个LinkID。
    至此,ED已经可以和AP自由的交换数据了,在sPeerFrameSem子过程中,我们将接收到的数据发还给AP并翻转一个LED。
        //接收到RF数据
        if(sPeerFrameSem)
        {
          uint8_t msg[MAX_APP_PAYLOAD], len;
          if (SMPL_SUCCESS == SMPL_Receive(LID_AP, msg, &len))
          {
            SMPL_Send(LID_AP, msg, len); //发回接收到的数据
            BSP_TOGGLE_LED2(); //翻转LED状态
            BSP_ENTER_CRITICAL_SECTION(intState);
            sPeerFrameSem--;
            BSP_EXIT_CRITICAL_SECTION(intState);
          }
        }
    搞定,可以编译运行了。
    设置Show build messages显示全部消息,编译……
    500_400-1324131753_4442f945.jpg

    500_400-1324131782_aa45d5b4.jpg
    可以看到软件占用资源情况,想要运行这个协议栈,还要跑一些自己的程序,至少要有10KB的Flash和1KB的RAM,不过比起ZigBee那样的重量级协议,已经非常节省了。
    500_400-1324131801_73ab8002.jpg

    四、运行结果
    这是本例的工程文件(IAR5.30),分别将AP和ED的程序下载到模块中。
    RF2500_Example_01.rar (960 KB, 下载次数: 38)
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2017-7-21 12:58
  • 签到天数: 907 天

    连续签到: 2 天

    [LV.10]以坛为家III

    发表于 2013-5-17 10:09:25 | 显示全部楼层
    写的不错!!!!!!!!!!!!!!!!!!
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2013-5-25 05:24:34 | 显示全部楼层
    哪一版的SimplicTI配哪一版的IAR好像有讲究。特别在用TI的Example Code时,佩错了就出错。有谁比较收悉版本配置的?
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条



    手机版|小黑屋|与非网

    GMT+8, 2024-11-24 00:41 , Processed in 0.132496 second(s), 19 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.