车干的ZigBee学习笔记九—设备间的第一次对话

一、功能要求

1:协调器组建PAN网络
2:协调器组网成功后会周期性广播“I am coordinator device ! ”(周期为5S)
3: 终端设备节点加入该PAN网络,加入网络成功后周期性广播字符串“I am endpoint device ! ”(周期为 5S)

二、实现过程(下面的多个代码块代表不同的.c文件,用于对照自己的协议栈)

首先需要在电脑C盘,找到TI公司的文件夹,C:\Texas Instruments\ZStack-CC2530-2.3.0-1.4.0\Projects\zstack\Samples,将samples中的samples APP进行复制,进入samples文件夹,打开.eww文件。

**第一步:**因为我们用到了串口和字符串,所以我们首先要加入两个头文件 #include “mt_uart.h” //串口 #include “string.h” //字符串

**第二步:**加入头文件以后,我们需要做的就是设置我们的串口,既然要设置我们的串口,那么我们必然就要调用我们的串口初始化函数MT_UartInit(); ,此函数定义于MT层的MT_UART.c文件

**第三步:**调用完我们的串口初始化函数,自然要进入此函数设置我们的波特率,以及确保流控为关闭状态。

**第四步:**串口初始化成功之后,我们在这里通过串口打印一句话,
串口的打印接口 extern uint16 HalUARTWrite ( uint8 port, uint8 *pBuffer, uint16 length ); 是在HAL层的hal_uart.h头文件内
uint8 port指的是串口号,uint8 *pBuffer指实际要发送的字符串,uint16 length指要发送字符串的长度

第五步:这里我们先不做改动。了解一下void SampleApp_Init( uint8 task_id ) 这个函数中的几个变量
SampleApp_TaskID = task_id; //任务优先级
SampleApp_NwkState = DEV_INIT; //当前设备在无线网络中的网络状态 DEV_INIT;为宏定义,初始状态
SampleApp_TransID = 0; //发送数据包的一个序列号,现在初始化为0,以后ZigBee每发送一个数据出去,这个序列号就会自动加一,可以根据这个序列号以及接收方真正接收到的数据的多少,计算丢包率

**第六步:**继续往下,到了我们对地址的设置,我们设置为广播通信,地址为0XFFFF
SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast; //地址模式,此处为Broadcast,设置为广播模式
SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_Periodic_DstAddr.addr.shortAddr = 0xFFFF; //设置广播模式的地址 0XFFFF

**第七步:**设置完串口以及广播相关的东西后,那么我们就到了事件处理函数uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events ) 它们在这里看一下它的具体运作过程:

	     首先呢,他是先通过 if ( events & SYS_EVENT_MSG )这条语句判断是否真的产生了SYS_EVENT_MSG这一事件。
	 		这个事件是一个系统消息事件,同时又是一个强制事件。
		 意思就是只要协议栈运行起来了,那么这一个事件就会被触发,所以会执行这个事件处理函数。
		 一般情况一个事件产生的同时,他会额外的附加产生一些事件和一些数据。
		 协议栈把这些附加的东西打包成一个消息结构体,并把这些消息结构体依次放到消息队列里去

		然后我们如何从消息队列里面去提取当前任务的消息结构体呢,用的就是 
		MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );   中的    osal_msg_receive函数

		再下面是常用的三个额外事件,具体内容见下面的sampleAPP.c代码块
		第一个,是否有按键按下
		第二个,是否有新的无线消息到达了
		第三个,是否当前设备的网络状态改变了
		在第三个事件这里,不同网络状态的宏定义需要了解一下
		if ( (SampleApp_NwkState == DEV_ZB_COORD)//DEV_ZB_COORD代表协调器
		          || (SampleApp_NwkState == DEV_ROUTER)   //DEV_ROUTER代表路由器
  	 	         || (SampleApp_NwkState == DEV_END_DEVICE) )//DEV_END_DEVICE代表终端
	还需要注意的一点是,在第三个额外事件中,调用了一个定时器函数
	osal_start_timerEx( SampleApp_TaskID,
                          SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
                          SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );
 隔一段时间后触发一个SAMPLEAPP_SEND_PERIODIC_MSG_EVT事件,并在后面对这个事件进行了一个判断,并再次调用此函数,			       					配合发送消息的函数,构成了周期发送消息的效果 。

**第八步:**那么具体是怎么发送消息,请看void SampleApp_SendPeriodicMessage( void ),具体的函数说明,在sampleAPP.c代码块中做了注解

**第九步:**看完怎么发送消息,接下来必然是到了接收消息的部分,请看发送函数上面的
void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt ) 接收函数
从整体的流程来讲,接收到了消息,最先进入的应该是事件处理函数,并且触发额外事件二:接受到新的无线消息,然后由额外事件二中的接收函数的函数接口,进入接收函数MessageMSGCB( afIncomingMSGPacket_t *pkt )

**第十步:**进入接收函数以后,首先对命令号进行一个判断,然后根据命令号进行相应的处理。确认命令号之后,我们首先需要调用串口打印函数,打印一下消息。那么具体哪个是真正要的消息呢?我们进入结构体 afIncomingMSGPacket_t *pkt 中查看
*进入之后我们可以看到许多变量,而我们真正需要的只有 afMSGCommandFormat_t cmd; / Application Data */ *这一个变量,我们再进入afMSGCommandFormat这个结构体,看看这个变量都具体包含哪些东西

typedef struct
{
  byte   TransSeqNumber;   //传送序列号
  uint16 DataLength;               // 数据长度
  byte  *Data;     //真正的数据
} afMSGCommandFormat_t;

**第十一步:**编译我们的工程,将不需要的功能模块前加x去掉
在这里插入图片描述
然后点击编译,下入硬件,就OK了

代码块一:sampleAPP.c

//sampleAPP.c
#include "OSAL.h"
#include "ZGlobals.h"
#include "AF.h"
#include "aps_groups.h"
#include "ZDApp.h"

#include "SampleApp.h"
#include "SampleAppHw.h"

#include "OnBoard.h"

/* HAL */
#include "hal_lcd.h"
#include "hal_led.h"
#include "hal_key.h"

#include "mt_uart.h"  //串口
#include "string.h" //字符串

// This list should be filled with Application specific Cluster IDs.
const cId_t SampleApp_ClusterList[SAMPLEAPP_MAX_CLUSTERS] =
{
  SAMPLEAPP_PERIODIC_CLUSTERID,
  SAMPLEAPP_FLASH_CLUSTERID
};

const SimpleDescriptionFormat_t SampleApp_SimpleDesc =
{
  SAMPLEAPP_ENDPOINT,              //  int Endpoint;
  SAMPLEAPP_PROFID,                //  uint16 AppProfId[2];
  SAMPLEAPP_DEVICEID,              //  uint16 AppDeviceId[2];
  SAMPLEAPP_DEVICE_VERSION,        //  int   AppDevVer:4;
  SAMPLEAPP_FLAGS,                 //  int   AppFlags:4;
  SAMPLEAPP_MAX_CLUSTERS,          //  uint8  AppNumInClusters;
  (cId_t *)SampleApp_ClusterList,  //  uint8 *pAppInClusterList;
  SAMPLEAPP_MAX_CLUSTERS,          //  uint8  AppNumInClusters;
  (cId_t *)SampleApp_ClusterList   //  uint8 *pAppInClusterList;
};


endPointDesc_t SampleApp_epDesc;


uint8 SampleApp_TaskID;   // Task ID for internal task/event processing
                          // This variable will be received when
                          // SampleApp_Init() is called.
devStates_t SampleApp_NwkState;

uint8 SampleApp_TransID;  // This is the unique message ID (counter)

afAddrType_t SampleApp_Periodic_DstAddr;
afAddrType_t SampleApp_Flash_DstAddr;

aps_Group_t SampleApp_Group;

uint8 SampleAppPeriodicCounter = 0;
uint8 SampleAppFlashCounter = 0;

/*********************************************************************
 * LOCAL FUNCTIONS
 */
void SampleApp_HandleKeys( uint8 shift, uint8 keys );
void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pckt );
void SampleApp_SendPeriodicMessage( void );
void SampleApp_SendFlashMessage( uint16 flashTime );


 */
void SampleApp_Init( uint8 task_id )
{
  SampleApp_TaskID = task_id;    //任务优先级
  SampleApp_NwkState = DEV_INIT;   //当前设备在无线网络中的网络状态   DEV_INIT;为宏定义,初始状态
  SampleApp_TransID = 0;		//发送数据包的一个序列号,现在初始化为0,以后ZigBee每发送一个数据出去,这个序列号就会自动加一,可以根据这个序列号以及接收方真正接收到的数据的多少,计算丢包率
  
  MT_UartInit ();  //调用串口初始化函数,进行波特率设置,并关闭流控
  HalUARTWrite ( 0, "uart0 is ok\n",strlen("uart0 is ok\n"));  //在这里我们 设置串口号为0,发送的字符串为uart0 is ok,然后计算字符串长度
 
 #if defined ( BUILD_ALL_DEVICES )
  if ( readCoordinatorJumper() )
    zgDeviceLogicalType = ZG_DEVICETYPE_COORDINATOR;
  else
    zgDeviceLogicalType = ZG_DEVICETYPE_ROUTER;
#endif // BUILD_ALL_DEVICES

#if defined ( HOLD_AUTO_START )
  ZDOInitDevice(0);
#endif
 //此处用于设置模式,以及模式地址
  SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast;  //地址模式,此处为Broadcast,设置为广播模式
  SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
  SampleApp_Periodic_DstAddr.addr.shortAddr = 0xFFFF;  //设置广播模式的地址 0XFFFF 
  
  //接下来是对设备的端口描述符进行成员的复制,一般情况下也不需要做改动
  SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT;
  SampleApp_epDesc.task_id = &SampleApp_TaskID;
  SampleApp_epDesc.simpleDesc
            = (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc;
  SampleApp_epDesc.latencyReq = noLatencyReqs;
  
  

  // 向AF注册端点描述
  afRegister( &SampleApp_epDesc );

  // Register for all key events - This app will handle all key events
  RegisterForKeys( SampleApp_TaskID );
  

#if defined ( LCD_SUPPORTED )
  HalLcdWriteString( "SampleApp", HAL_LCD_LINE_1 );
#endif
}

//下面是当我们的协议栈运行起来之后一定会调用的一个事件处理函数,我们看一下他的具体运行过程

uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
{
  afIncomingMSGPacket_t *MSGpkt;
  (void)task_id;  
/*
  首先呢,他是先判断是否真的产生了SYS_EVENT_MSG这一事件。
  这个事件是一个系统消息事件,同时又是一个强制事件。
  意思就是只要协议栈运行起来了,那么这一个事件就会被触发,所以会执行这个事件处理函数。
  一般情况一个事件产生的同时,他会额外的附加产生一些事件和一些数据。
  协议栈把这些附加的东西打包成一个消息结构体,并把这些消息结构体依次放到消息队列里去
  
  */
  if ( events & SYS_EVENT_MSG )
  {
    //那么如何从消息队列里面去提取当前任务的消息结构体呢,用的就是osal_msg_receive函数
    MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
    while ( MSGpkt )
    {
      //常用的一些产生的额外事件有以下三个
      //然后再对提取的消息结构体进行拆包,可以看到 switch ( MSGpkt->hdr.event )他产生了一些额外的事件
      switch ( MSGpkt->hdr.event )
      {
        // 第一个,是否有按键按下
        case KEY_CHANGE:
          SampleApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );
          break;

        // 第二个,是否有新的无线消息到达了
        case AF_INCOMING_MSG_CMD:
          SampleApp_MessageMSGCB( MSGpkt );
          break;

        // 第三个,是否当前设备的网络状态改变了
        case ZDO_STATE_CHANGE:
          SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
          //如果协调器创建网络成功的时候,他的网络状态会由初始值变为协调器状态
          //所以说,如果我们使用协调器创建网络的时候势必会触发此事件,那么网络状态改变后会调用定时器osal_start_timerEx
          if ( (SampleApp_NwkState == DEV_ZB_COORD)//DEV_ZB_COORD代表协调器
              || (SampleApp_NwkState == DEV_ROUTER)   //DEV_ROUTER代表路由器
              || (SampleApp_NwkState == DEV_END_DEVICE) )//DEV_END_DEVICE代表终端
          {
            // Start sending the periodic message in a regular interval.
            //隔一段时间之后会触发一个事件,那么在下一次事件轮询之前,触发此事件后,协议栈将进行什么操作呢?
            //下面看if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )这个函数
            osal_start_timerEx( SampleApp_TaskID,
                              SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
                              SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );//这个参数决定隔多长时间
          }
          else
          {
            // Device is no longer in the network
          }
          break;

        default:
          break;
      }

      // Release the memory
      osal_msg_deallocate( (uint8 *)MSGpkt );

      // Next - if one is available
      MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
    }

    // return unprocessed events
    return (events ^ SYS_EVENT_MSG);
  }

  // Send a message out - This event is generated by a timer
  //  (setup in SampleApp_Init()).
  if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )
  {
    //发送消息
    SampleApp_SendPeriodicMessage();  

    // 此处又调用定时器触发事件,
    //在下次轮询时又产生SAMPLEAPP_SEND_PERIODIC_MSG_EVT事件
    //再次循环回来,5S一次,构成周期性发送消息,
    osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
        (SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) );

    // return unprocessed events
    return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT);
  }

  // Discard unknown events
  return 0;
}

void SampleApp_HandleKeys( uint8 shift, uint8 keys )
{
  (void)shift;  // Intentionally unreferenced parameter
  
  if ( keys & HAL_KEY_SW_1 )
  {
    /* This key sends the Flash Command is sent to Group 1.
     * This device will not receive the Flash Command from this
     * device (even if it belongs to group 1).
     */
    SampleApp_SendFlashMessage( SAMPLEAPP_FLASH_DURATION );
  }

  if ( keys & HAL_KEY_SW_2 )
  {
    /* The Flashr Command is sent to Group 1.
     * This key toggles this device in and out of group 1.
     * If this device doesn't belong to group 1, this application
     * will not receive the Flash command sent to group 1.
     */
    aps_Group_t *grp;
    grp = aps_FindGroup( SAMPLEAPP_ENDPOINT, SAMPLEAPP_FLASH_GROUP );
    if ( grp )
    {
      // Remove from the group
      aps_RemoveGroup( SAMPLEAPP_ENDPOINT, SAMPLEAPP_FLASH_GROUP );
    }
    else
    {
      // Add to the flash group
      aps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group );
    }
  }
}

void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
  uint16 flashTime;

  switch ( pkt->clusterId )//首先对发送的命令号进行判断
  {
    case SAMPLEAPP_PERIODIC_CLUSTERID: //发送的也是这个命令号
      //确认后,打印消息,同上面的串口打印函数
      HalUARTWrite ( 0, (pkt->cmd).Data,(pkt->cmd). DataLength);  
      //进入上面的afIncomingMSGPacket_t *pkt结构体,找一下哪一个真正存放着数据
      break;

    case SAMPLEAPP_FLASH_CLUSTERID:
      flashTime = BUILD_UINT16(pkt->cmd.Data[1], pkt->cmd.Data[2] );
      HalLedBlink( HAL_LED_4, 4, 50, (flashTime / 4) );
      break;
  }
}

void SampleApp_SendPeriodicMessage( void )
{
  uint *buff=NULL;  //首先定义一个缓存区
  //通过全局变量来判断是协调器还是终端
  /*协议栈第190行左右的 
  if ( readCoordinatorJumper() )
    zgDeviceLogicalType = ZG_DEVICETYPE_COORDINATOR;
  else
    zgDeviceLogicalType = ZG_DEVICETYPE_ROUTER;这个判断中
    zgDeviceLogicalType = ZG_DEVICETYPE_COORDINATOR;全局变量可以代表ZigBee设备的逻辑类型
  */
  if(zgDeviceLogicalType == ZG_DEVICETYPE_COORDINATOR;)//ZG_DEVICETYPE_COORDINATOR  这个宏定义代表协调器
  													//goto 一下这个宏定义可以看到其他逻辑类型的宏定义名称
  {
    buff="I am coordinator device\n";
  }
  else if(zgDeviceLogicalType == ZG_DEVICETYPE_ENDDEVICE )//ZG_DEVICETYPE_ENDDEVICE代表终端
  {
    buff="I am endpoint device";
  }
  //它的第一个参数,代表发送目的地地址,作用:找到网络中的设备
  //第二个参数,端口描述符,作用:选中该设备上的某个端口
  //第三个参数,发送一个命令号,涉及到ZigBee里的一个簇的概念
  //第四个参数,发送数据的长度
  //第五个参数,真正发送的数据
  //第五个参数,一个指针,代表发送数据包的序列号,用来计算丢包率的一个变量
  //后两个参数不需要改动,做传参就可以
  if ( AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc,
                       SAMPLEAPP_PERIODIC_CLUSTERID,
                       strlen(buff),//此处用strlen计算数据包长度
                       buff,//发送实际数据,到这里发送数据设置完毕,下面看接收数据,回到刚才三个常用事件中的收到无线消息
                       &SampleApp_TransID,
                       AF_DISCV_ROUTE,
                       AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
  {
  }
  else
  {
    // Error occurred in request to send.
  }
}

void SampleApp_SendFlashMessage( uint16 flashTime )
{
  uint8 buffer[3];
  buffer[0] = (uint8)(SampleAppFlashCounter++);
  buffer[1] = LO_UINT16( flashTime );
  buffer[2] = HI_UINT16( flashTime );

  if ( AF_DataRequest( &SampleApp_Flash_DstAddr, &SampleApp_epDesc,
                       SAMPLEAPP_FLASH_CLUSTERID,
                       3,
                       buffer,
                       &SampleApp_TransID,
                       AF_DISCV_ROUTE,
                       AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
  {
  }
  else
  {
    // Error occurred in request to send.
  }
}


代码块二:MT_uart.c

#include "ZComDef.h"
#include "OSAL.h"
#include "hal_uart.h"
#include "MT.h"
#include "MT_UART.h"
#include "OSAL_Memory.h"


/***************************************************************************************************
 * MACROS
 ***************************************************************************************************/

/***************************************************************************************************
 * CONSTANTS
 ***************************************************************************************************/
/* State values for ZTool protocal */
#define SOP_STATE      0x00
#define CMD_STATE1     0x01
#define CMD_STATE2     0x02
#define LEN_STATE      0x03
#define DATA_STATE     0x04
#define FCS_STATE      0x05

/***************************************************************************************************
 *                                         GLOBAL VARIABLES
 ***************************************************************************************************/
/* Used to indentify the application ID for osal task */
byte App_TaskID;

/* ZTool protocal parameters */
uint8 state;
uint8  CMD_Token[2];
uint8  LEN_Token;
uint8  FSC_Token;
mtOSALSerialData_t  *pMsg;
uint8  tempDataLen;

#if defined (ZAPP_P1) || defined (ZAPP_P2)
uint16  MT_UartMaxZAppBufLen;
bool    MT_UartZAppRxStatus;
#endif

void MT_UartInit ()
{
  halUARTCfg_t uartConfig;

  /* Initialize APP ID */
  App_TaskID = 0;

  /* UART Configuration */
  uartConfig.configured           = TRUE;
  uartConfig.baudRate             = MT_UART_DEFAULT_BAUDRATE;
  uartConfig.flowControl          = MT_UART_DEFAULT_OVERFLOW;
  uartConfig.flowControlThreshold = MT_UART_DEFAULT_THRESHOLD;
  uartConfig.rx.maxBufSize        = MT_UART_DEFAULT_MAX_RX_BUFF;
  uartConfig.tx.maxBufSize        = MT_UART_DEFAULT_MAX_TX_BUFF;
  uartConfig.idleTimeout          = MT_UART_DEFAULT_IDLE_TIMEOUT;
  uartConfig.intEnable            = TRUE;
#if defined (ZTOOL_P1) || defined (ZTOOL_P2)
  uartConfig.callBackFunc         = MT_UartProcessZToolData;
#elif defined (ZAPP_P1) || defined (ZAPP_P2)
  uartConfig.callBackFunc         = MT_UartProcessZAppData;
#else
  uartConfig.callBackFunc         = NULL;
#endif

  /* Start UART */
#if defined (MT_UART_DEFAULT_PORT)
  HalUARTOpen (MT_UART_DEFAULT_PORT, &uartConfig);
#else
  /* Silence IAR compiler warning */
  (void)uartConfig;
#endif

  /* Initialize for ZApp */
#if defined (ZAPP_P1) || defined (ZAPP_P2)
  /* Default max bytes that ZAPP can take */
  MT_UartMaxZAppBufLen  = 1;
  MT_UartZAppRxStatus   = MT_UART_ZAPP_RX_READY;
#endif

}

void MT_UartRegisterTaskID( byte taskID )
{
  App_TaskID = taskID;
}

byte MT_UartCalcFCS( uint8 *msg_ptr, uint8 len )
{
  byte x;
  byte xorResult;

  xorResult = 0;

  for ( x = 0; x < len; x++, msg_ptr++ )
    xorResult = xorResult ^ *msg_ptr;

  return ( xorResult );
}


void MT_UartProcessZToolData ( uint8 port, uint8 event )
{
  uint8  ch;
  uint8  bytesInRxBuffer;
  
  (void)event;  // Intentionally unreferenced parameter

  while (Hal_UART_RxBufLen(port))
  {
    HalUARTRead (port, &ch, 1);

    switch (state)
    {
      case SOP_STATE:
        if (ch == MT_UART_SOF)
          state = LEN_STATE;
        break;

      case LEN_STATE:
        LEN_Token = ch;

        tempDataLen = 0;

        /* Allocate memory for the data */
        pMsg = (mtOSALSerialData_t *)osal_msg_allocate( sizeof ( mtOSALSerialData_t ) +
                                                        MT_RPC_FRAME_HDR_SZ + LEN_Token );

        if (pMsg)
        {
          /* Fill up what we can */
          pMsg->hdr.event = CMD_SERIAL_MSG;
          pMsg->msg = (uint8*)(pMsg+1);
          pMsg->msg[MT_RPC_POS_LEN] = LEN_Token;
          state = CMD_STATE1;
        }
        else
        {
          state = SOP_STATE;
          return;
        }
        break;

      case CMD_STATE1:
        pMsg->msg[MT_RPC_POS_CMD0] = ch;
        state = CMD_STATE2;
        break;

      case CMD_STATE2:
        pMsg->msg[MT_RPC_POS_CMD1] = ch;
        /* If there is no data, skip to FCS state */
        if (LEN_Token)
        {
          state = DATA_STATE;
        }
        else
        {
          state = FCS_STATE;
        }
        break;

      case DATA_STATE:

        /* Fill in the buffer the first byte of the data */
        pMsg->msg[MT_RPC_FRAME_HDR_SZ + tempDataLen++] = ch;

        /* Check number of bytes left in the Rx buffer */
        bytesInRxBuffer = Hal_UART_RxBufLen(port);

        /* If the remain of the data is there, read them all, otherwise, just read enough */
        if (bytesInRxBuffer <= LEN_Token - tempDataLen)
        {
          HalUARTRead (port, &pMsg->msg[MT_RPC_FRAME_HDR_SZ + tempDataLen], bytesInRxBuffer);
          tempDataLen += bytesInRxBuffer;
        }
        else
        {
          HalUARTRead (port, &pMsg->msg[MT_RPC_FRAME_HDR_SZ + tempDataLen], LEN_Token - tempDataLen);
          tempDataLen += (LEN_Token - tempDataLen);
        }

        /* If number of bytes read is equal to data length, time to move on to FCS */
        if ( tempDataLen == LEN_Token )
            state = FCS_STATE;

        break;

      case FCS_STATE:

        FSC_Token = ch;

        /* Make sure it's correct */
        if ((MT_UartCalcFCS ((uint8*)&pMsg->msg[0], MT_RPC_FRAME_HDR_SZ + LEN_Token) == FSC_Token))
        {
          osal_msg_send( App_TaskID, (byte *)pMsg );
        }
        else
        {
          /* deallocate the msg */
          osal_msg_deallocate ( (uint8 *)pMsg );
        }

        /* Reset the state, send or discard the buffers at this point */
        state = SOP_STATE;

        break;

      default:
       break;
    }
  }
}

#if defined (ZAPP_P1) || defined (ZAPP_P2)

void MT_UartProcessZAppData ( uint8 port, uint8 event )
{

  osal_event_hdr_t  *msg_ptr;
  uint16 length = 0;
  uint16 rxBufLen  = Hal_UART_RxBufLen(MT_UART_DEFAULT_PORT);

  /*
     If maxZAppBufferLength is 0 or larger than current length
     the entire length of the current buffer is returned.
  */
  if ((MT_UartMaxZAppBufLen != 0) && (MT_UartMaxZAppBufLen <= rxBufLen))
  {
    length = MT_UartMaxZAppBufLen;
  }
  else
  {
    length = rxBufLen;
  }

  /* Verify events */
  if (event == HAL_UART_TX_FULL)
  {
    // Do something when TX if full
    return;
  }

  if (event & ( HAL_UART_RX_FULL | HAL_UART_RX_ABOUT_FULL | HAL_UART_RX_TIMEOUT))
  {
    if ( App_TaskID )
    {
      /*
         If Application is ready to receive and there is something
         in the Rx buffer then send it up
      */
      if ((MT_UartZAppRxStatus == MT_UART_ZAPP_RX_READY ) && (length != 0))
      {
        /* Disable App flow control until it processes the current data */
         MT_UartAppFlowControl (MT_UART_ZAPP_RX_NOT_READY);

        /* 2 more bytes are added, 1 for CMD type, other for length */
        msg_ptr = (osal_event_hdr_t *)osal_msg_allocate( length + sizeof(osal_event_hdr_t) );
        if ( msg_ptr )
        {
          msg_ptr->event = SPI_INCOMING_ZAPP_DATA;
          msg_ptr->status = length;

          /* Read the data of Rx buffer */
          HalUARTRead( MT_UART_DEFAULT_PORT, (uint8 *)(msg_ptr + 1), length );

          /* Send the raw data to application...or where ever */
          osal_msg_send( App_TaskID, (uint8 *)msg_ptr );
        }
      }
    }
  }
}

void MT_UartZAppBufferLengthRegister ( uint16 maxLen )
{
  /* If the maxLen is larger than the RX buff, something is not right */
  if (maxLen <= MT_UART_DEFAULT_MAX_RX_BUFF)
    MT_UartMaxZAppBufLen = maxLen;
  else
    MT_UartMaxZAppBufLen = 1; /* default is 1 byte */
}


void MT_UartAppFlowControl ( bool status )
{

  /* Make sure only update if needed */
  if (status != MT_UartZAppRxStatus )
  {
    MT_UartZAppRxStatus = status;
  }

  /* App is ready to read again, ProcessZAppData have to be triggered too */
  if (status == MT_UART_ZAPP_RX_READY)
  {
    MT_UartProcessZAppData (MT_UART_DEFAULT_PORT, HAL_UART_RX_TIMEOUT );
  }

}

#endif //ZAPP

发布了13 篇原创文章 · 获赞 3 · 访问量 1848

猜你喜欢

转载自blog.csdn.net/weixin_44127810/article/details/104463308