14 ZigBee小项目笔记day01

终端节点:


/**************************************************************************************************
  Filename:       SimonApp.c
  Revised:        $Date: 2009-03-18 15:56:27 -0700 (Wed, 18 Mar 2009) $
  Revision:       $Revision: 19453 $

  Description:    Generic Application (no Profile).


  Copyright 2004-2009 Texas Instruments Incorporated. All rights reserved.

  IMPORTANT: Your use of this Software is limited to those specific rights
  granted under the terms of a software license agreement between the user
  who downloaded the software, his/her employer (which must be your employer)
  and Texas Instruments Incorporated (the "License").  You may not use this
  Software unless you agree to abide by the terms of the License. The License
  limits your use, and you acknowledge, that the Software may not be modified,
  copied or distributed unless embedded on a Texas Instruments microcontroller
  or used solely and exclusively in conjunction with a Texas Instruments radio
  frequency transceiver, which is integrated into your product.  Other than for
  the foregoing purpose, you may not use, reproduce, copy, prepare derivative
  works of, modify, distribute, perform, display or sell this Software and/or
  its documentation for any purpose.

  YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
  PROVIDED 揂S IS?WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, 
  INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE, 
  NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
  TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
  NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
  LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
  INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
  OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
  OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
  (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.

  Should you have any questions regarding your right to use this Software,
  contact Texas Instruments Incorporated at www.TI.com. 
**************************************************************************************************/

/*********************************************************************
  This application isn't intended to do anything useful, it is
  intended to be a simple example of an application's structure.

  This application sends "Hello World" to another "Generic"
  application every 15 seconds.  The application will also
  receive "Hello World" packets.

  The "Hello World" messages are sent/received as MSG type message.

  This applications doesn't have a profile, so it handles everything
  directly - itself.

  Key control:
    SW1:
    SW2:  initiates end device binding
    SW3:
    SW4:  initiates a match description request
*********************************************************************/

/*********************************************************************
 * INCLUDES
 */
#include "OSAL.h"
#include "AF.h"
#include "ZDApp.h"
#include "ZDObject.h"
#include "ZDProfile.h"

#include "SimonApp.h"
#include "DebugTrace.h"

#if !defined( WIN32 )
  #include "OnBoard.h"
#endif

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

#include"74LS164_8LED.h"
#include "SD_Key.h"

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

/*********************************************************************
 * CONSTANTS
 */

/*********************************************************************
 * TYPEDEFS
 */

/*********************************************************************
 * GLOBAL VARIABLES
 */

// This list should be filled with Application specific Cluster IDs.
const cId_t SimonApp_ClusterList[SimonApp_MAX_CLUSTERS] =
{
  SimonApp_CLUSTERID
};

const SimpleDescriptionFormat_t SimonApp_SimpleDesc =
{
  SimonApp_ENDPOINT,              //  int Endpoint;
  SimonApp_PROFID,                //  uint16 AppProfId[2];
  SimonApp_DEVICEID,              //  uint16 AppDeviceId[2];
  SimonApp_DEVICE_VERSION,        //  int   AppDevVer:4;
  SimonApp_FLAGS,                 //  int   AppFlags:4;
  SimonApp_MAX_CLUSTERS,          //  byte  AppNumInClusters;
  (cId_t *)SimonApp_ClusterList,  //  byte *pAppInClusterList;
  SimonApp_MAX_CLUSTERS,          //  byte  AppNumInClusters;
  (cId_t *)SimonApp_ClusterList   //  byte *pAppInClusterList;
};

// This is the Endpoint/Interface description.  It is defined here, but
// filled-in in SimonApp_Init().  Another way to go would be to fill
// in the structure here and make it a "const" (in code space).  The
// way it's defined in this sample app it is define in RAM.
endPointDesc_t SimonApp_epDesc;

/*********************************************************************
 * EXTERNAL VARIABLES
 */

/*********************************************************************
 * EXTERNAL FUNCTIONS
 */

/*********************************************************************
 * LOCAL VARIABLES
 */
byte SimonApp_TaskID;   // Task ID for internal task/event processing
                          // This variable will be received when
                          // SimonApp_Init() is called.
devStates_t SimonApp_NwkState;


byte SimonApp_TransID;  // This is the unique message ID (counter)

afAddrType_t SimonApp_DstAddr;









uint16  myAddr = 0;
uint16  mySeq = 0;

/*added by Simon*/
/*added by Simon*/
#define BUF_MAX   72//payload for zstack max 75
#define MY_PORT_NUM   0
uint8 gUartBuf[BUF_MAX];


/*************************************************************************/
/*|  1    | 1     |   2          |  2        |    1       |  1   |  64  |*/
/*-----------------------------------------------------------------------*/
/*|  type | id    |   sequence   |  shortAddr|  endpoint  |  0   | Data |*/
/*************************************************************************/
static void rxCB(uint8 port,uint8 event); 

#define MY_ENDPOINT 11














/*********************************************************************
 * LOCAL FUNCTIONS
 */
void SimonApp_ProcessZDOMsgs( zdoIncomingMsg_t *inMsg );
void SimonApp_HandleKeys( byte shift, byte keys );
void SimonApp_MessageMSGCB( afIncomingMSGPacket_t *pckt );
void SimonApp_SendTheMessage( void );

/*********************************************************************
 * NETWORK LAYER CALLBACKS
 */

/*********************************************************************
 * PUBLIC FUNCTIONS
 */

/*********************************************************************
 * @fn      SimonApp_Init
 *
 * @brief   Initialization function for the Generic App Task.
 *          This is called during initialization and should contain
 *          any application specific initialization (ie. hardware
 *          initialization/setup, table initialization, power up
 *          notificaiton ... ).
 *
 * @param   task_id - the ID assigned by OSAL.  This ID should be
 *                    used to send messages and set timers.
 *
 * @return  none
 */
void SimonApp_Init( byte task_id )
{

   /*added by Simon*/
  halUARTCfg_t uartConfig;



  SimonApp_TaskID = task_id;
  SimonApp_NwkState = DEV_INIT;
  SimonApp_TransID = 0;

  // Device hardware initialization can be added here or in main() (Zmain.c).
  // If the hardware is application specific - add it here.
  // If the hardware is other parts of the device add it in main().

  SimonApp_DstAddr.addrMode = (afAddrMode_t)AddrNotPresent;
  SimonApp_DstAddr.endPoint = 0;
  SimonApp_DstAddr.addr.shortAddr = 0;

  // Fill out the endpoint description.
  SimonApp_epDesc.endPoint = MY_ENDPOINT;//SimonApp_ENDPOINT;
  SimonApp_epDesc.task_id = &SimonApp_TaskID;
  SimonApp_epDesc.simpleDesc
            = (SimpleDescriptionFormat_t *)&SimonApp_SimpleDesc;
  SimonApp_epDesc.latencyReq = noLatencyReqs;

  // Register the endpoint description with the AF
  afRegister( &SimonApp_epDesc );

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








   /*added by Simon Initialize the uart*/
  uartConfig.configured = TRUE;
  uartConfig.baudRate = HAL_UART_BR_115200;
  uartConfig.flowControl = FALSE;
  uartConfig.flowControlThreshold = 256;                 // 2x30 don't care - see uart driver.
  uartConfig.rx.maxBufSize        = 256;                // 2x30 don't care - see uart driver.
  uartConfig.tx.maxBufSize        = 256;                // 2x30 don't care - see uart driver.
  uartConfig.idleTimeout          = 6;                 // 2x30 don't care - see uart driver.
  uartConfig.intEnable            = TRUE;              // 2x30 don't care - see uart driver.
  uartConfig.callBackFunc = rxCB;

  HalUARTOpen(MY_PORT_NUM,&uartConfig);
  mySeq = 0;//初始化数据包序号







  // Update the display
#if defined ( LCD_SUPPORTED )
    HalLcdWriteString( "SimonApp", HAL_LCD_LINE_1 );
#endif

  ZDO_RegisterForZDOMsg( SimonApp_TaskID, End_Device_Bind_rsp );
  ZDO_RegisterForZDOMsg( SimonApp_TaskID, Match_Desc_rsp );
}

/*********************************************************************
 * @fn      SimonApp_ProcessEvent
 *
 * @brief   Generic Application Task event processor.  This function
 *          is called to process all events for the task.  Events
 *          include timers, messages and any other user defined events.
 *
 * @param   task_id  - The OSAL assigned task ID.
 * @param   events - events to process.  This is a bit map and can
 *                   contain more than one event.
 *
 * @return  none
 */
UINT16 SimonApp_ProcessEvent( byte task_id, UINT16 events )
{
  afIncomingMSGPacket_t *MSGpkt;
  afDataConfirm_t *afDataConfirm;

  // Data Confirmation message fields
  byte sentEP;
  ZStatus_t sentStatus;
  byte sentTransID;       // This should match the value sent
  (void)task_id;  // Intentionally unreferenced parameter

  if ( events & SYS_EVENT_MSG )
  {
    MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SimonApp_TaskID );
    while ( MSGpkt )
    {
      switch ( MSGpkt->hdr.event )
      {
        case ZDO_CB_MSG:
          SimonApp_ProcessZDOMsgs( (zdoIncomingMsg_t *)MSGpkt );
          break;

        case KEY_CHANGE:
          SimonApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );
          break;

        case AF_DATA_CONFIRM_CMD:
          // This message is received as a confirmation of a data packet sent.
          // The status is of ZStatus_t type [defined in ZComDef.h]
          // The message fields are defined in AF.h
          afDataConfirm = (afDataConfirm_t *)MSGpkt;
          sentEP = afDataConfirm->endpoint;
          sentStatus = afDataConfirm->hdr.status;
          sentTransID = afDataConfirm->transID;
          (void)sentEP;
          (void)sentTransID;

          // Action taken when confirmation is received.
          if ( sentStatus != ZSuccess )
          {
            // The data wasn't delivered -- Do something
          }
          break;

        case AF_INCOMING_MSG_CMD:
          SimonApp_MessageMSGCB( MSGpkt );
          break;

        case ZDO_STATE_CHANGE:
          SimonApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
#if 0
          if ( (SimonApp_NwkState == DEV_ZB_COORD)
              || (SimonApp_NwkState == DEV_ROUTER)
              || (SimonApp_NwkState == DEV_END_DEVICE) )
          {
            // Start sending "the" message in a regular interval.
            osal_start_timerEx( SimonApp_TaskID,
                                SimonApp_SEND_MSG_EVT,
                              SimonApp_SEND_MSG_TIMEOUT );
          }
#endif
          /*网络状态改变的指示操作*/
          if (SimonApp_NwkState == DEV_ZB_COORD)
          {
            LS164_BYTE(11);
            osal_set_event( SimonApp_TaskID, SimonApp_SEND_MSG_EVT );
          }
          if (SimonApp_NwkState == DEV_ROUTER)
          {
            LS164_BYTE(12);
          }
          if (SimonApp_NwkState == DEV_END_DEVICE)
          {
            LS164_BYTE(13);
          }
          break;

        default:
          break;
      }

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

      // Next
      MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SimonApp_TaskID );
    }

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

  // Send a message out - This event is generated by a timer
  //  (setup in SimonApp_Init()).
  if ( events & SimonApp_SEND_MSG_EVT )
  {
#if 0
    // Send "the" message
    SimonApp_SendTheMessage();

    // Setup to send message again
    osal_start_timerEx( SimonApp_TaskID,
                        SimonApp_SEND_MSG_EVT,
                      SimonApp_SEND_MSG_TIMEOUT );
#endif 
    P0DIR |=0X02;
    P0_1=0;

    myAddr = NLME_GetShortAddr();
    // return unprocessed events
    return (events ^ SimonApp_SEND_MSG_EVT);
  }

  if ( events & SimonApp_MY_EVT )
  {
    if(0==P1_1)
     {//按钮3按下,给协调器的7号端点的0x0001号员工发送数据3
        char theMessageData[] ={3};
        SimonApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
        SimonApp_DstAddr.addr.shortAddr = 0x0000;
        // Take the first endpoint, Can be changed to search through endpoints
        SimonApp_DstAddr.endPoint = 7;

        AF_DataRequest( &SimonApp_DstAddr, &SimonApp_epDesc,
                   0x0001,
                   1,//(byte)osal_strlen( theMessageData ) + 1,
                   (byte *)&theMessageData,
                   &SimonApp_TransID,
                   AF_DISCV_ROUTE, AF_DEFAULT_RADIUS );
     }
     if(0==P2_0)
     {//按钮4按下,协调器的7号端点的0x0002号员工发送数据4
        char theMessageData[] ={4};
        SimonApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
        SimonApp_DstAddr.addr.shortAddr = 0x0000;
        // Take the first endpoint, Can be changed to search through endpoints
        SimonApp_DstAddr.endPoint = 7;

        AF_DataRequest( &SimonApp_DstAddr, &SimonApp_epDesc,
                   0x0002,
                   1,//(byte)osal_strlen( theMessageData ) + 1,
                   (byte *)&theMessageData,
                   &SimonApp_TransID,
                   AF_DISCV_ROUTE, AF_DEFAULT_RADIUS );
     }
     if(0==P0_5)
     {//按钮5按下,协调器的6号端点的0x0001号员工发送数据5
         char theMessageData[] ={5};
        SimonApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
        SimonApp_DstAddr.addr.shortAddr = 0x0000;
        // Take the first endpoint, Can be changed to search through endpoints
        SimonApp_DstAddr.endPoint = 6;

        AF_DataRequest( &SimonApp_DstAddr, &SimonApp_epDesc,
                   0x0001,
                   1,//(byte)osal_strlen( theMessageData ) + 1,
                   (byte *)&theMessageData,
                   &SimonApp_TransID,
                   AF_DISCV_ROUTE, AF_DEFAULT_RADIUS );
     }
    return (events ^ SimonApp_MY_EVT);
  }

  // Discard unknown events
  return 0;
}

/*********************************************************************
 * Event Generation Functions
 */

/*********************************************************************
 * @fn      SimonApp_ProcessZDOMsgs()
 *
 * @brief   Process response messages
 *
 * @param   none
 *
 * @return  none
 */
void SimonApp_ProcessZDOMsgs( zdoIncomingMsg_t *inMsg )
{
  switch ( inMsg->clusterID )
  {
    case End_Device_Bind_rsp:
      if ( ZDO_ParseBindRsp( inMsg ) == ZSuccess )
      {
        // Light LED
        HalLedSet( HAL_LED_4, HAL_LED_MODE_ON );
      }
#if defined(BLINK_LEDS)
      else
      {
        // Flash LED to show failure
        HalLedSet ( HAL_LED_4, HAL_LED_MODE_FLASH );
      }
#endif
      break;

    case Match_Desc_rsp:
      {
        ZDO_ActiveEndpointRsp_t *pRsp = ZDO_ParseEPListRsp( inMsg );
        if ( pRsp )
        {
          if ( pRsp->status == ZSuccess && pRsp->cnt )
          {
            SimonApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
            SimonApp_DstAddr.addr.shortAddr = pRsp->nwkAddr;
            // Take the first endpoint, Can be changed to search through endpoints
            SimonApp_DstAddr.endPoint = pRsp->epList[0];

            // Light LED
            HalLedSet( HAL_LED_4, HAL_LED_MODE_ON );
          }
          osal_mem_free( pRsp );
        }
      }
      break;
  }
}

/*********************************************************************
 * @fn      SimonApp_HandleKeys
 *
 * @brief   Handles all key events for this device.
 *
 * @param   shift - true if in shift/alt.
 * @param   keys - bit field for key events. Valid entries:
 *                 HAL_KEY_SW_4
 *                 HAL_KEY_SW_3
 *                 HAL_KEY_SW_2
 *                 HAL_KEY_SW_1
 *
 * @return  none
 */
void SimonApp_HandleKeys( byte shift, byte keys )
{
  zAddrType_t dstAddr;

  // Shift is used to make each button/switch dual purpose.
  if ( shift )
  {
    if ( keys & HAL_KEY_SW_1 )
    {
    }
    if ( keys & HAL_KEY_SW_2 )
    {
    }
    if ( keys & HAL_KEY_SW_3 )
    {
    }
    if ( keys & HAL_KEY_SW_4 )
    {
    }
  }
  else
  {
    if ( keys & HAL_KEY_SW_1 )
    {
    }

    if ( keys & HAL_KEY_SW_2 )
    {
      HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF );

      // Initiate an End Device Bind Request for the mandatory endpoint
      dstAddr.addrMode = Addr16Bit;
      dstAddr.addr.shortAddr = 0x0000; // Coordinator
      ZDP_EndDeviceBindReq( &dstAddr, NLME_GetShortAddr(), 
                            SimonApp_epDesc.endPoint,
                            SimonApp_PROFID,
                            SimonApp_MAX_CLUSTERS, (cId_t *)SimonApp_ClusterList,
                            SimonApp_MAX_CLUSTERS, (cId_t *)SimonApp_ClusterList,
                            FALSE );
    }

    if ( keys & HAL_KEY_SW_3 )
    {
    }

    if ( keys & HAL_KEY_SW_4 )
    {
      HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF );
      // Initiate a Match Description Request (Service Discovery)
      dstAddr.addrMode = AddrBroadcast;
      dstAddr.addr.shortAddr = NWK_BROADCAST_SHORTADDR;
      ZDP_MatchDescReq( &dstAddr, NWK_BROADCAST_SHORTADDR,
                        SimonApp_PROFID,
                        SimonApp_MAX_CLUSTERS, (cId_t *)SimonApp_ClusterList,
                        SimonApp_MAX_CLUSTERS, (cId_t *)SimonApp_ClusterList,
                        FALSE );
    }
  }
}

/*********************************************************************
 * LOCAL FUNCTIONS
 */

/*********************************************************************
 * @fn      SimonApp_MessageMSGCB
 *
 * @brief   Data message processor callback.  This function processes
 *          any incoming data - probably from other devices.  So, based
 *          on cluster ID, perform the intended action.
 *
 * @param   none
 *
 * @return  none
 */
void SimonApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )//在接收方成功接收以后会发送数据到该模块
{
  switch ( pkt->clusterId )
  {
    case CLUSTER_PHOTO_NODE://实际簇---房间里到底是谁
      if(1 == pkt->cmd.Data[0])//接收方反馈1作为接收成功的应答
      {
         HalUARTWrite(MY_PORT_NUM,"OK\r\n",4);//向串口/上位机发送成功发送的反馈信息
      }
     break;
  }
}

/*********************************************************************
 * @fn      SimonApp_SendTheMessage
 *
 * @brief   Send "the" message.
 *
 * @param   none
 *
 * @return  none
 */
void SimonApp_SendTheMessage( void )
{
  char theMessageData[] = "Hello World";

  if ( AF_DataRequest( &SimonApp_DstAddr, &SimonApp_epDesc,
                       SimonApp_CLUSTERID,
                       (byte)osal_strlen( theMessageData ) + 1,
                       (byte *)&theMessageData,
                       &SimonApp_TransID,
                       AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
  {
    // Successfully requested to be sent.
  }
  else
  {
    // Error occurred in request to send.
  }
}

/*********************************************************************
*********************************************************************/














/*added by Simon*/
/*当串口接收到上位机的数据以后,打包-->发送给协调器*/
static void rxCB(uint8 port,uint8 event)
{
    static uint8 tmp_len = 0;

    //osal_memset(gUartBuf,0,BUF_MAX);
    //在协议栈的回调函数里必须加上该条件判断才能正常使用回调功能
    //回调函数默认是利用DMA的轮询方式工作
    if ((event & (HAL_UART_RX_FULL | HAL_UART_RX_ABOUT_FULL | HAL_UART_RX_TIMEOUT)) &&!tmp_len)
    {
       if(!tmp_len)//tmp_len必须是0
       {
          osal_memset(gUartBuf,0,BUF_MAX);//清空缓冲区
          tmp_len=HalUARTRead(MY_PORT_NUM,gUartBuf+8, BUF_MAX);//读取串口内容,此时的长度tmp_len为有效数据长度

          /*开头的八个字节是节点的相关信息*/
          gUartBuf[0] =  TYPE_PHOTO;//节点类型
          gUartBuf[1] = MY_ID;//同类节点中的节点序号



          /*2530是低地址对应低字节*/
          /*在网络数据包里尽量吧低字节放在低地址(数据包的前面)*/
          /*该数据包在已发送序列中的序号*/
          mySeq++;
          //HalUARTWrite(MY_PORT_NUM,(uint8 *)&mySeq,2);          
          gUartBuf[3] =  (mySeq>>8);
          gUartBuf[2] =  (mySeq%256);


          /*该节点的网络短地址*/
          myAddr = NLME_GetShortAddr();
          gUartBuf[5] = (myAddr>>8);
          gUartBuf[4] = (myAddr%256);

          /*该节点用哪个端点给协调器发送数据*/
          gUartBuf[6] = MY_ENDPOINT;
          gUartBuf[7] = 0;//保留未使用-->填充为0

          //HalUARTWrite(MY_PORT_NUM,gUartBuf,tmp_len+3);
       }
       if(tmp_len>2 )//该参数有待修改
       {
//          HalUARTWrite(MY_PORT_NUM,(uint8*)&tmp_len,1);
          //HalUARTWrite(MY_PORT_NUM,gUartBuf,tmp_len+3);

          tmp_len += 8;//长度修正为实际数据包大小


          /*填充目标地址*/
          SimonApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;//单播模式
          SimonApp_DstAddr.addr.shortAddr = 0x0000;//目标是协调器
          // Take the first endpoint, Can be changed to search through endpoints
          SimonApp_DstAddr.endPoint = MY_ENDPOINT02;//发送给协调器的6号端点

          AF_DataRequest( &SimonApp_DstAddr, &SimonApp_epDesc,//端点描述符用默认填充的就好
                     CLUSTER_PHOTO_NODE,//6号端点里面的CLUSTER_PHOTO_NODE员工
                     tmp_len,//实际长度
                     (byte *)&gUartBuf,//打包好的数据
                     &SimonApp_TransID,//协议栈自动维护的数据包序号
                     AF_DISCV_ROUTE, AF_DEFAULT_RADIUS );//后两个参数默认不修改

       }
       tmp_len=0; //清空长度
    }
}





协调器

头文件(终端节点和协调器共用)

/**************************************************************************************************
  Filename:       SimonApp.h
  Revised:        $Date: 2007-10-27 17:22:23 -0700 (Sat, 27 Oct 2007) $
  Revision:       $Revision: 15795 $

  Description:    This file contains the Generic Application definitions.


  Copyright 2004-2007 Texas Instruments Incorporated. All rights reserved.

  IMPORTANT: Your use of this Software is limited to those specific rights
  granted under the terms of a software license agreement between the user
  who downloaded the software, his/her employer (which must be your employer)
  and Texas Instruments Incorporated (the "License").  You may not use this
  Software unless you agree to abide by the terms of the License. The License
  limits your use, and you acknowledge, that the Software may not be modified,
  copied or distributed unless embedded on a Texas Instruments microcontroller
  or used solely and exclusively in conjunction with a Texas Instruments radio
  frequency transceiver, which is integrated into your product.  Other than for
  the foregoing purpose, you may not use, reproduce, copy, prepare derivative
  works of, modify, distribute, perform, display or sell this Software and/or
  its documentation for any purpose.

  YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
  PROVIDED 揂S IS?WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, 
  INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE, 
  NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
  TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
  NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
  LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
  INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
  OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
  OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
  (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.

  Should you have any questions regarding your right to use this Software,
  contact Texas Instruments Incorporated at www.TI.com. 
**************************************************************************************************/

#ifndef SimonApp_H
#define SimonApp_H

#ifdef __cplusplus
extern "C"
{
#endif

/*********************************************************************
 * INCLUDES
 */
#include "ZComDef.h"

/*********************************************************************
 * CONSTANTS
 */

// These constants are only for example and should be changed to the
// device's needs
#define SimonApp_ENDPOINT           10

#define SimonApp_PROFID             0x0F04
#define SimonApp_DEVICEID           0x0001
#define SimonApp_DEVICE_VERSION     0
#define SimonApp_FLAGS              0

#define SimonApp_MAX_CLUSTERS       1
#define SimonApp_CLUSTERID          1

// Send Message Timeout
#define SimonApp_SEND_MSG_TIMEOUT   5000     // Every 5 seconds

// Application Events (OSAL) - These are bit weighted definitions.
#define SimonApp_SEND_MSG_EVT       0x0001











/*added by Simon*/  
#define SimonApp_MY_EVT       0x0002
#define SimonApp_RESPONSE_PHOTO_EVT       0x0004
#define SimonApp_RESPONSE_TINY_EVT       0x0008

#define TYPE_PHOTO 0x01
#define HDR_LENGTH 8
#define MY_ID 0  

#define CLUSTER_PHOTO_NODE  0x0001
#define CLUSTER_TINY_NODE   0x0002



#define MY_ENDPOINT01 7
#define MY_ENDPOINT02 6  




















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

/*********************************************************************
 * FUNCTIONS
 */

/*
 * Task Initialization for the Generic Application
 */
extern void SimonApp_Init( byte task_id );

/*
 * Task Event Processor for the Generic Application
 */
extern UINT16 SimonApp_ProcessEvent( byte task_id, UINT16 events );

/*********************************************************************
*********************************************************************/

#ifdef __cplusplus
}
#endif

#endif /* SimonApp_H */

实现文件:


/**************************************************************************************************
  Filename:       SimonApp.c
  Revised:        $Date: 2009-03-18 15:56:27 -0700 (Wed, 18 Mar 2009) $
  Revision:       $Revision: 19453 $

  Description:    Generic Application (no Profile).


  Copyright 2004-2009 Texas Instruments Incorporated. All rights reserved.

  IMPORTANT: Your use of this Software is limited to those specific rights
  granted under the terms of a software license agreement between the user
  who downloaded the software, his/her employer (which must be your employer)
  and Texas Instruments Incorporated (the "License").  You may not use this
  Software unless you agree to abide by the terms of the License. The License
  limits your use, and you acknowledge, that the Software may not be modified,
  copied or distributed unless embedded on a Texas Instruments microcontroller
  or used solely and exclusively in conjunction with a Texas Instruments radio
  frequency transceiver, which is integrated into your product.  Other than for
  the foregoing purpose, you may not use, reproduce, copy, prepare derivative
  works of, modify, distribute, perform, display or sell this Software and/or
  its documentation for any purpose.

  YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
  PROVIDED 揂S IS?WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, 
  INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE, 
  NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
  TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
  NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
  LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
  INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
  OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
  OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
  (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.

  Should you have any questions regarding your right to use this Software,
  contact Texas Instruments Incorporated at www.TI.com. 
**************************************************************************************************/

/*********************************************************************
  This application isn't intended to do anything useful, it is
  intended to be a simple example of an application's structure.

  This application sends "Hello World" to another "Generic"
  application every 15 seconds.  The application will also
  receive "Hello World" packets.

  The "Hello World" messages are sent/received as MSG type message.

  This applications doesn't have a profile, so it handles everything
  directly - itself.

  Key control:
    SW1:
    SW2:  initiates end device binding
    SW3:
    SW4:  initiates a match description request
*********************************************************************/

/*********************************************************************
 * INCLUDES
 */
#include "OSAL.h"
#include "AF.h"
#include "ZDApp.h"
#include "ZDObject.h"
#include "ZDProfile.h"

#include "SimonApp.h"
#include "DebugTrace.h"

#if !defined( WIN32 )
  #include "OnBoard.h"
#endif

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

#include"74LS164_8LED.h"
#include "SD_Key.h"
//#include "UART.h"

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

/*********************************************************************
 * CONSTANTS
 */

/*********************************************************************
 * TYPEDEFS
 */

/*********************************************************************
 * GLOBAL VARIABLES
 */

// This list should be filled with Application specific Cluster IDs.
const cId_t SimonApp_ClusterList[SimonApp_MAX_CLUSTERS] =
{
  SimonApp_CLUSTERID
};

const SimpleDescriptionFormat_t SimonApp_SimpleDesc =
{
  SimonApp_ENDPOINT,              //  int Endpoint;
  SimonApp_PROFID,                //  uint16 AppProfId[2];
  SimonApp_DEVICEID,              //  uint16 AppDeviceId[2];
  SimonApp_DEVICE_VERSION,        //  int   AppDevVer:4;
  SimonApp_FLAGS,                 //  int   AppFlags:4;
  SimonApp_MAX_CLUSTERS,          //  byte  AppNumInClusters;
  (cId_t *)SimonApp_ClusterList,  //  byte *pAppInClusterList;
  SimonApp_MAX_CLUSTERS,          //  byte  AppNumInClusters;
  (cId_t *)SimonApp_ClusterList   //  byte *pAppInClusterList;
};

// This is the Endpoint/Interface description.  It is defined here, but
// filled-in in SimonApp_Init().  Another way to go would be to fill
// in the structure here and make it a "const" (in code space).  The
// way it's defined in this sample app it is define in RAM.
endPointDesc_t SimonApp_epDesc;
endPointDesc_t SimonApp_epDesc1;

/*********************************************************************
 * EXTERNAL VARIABLES
 */

/*********************************************************************
 * EXTERNAL FUNCTIONS
 */

/*********************************************************************
 * LOCAL VARIABLES
 */
byte SimonApp_TaskID;   // Task ID for internal task/event processing
                          // This variable will be received when
                          // SimonApp_Init() is called.
devStates_t SimonApp_NwkState;


byte SimonApp_TransID;  // This is the unique message ID (counter)

afAddrType_t SimonApp_DstAddr;

/*********************************************************************
 * LOCAL FUNCTIONS
 */
void SimonApp_ProcessZDOMsgs( zdoIncomingMsg_t *inMsg );
void SimonApp_HandleKeys( byte shift, byte keys );
void SimonApp_MessageMSGCB( afIncomingMSGPacket_t *pckt );
void SimonApp_SendTheMessage( void );










/*added by Simon*/


#define TINY_ID_MAX      16
#define PHOTO_ID_MAX      1

typedef struct _AddrInfo
{
    uint16      shortAddr;
    byte        endPoint;
    uint8       exist;
    uint16       seqnb;
}AddrInfo_t;

AddrInfo_t *TinyNode_AddrArr;
AddrInfo_t *PothoNode_AddrArr;


#define BUF_MAX   72//payload for zstack max 75
#define MY_PORT_NUM   0
uint8 gUartBuf[10];

/*************************************************************************/
/*|  1    | 1     |   2          |  2        |    1       |  1   |  64  |*/
/*-----------------------------------------------------------------------*/
/*|  type | id    |   sequence   |  shortAddr|  endpoint  |  0   | Data |*/
/*************************************************************************/
static void rxCB(uint8 port,uint8 event); 
static void ResponsePhotoNode(void);




afAddrType_t gResponseAddr;



#define TYPE_PHOTO 0x01
#define HDR_LENGTH 8

static uint8 gPhotoID = 0;





/*********************************************************************
 * NETWORK LAYER CALLBACKS
 */

/*********************************************************************
 * PUBLIC FUNCTIONS
 */

/*********************************************************************
 * @fn      SimonApp_Init
 *
 * @brief   Initialization function for the Generic App Task.
 *          This is called during initialization and should contain
 *          any application specific initialization (ie. hardware
 *          initialization/setup, table initialization, power up
 *          notificaiton ... ).
 *
 * @param   task_id - the ID assigned by OSAL.  This ID should be
 *                    used to send messages and set timers.
 *
 * @return  none
 */


void SimonApp_Init( byte task_id )
{

  /*added by Simon*/
  halUARTCfg_t uartConfig;//串口配置变量


  SimonApp_TaskID = task_id;
  SimonApp_NwkState = DEV_INIT;
  SimonApp_TransID = 0;

  // Device hardware initialization can be added here or in main() (Zmain.c).
  // If the hardware is application specific - add it here.
  // If the hardware is other parts of the device add it in main().

  SimonApp_DstAddr.addrMode = (afAddrMode_t)AddrNotPresent;
  SimonApp_DstAddr.endPoint = 0;
  SimonApp_DstAddr.addr.shortAddr = 0;

  // Fill out the endpoint description.
  SimonApp_epDesc.endPoint = MY_ENDPOINT01;//SimonApp_ENDPOINT;
  SimonApp_epDesc.task_id = &SimonApp_TaskID;
  SimonApp_epDesc.simpleDesc
            = (SimpleDescriptionFormat_t *)&SimonApp_SimpleDesc;
  SimonApp_epDesc.latencyReq = noLatencyReqs;

  // Register the endpoint description with the AF
  afRegister( &SimonApp_epDesc );

  /*=========================================================================*/

  // Fill out the endpoint description.
  SimonApp_epDesc1.endPoint = MY_ENDPOINT02;//SimonApp_ENDPOINT;
  SimonApp_epDesc1.task_id = &SimonApp_TaskID;
  SimonApp_epDesc1.simpleDesc
            = (SimpleDescriptionFormat_t *)&SimonApp_SimpleDesc;
  SimonApp_epDesc1.latencyReq = noLatencyReqs;

  // Register the endpoint description with the AF
  afRegister( &SimonApp_epDesc1 );

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






  /*added by Simon Initialize the uart*/
  uartConfig.configured = TRUE;
  uartConfig.baudRate = HAL_UART_BR_115200;
  uartConfig.flowControl = FALSE;
  uartConfig.flowControlThreshold = 256;                 // 2x30 don't care - see uart driver.
  uartConfig.rx.maxBufSize        = 256;                // 2x30 don't care - see uart driver.
  uartConfig.tx.maxBufSize        = 256;                // 2x30 don't care - see uart driver.
  uartConfig.idleTimeout          = 6;                 // 2x30 don't care - see uart driver.
  uartConfig.intEnable            = TRUE;              // 2x30 don't care - see uart driver.
  uartConfig.callBackFunc = rxCB;

  HalUARTOpen(MY_PORT_NUM,&uartConfig);//打开串口--默认情况下,在这里还不能正常使用串口--具体原因有待抽时间分析


  TinyNode_AddrArr = (AddrInfo_t*)osal_mem_alloc(sizeof(AddrInfo_t)*TINY_ID_MAX);//给小节点(温湿度)存储地址信息的数组
  PothoNode_AddrArr = (AddrInfo_t*)osal_mem_alloc(sizeof(AddrInfo_t)*PHOTO_ID_MAX);//给传图像的节点分配存储地址的信息

  /*清空动态申请的内存空间*/
  osal_memset(TinyNode_AddrArr,0,sizeof(AddrInfo_t)*TINY_ID_MAX);
  osal_memset(PothoNode_AddrArr,0,sizeof(AddrInfo_t)*PHOTO_ID_MAX);







  // Update the display
#if defined ( LCD_SUPPORTED )
    HalLcdWriteString( "SimonApp", HAL_LCD_LINE_1 );
#endif

  ZDO_RegisterForZDOMsg( SimonApp_TaskID, End_Device_Bind_rsp );
  ZDO_RegisterForZDOMsg( SimonApp_TaskID, Match_Desc_rsp );


}

/*********************************************************************
 * @fn      SimonApp_ProcessEvent
 *
 * @brief   Generic Application Task event processor.  This function
 *          is called to process all events for the task.  Events
 *          include timers, messages and any other user defined events.
 *
 * @param   task_id  - The OSAL assigned task ID.
 * @param   events - events to process.  This is a bit map and can
 *                   contain more than one event.
 *
 * @return  none
 */
UINT16 SimonApp_ProcessEvent( byte task_id, UINT16 events )
{
  afIncomingMSGPacket_t *MSGpkt;
  afDataConfirm_t *afDataConfirm;

  // Data Confirmation message fields
  byte sentEP;
  ZStatus_t sentStatus;
  byte sentTransID;       // This should match the value sent
  (void)task_id;  // Intentionally unreferenced parameter

  if ( events & SYS_EVENT_MSG )
  {
    MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SimonApp_TaskID );
    while ( MSGpkt )
    {
      switch ( MSGpkt->hdr.event )
      {
        case ZDO_CB_MSG:
          SimonApp_ProcessZDOMsgs( (zdoIncomingMsg_t *)MSGpkt );
          break;

        case KEY_CHANGE:
          SimonApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );
          break;

        case AF_DATA_CONFIRM_CMD:
          // This message is received as a confirmation of a data packet sent.
          // The status is of ZStatus_t type [defined in ZComDef.h]
          // The message fields are defined in AF.h
          afDataConfirm = (afDataConfirm_t *)MSGpkt;
          sentEP = afDataConfirm->endpoint;
          sentStatus = afDataConfirm->hdr.status;
          sentTransID = afDataConfirm->transID;
          (void)sentEP;
          (void)sentTransID;

          // Action taken when confirmation is received.
          if ( sentStatus != ZSuccess )
          {
            // The data wasn't delivered -- Do something
          }
          break;

        case AF_INCOMING_MSG_CMD:
          SimonApp_MessageMSGCB( MSGpkt );
          break;

        case ZDO_STATE_CHANGE:
          SimonApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
#if 0
          if ( (SimonApp_NwkState == DEV_ZB_COORD)
              || (SimonApp_NwkState == DEV_ROUTER)
              || (SimonApp_NwkState == DEV_END_DEVICE) )
          {
            // Start sending "the" message in a regular interval.
            osal_start_timerEx( SimonApp_TaskID,
                                SimonApp_SEND_MSG_EVT,
                              SimonApp_SEND_MSG_TIMEOUT );
          }
#endif
          if (SimonApp_NwkState == DEV_ZB_COORD)//变为协调器,数码管显示C
          {
            LS164_BYTE(11);

            osal_set_event( SimonApp_TaskID, SimonApp_SEND_MSG_EVT );//设置SimonApp_SEND_MSG_EVT以便执行SimonApp_SEND_MSG_EVT的处理函数
          }
          if (SimonApp_NwkState == DEV_ROUTER)//变为路由器,数码管显示R
          {
            LS164_BYTE(12);
          }
          if (SimonApp_NwkState == DEV_END_DEVICE)//变为终端节点,数码管显示E
          {
            LS164_BYTE(13);
          }
          break;

        default:
          break;
      }

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

      // Next
      MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SimonApp_TaskID );
    }

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

  // Send a message out - This event is generated by a timer
  //  (setup in SimonApp_Init()).
  if ( events & SimonApp_SEND_MSG_EVT )
  {
#if 0
    // Send "the" message
    SimonApp_SendTheMessage();

    // Setup to send message again
    osal_start_timerEx( SimonApp_TaskID,
                        SimonApp_SEND_MSG_EVT,
                      SimonApp_SEND_MSG_TIMEOUT );
#endif 
    /*在变为协调器的同时点亮LED*/
    P0DIR |=0X02;
    P0_1=0;


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

  if ( events & SimonApp_MY_EVT )
  {
    if(0==P1_1)
     {//按钮3按下
        LS164_BYTE(3);//显示3
     }
     if(0==P2_0)
     {//按钮4按下
        LS164_BYTE(4);
     }
     if(0==P0_5)
     {//按钮5按下
        LS164_BYTE(5);
     }
    return (events ^ SimonApp_MY_EVT);
  }


  /*在收到终端节点的数据以后要发送反馈信息给相应的终端节点*/
  if ( events & SimonApp_RESPONSE_PHOTO_EVT )
  {
    ResponsePhotoNode();
    return (events ^ SimonApp_RESPONSE_PHOTO_EVT);
  }

  // Discard unknown events
  return 0;
}

/*********************************************************************
 * Event Generation Functions
 */

/*********************************************************************
 * @fn      SimonApp_ProcessZDOMsgs()
 *
 * @brief   Process response messages
 *
 * @param   none
 *
 * @return  none
 */
void SimonApp_ProcessZDOMsgs( zdoIncomingMsg_t *inMsg )
{
  switch ( inMsg->clusterID )
  {
    case End_Device_Bind_rsp:
      if ( ZDO_ParseBindRsp( inMsg ) == ZSuccess )
      {
        // Light LED
        HalLedSet( HAL_LED_4, HAL_LED_MODE_ON );
      }
#if defined(BLINK_LEDS)
      else
      {
        // Flash LED to show failure
        HalLedSet ( HAL_LED_4, HAL_LED_MODE_FLASH );
      }
#endif
      break;

    case Match_Desc_rsp:
      {
        ZDO_ActiveEndpointRsp_t *pRsp = ZDO_ParseEPListRsp( inMsg );
        if ( pRsp )
        {
          if ( pRsp->status == ZSuccess && pRsp->cnt )
          {
            SimonApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
            SimonApp_DstAddr.addr.shortAddr = pRsp->nwkAddr;
            // Take the first endpoint, Can be changed to search through endpoints
            SimonApp_DstAddr.endPoint = pRsp->epList[0];

            // Light LED
            HalLedSet( HAL_LED_4, HAL_LED_MODE_ON );
          }
          osal_mem_free( pRsp );
        }
      }
      break;
  }
}

/*********************************************************************
 * @fn      SimonApp_HandleKeys
 *
 * @brief   Handles all key events for this device.
 *
 * @param   shift - true if in shift/alt.
 * @param   keys - bit field for key events. Valid entries:
 *                 HAL_KEY_SW_4
 *                 HAL_KEY_SW_3
 *                 HAL_KEY_SW_2
 *                 HAL_KEY_SW_1
 *
 * @return  none
 */
void SimonApp_HandleKeys( byte shift, byte keys )
{
  zAddrType_t dstAddr;

  // Shift is used to make each button/switch dual purpose.
  if ( shift )
  {
    if ( keys & HAL_KEY_SW_1 )
    {
    }
    if ( keys & HAL_KEY_SW_2 )
    {
    }
    if ( keys & HAL_KEY_SW_3 )
    {
    }
    if ( keys & HAL_KEY_SW_4 )
    {
    }
  }
  else
  {
    if ( keys & HAL_KEY_SW_1 )
    {
    }

    if ( keys & HAL_KEY_SW_2 )
    {
      HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF );

      // Initiate an End Device Bind Request for the mandatory endpoint
      dstAddr.addrMode = Addr16Bit;
      dstAddr.addr.shortAddr = 0x0000; // Coordinator
      ZDP_EndDeviceBindReq( &dstAddr, NLME_GetShortAddr(), 
                            SimonApp_epDesc.endPoint,
                            SimonApp_PROFID,
                            SimonApp_MAX_CLUSTERS, (cId_t *)SimonApp_ClusterList,
                            SimonApp_MAX_CLUSTERS, (cId_t *)SimonApp_ClusterList,
                            FALSE );
    }

    if ( keys & HAL_KEY_SW_3 )
    {
    }

    if ( keys & HAL_KEY_SW_4 )
    {
      HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF );
      // Initiate a Match Description Request (Service Discovery)
      dstAddr.addrMode = AddrBroadcast;
      dstAddr.addr.shortAddr = NWK_BROADCAST_SHORTADDR;
      ZDP_MatchDescReq( &dstAddr, NWK_BROADCAST_SHORTADDR,
                        SimonApp_PROFID,
                        SimonApp_MAX_CLUSTERS, (cId_t *)SimonApp_ClusterList,
                        SimonApp_MAX_CLUSTERS, (cId_t *)SimonApp_ClusterList,
                        FALSE );
    }
  }
}

/*********************************************************************
 * LOCAL FUNCTIONS
 */

/*********************************************************************
 * @fn      SimonApp_MessageMSGCB
 *
 * @brief   Data message processor callback.  This function processes
 *          any incoming data - probably from other devices.  So, based
 *          on cluster ID, perform the intended action.
 *
 * @param   none
 *
 * @return  none
 */
void SimonApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
  uint8 id = 255;
  if ( MY_ENDPOINT01 == pkt->endPoint )//7号端点
  {
      switch ( pkt->clusterId )
      {
        case 0x0001://1号员工--负责处理终端节点按键3按下发送过来的数据

          //Uart_Send_String(pkt->cmd.Data,pkt->cmd.DataLength);
          LS164_BYTE(pkt->cmd.Data[0]);
          MYLED1 ^= 1;//LED翻转
          break;
        case 0x0002://2号员工--负责处理终端节点按键4按下发送过来的数据
          //Uart_Send_String(pkt->cmd.Data,pkt->cmd.DataLength);
          LS164_BYTE(pkt->cmd.Data[0]);
          MYLED2 ^= 1;
          break;

      }
  }

  if ( MY_ENDPOINT02 == pkt->endPoint )//6号端点/房间
  {
      switch ( pkt->clusterId )
      {
        case CLUSTER_PHOTO_NODE://1号员工

          //Uart_Send_String(pkt->cmd.Data,pkt->cmd.DataLength);
          //LS164_BYTE(pkt->cmd.Data[0]);
          //HalUARTWrite(MY_PORT_NUM,"Simon\r\n",7);
          if(TYPE_PHOTO == pkt->cmd.Data[0])//如果是图像节点发送来的数据
          {
            MYLED3 ^= 1;//LED3翻转

            id = pkt->cmd.Data[1];//获取节点在同类节点中的序号
            gPhotoID = id;//缓存序号
            //HalUARTWrite(MY_PORT_NUM,pkt->cmd.Data,pkt->cmd.DataLength);


            //if(0 == PothoNode_AddrArr[id].exist)
            {
              //((uint8 * )&(PothoNode_AddrArr[id].shortAddr))[0] =  pkt->cmd.Data[5];//pkt->cmd.Data[4]<<8+ pkt->cmd.Data[5]);
              //((uint8 * )&(PothoNode_AddrArr[id].shortAddr))[1] =  pkt->cmd.Data[4];


              /*每次数据到来都讲数据包里携带的网络短地址和端点缓存下来*/
              PothoNode_AddrArr[id].shortAddr = *((uint16 *)&(pkt->cmd.Data[4]));//(pkt->cmd.Data[5]*256+ pkt->cmd.Data[4]);
              PothoNode_AddrArr[id].endPoint = pkt->cmd.Data[6];
              //表示已经缓存过该节点--现处于调试阶段--后期修改
              //按理来说,这里的代码应该只在节点第一次发送数据给协调器的时候调用
              PothoNode_AddrArr[id].exist = 1;

              MYLED2 ^= 1;//协调器第一次收到某个节点发送的数据--翻转LED2
            }
 #if 0           
            //HalUARTWrite(MY_PORT_NUM,(uint8 *)PothoNode_AddrArr,PHOTO_ID_MAX*sizeof(AddrInfo_t));


            //if((PothoNode_AddrArr[id].seqnb + 1) == (pkt->cmd.Data[2]<<8+ pkt->cmd.Data[3]))
            //if( (((uint8 * )&(PothoNode_AddrArr[id].seqnb))[0] +1)  == pkt->cmd.Data[3]
            //   && ((uint8 * )&(PothoNode_AddrArr[id].seqnb))[1] == pkt->cmd.Data[2] )
            //if((PothoNode_AddrArr[id].seqnb + 1) == (pkt->cmd.Data[3]*256+ pkt->cmd.Data[2]))
            if((PothoNode_AddrArr[id].seqnb + 1) == (*((uint16 *)&(pkt->cmd.Data[2]))))
            {
              HalUARTWrite(MY_PORT_NUM,pkt->cmd.Data,pkt->cmd.DataLength);
              osal_set_event( SimonApp_TaskID, SimonApp_RESPONSE_PHOTO_EVT );
              PothoNode_AddrArr[id].seqnb++;

            }
#endif          

            //每次有数据到来,都直接将数据发送给上位机
            HalUARTWrite(MY_PORT_NUM,pkt->cmd.Data+8,pkt->cmd.DataLength-8);
            //每次有数据到来,都给节点反馈信息
            osal_set_event( SimonApp_TaskID, SimonApp_RESPONSE_PHOTO_EVT );
            //ResponsePhotoNode();

          }
          break;
      }
  }
}

/*********************************************************************
 * @fn      SimonApp_SendTheMessage
 *
 * @brief   Send "the" message.
 *
 * @param   none
 *
 * @return  none
 */
void SimonApp_SendTheMessage( void )
{
  char theMessageData[] = "Hello World";

  if ( AF_DataRequest( &SimonApp_DstAddr, &SimonApp_epDesc,
                       SimonApp_CLUSTERID,
                       (byte)osal_strlen( theMessageData ) + 1,
                       (byte *)&theMessageData,
                       &SimonApp_TransID,
                       AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
  {
    // Successfully requested to be sent.
  }
  else
  {
    // Error occurred in request to send.
  }
}

/*********************************************************************
*********************************************************************/







/*added by Simon*/

/*暂时没多大用处*/
static void rxCB(uint8 port,uint8 event)
{
#if 0 //串口回显测试用
    uint8 tmp_len = 0;

    osal_memset(gUartBuf,0,BUF_MAX);

    tmp_len = HalUARTRead(MY_PORT_NUM,gUartBuf,5);

    gUartBuf[tmp_len] =  tmp_len;
    gUartBuf[tmp_len+1] = '\r';
    gUartBuf[tmp_len+2] = '\n';

    //HalUARTWrite(MY_PORT_NUM,(uint8*)&tmp_len,1);//
    if(osal_memcmp(gUartBuf,"12345",5))
    {
      HalUARTWrite(MY_PORT_NUM,(uint8*)&tmp_len,1);
      HalUARTWrite(MY_PORT_NUM,gUartBuf,tmp_len+3);
    }
#endif
    static uint8 tmp_len = 0;
    if ((event & (HAL_UART_RX_FULL | HAL_UART_RX_ABOUT_FULL | HAL_UART_RX_TIMEOUT)) &&!tmp_len)
    {
       if(!tmp_len)
       {
          tmp_len=HalUARTRead(MY_PORT_NUM,gUartBuf, BUF_MAX);
          gUartBuf[tmp_len] =  tmp_len;
          gUartBuf[tmp_len+1] = '\r';
          gUartBuf[tmp_len+2] = '\n';
       }
       if(tmp_len>2)
       {
          HalUARTWrite(MY_PORT_NUM,(uint8*)&tmp_len,1);
          HalUARTWrite(MY_PORT_NUM,gUartBuf,tmp_len+3);
       }
       tmp_len=0; 
    }
}


static void ResponsePhotoNode(void)//给节点反馈信息
{

  char theMessageData[] = {1};//给节点发送一个1表示成功收到他的数据

  gResponseAddr.addrMode = (afAddrMode_t)Addr16Bit;
  gResponseAddr.addr.shortAddr = PothoNode_AddrArr[gPhotoID].shortAddr;
  // Take the first endpoint, Can be changed to search through endpoints
  gResponseAddr.endPoint = PothoNode_AddrArr[gPhotoID].endPoint;

  if ( AF_DataRequest( &gResponseAddr, &SimonApp_epDesc,
                       CLUSTER_PHOTO_NODE,
                       1,
                       (byte *)&theMessageData,
                       &SimonApp_TransID,
                       AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
  {
    // Successfully requested to be sent.
  }
  else
  {
    // Error occurred in request to send.
    osal_set_event( SimonApp_TaskID, SimonApp_RESPONSE_PHOTO_EVT );
  }
}

上位机

串口模块

头文件:



#ifndef __UART_H__
#define __UART_H__


#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <sys/types.h>  
#include <sys/stat.h>  
#include <errno.h>  
#include <termios.h>  
#include <fcntl.h>  
#include <sys/time.h>  
#include <unistd.h> 


//#define COMGERAL  1  
#define MAX_COM_NUM 4 

#define OPEN_UART_ERR   -1 
#define SET_UART_ERR    -2


typedef unsigned char uint8;

int set_uart_config(int fd,int baudrate,int data_bit,char parity,int stop_bit);
int open_uart(int com_port) ;



#endif

实现文件:


/************************************* 
*filename:serialconfig.c 
*author:ZhenjunLiu 
*desc:config the serial with some args 
*************************************/  

#include "uart.h"  

int set_uart_config(int fd,int baudrate,int data_bit,char parity,int stop_bit)  
{  
        struct termios new_cfg,old_cfg;  
        int speed;  

        /*1.保存原先串口配置*/  
        if(tcgetattr(fd,&old_cfg) != 0)  
        {  
                perror("tcgetattr");  
                return -1;  

        }  

        new_cfg = old_cfg;  


        /*2.激活选项,设置为原始模式*/  
        new_cfg.c_cflag |= CLOCAL | CREAD;  
        cfmakeraw(&new_cfg);  

        /*3.设置位掩码,除去位掩码*/  
        new_cfg.c_cflag &= ~CSIZE;  


        /*4.设置波特率*/  
        switch(baudrate)  
        {  
                case 2400:  
                    {  
                        speed = B2400;    
                    }  
                    break;  

                case 4800:  
                    {  
                        speed = B4800;    
                    }  
                    break;  
                case 9600:  
                    {  
                        speed = B9600;    
                    }  
                    break;  
                case 19200:  
                    {  
                        speed = B19200;   
                    }  
                    break;  
                case 38400:  
                    {  
                        speed = B38400;   
                    }  
                    break;  
                case 230400:  
                    {  
                        speed = B230400;      
                    }  
                    break;  
                case 115200:  
                default:  
                    {  
                        speed = B115200;      
                    }  
                    break;  


        }  

        /*实际波特率的设置*/  
        cfsetispeed(&new_cfg,speed);  

        cfsetospeed(&new_cfg,speed);  


        /*5.数据位设置*/  
        switch(data_bit)  
        {  
                case 7:  
                    {  
                        new_cfg.c_cflag |= CS7;  
                    }  
                    break;  

                default:  
                case 8:  
                    {  
                        new_cfg.c_cflag |= CS8;  
                    }  
                    break;  

        }  


        /*6.奇偶校验位*/  
        switch(parity)  
        {  
                default:  
                case 'n':  
                case 'N':  
                    {  
                        new_cfg.c_cflag &= ~PARENB;  
                        new_cfg.c_iflag &= ~INPCK;  
                    }  
                    break;  
                case 'o':  
                case 'O':  
                    {  

                        new_cfg.c_cflag |= (PARENB | PARODD);  
                        new_cfg.c_iflag |= INPCK;  
                    }  
                    break;  

                case 'e':  
                case 'E':  
                    {  

                        new_cfg.c_cflag |= PARENB;  
                        new_cfg.c_cflag &= ~PARODD;  
                        new_cfg.c_iflag |= INPCK;  
                    }  
                    break;  

                case 's':  
                case 'S':  
                    {  

                        new_cfg.c_cflag &= ~PARENB;  
                        new_cfg.c_cflag &= ~CSTOPB;  
                    }  
                    break;  
        }  


        /*7.设置停止位*/  
        switch(stop_bit)  
        {  
                case 1:  
                default:  
                    {  
                        new_cfg.c_cflag &= ~CSTOPB;    
                    }  
                break;  

                case 2:  
                    {  
                        new_cfg.c_cflag |= CSTOPB;  
                    }  
                break;  

        }  

        /*8.设置最少字符和等待时间*/  
        new_cfg.c_cc[VTIME] = 0;  
        new_cfg.c_cc[VMIN] = 4;  

        /*9.清除串口缓冲 
                    TCIFLUSH:对接收到而未被读取的数据进行清空处理 
                    TCOFLUSH:对尚未传送成功的输出数据进行清空处理 
                    TCIOFLUSH:包括前两种功能,即对尚未处理的数据进行处理 
        */  
        tcflush(fd,TCIFLUSH);  


        /*10.激活配置 
            TCSANOW:配置的修改立即生效 
            TCSADRAIN:配置的修改在所有写入fd的输出都传输完毕之后生效 
            TCSAFLUSH:所有已接收但未读入的输入都将在修改生效之前被丢弃 
        */  
        if((tcsetattr(fd,TCSANOW,&new_cfg)) != 0)  
        {  
                perror("tcsetattr");  
                return -1;        

        }  


        return 0;  
}  



int open_uart(int com_port)  
{  
        int fd;  
#ifdef COMGERAL  
        char *dev[] = {"/dev/ttySAC0","/dev/ttySAC1","/dev/ttySAC2","/dev/ttySAC3"};  
#else  
        char *dev[] = {"/dev/ttyUSB0","/dev/ttyUSB1","/dev/ttyUSB2","/dev/ttyUSB3"};  
#endif  

        if((com_port < 0) || (com_port > MAX_COM_NUM))  
            {  
                return -1;  

            }  

        fd = open(dev[com_port -1],O_RDWR | O_NOCTTY | O_NDELAY);  

        if(fd < 0)  
            {  
                perror("open");  
                return -1;  
            }  

        if(fcntl(fd,F_SETFL,0) < 0)  
            {  

                perror("fcntl");  
                return -1;   
            }  

        if(isatty(fd) == 0)  
            {  
                perror("This is not a tty");  
                return -1;  
            }  

            return fd;  
}  


主程序:


#include "uart.h" 

#define MAX_BUF 64
#define OPEN_PIC_ERR    -2  
const char begin_str[] = "begin\r\n";
const char end_str[] = "end\r\n";
char buf[MAX_BUF]={0};
char rcv_buf[MAX_BUF]={0};

int main(int argc,char ** argv)
{
  int uart_fd    = 0;
  int res        = 0;
  int pic_fd     = 0;
  int read_cnt   = 0;

  fd_set inset,tempset;  
  struct timeval tv; 
  FD_ZERO(&inset);

  if(argc <2)
  {
    printf("too less args...\n");
    exit(-1);
  }

  /*0. 打开串口*/
  uart_fd = open_uart(1);
  if(uart_fd < 0)
  {
    perror("open_uart");
    return OPEN_UART_ERR;
  }
  FD_SET(uart_fd,&inset);


  /*1. 配置串口*/
  if(set_uart_config(uart_fd,115200,8,'N',1) < 0)  
  {  
      perror("set_uart_config");  
      return SET_UART_ERR;  
  }  

  /*2. 向串口写入开始发送数据包*/
  write(uart_fd,begin_str,strlen(begin_str)); 

  /*3. 传输图片*/

  /*3.1. 打开图片*/
  pic_fd = open((const char *)argv[1],O_RDONLY);
  if(pic_fd < 0)
  {
      perror("open");  
      return OPEN_PIC_ERR;  
  }


  /*3.2. 读取一部分数据到缓冲区*/
  /*临时缓冲区清零*/
  memset(buf,0,MAX_BUF);

  /*等待时间初始化*/
  tv.tv_sec = 1;  
  tv.tv_usec = 0; 

  while((read_cnt = read(pic_fd,buf,MAX_BUF)) > 0 )
  {
      /*3.3. 将当前缓冲区数据包写入串口*/
      write(uart_fd,buf,read_cnt);

      /*3.3. 等待接收端响应*/
      while(1)
      {
          memset(rcv_buf,0,MAX_BUF);

          /*为了程序的健壮性,需要在主循环不断更新文件描述符集合以及等待时间*/
          tempset = inset;
          tv.tv_sec = 1;  
          tv.tv_usec = 0;  
          res = select(uart_fd + 1,&tempset,NULL,NULL,&tv);  

          /*3.3.1 规定时间内收到响应数据包继续往下执行*/
          /*3.3.2 超时没有响应信息则重新发送当前缓冲区数据包*/
          /*3.3.3 发生错误就退出程序给出提示信息*/
          if(res == 0)
          {  
              printf("time out \n");
              write(uart_fd,buf,read_cnt);
              continue;
          }  
          else if (res < 0)
          {  
              printf("select error\n"); 
              exit(-1);
          } 
          else  
          {  
              if(FD_ISSET(uart_fd, &inset)) 
              {
                read(uart_fd,rcv_buf,MAX_BUF);  
                printf("from zigbee:%s",rcv_buf);
                //if(strcmp(rcv_buf,"OK\r\n") == 0)
                break;
              }  
          }  

      }

      /*临时缓冲区清零*/
      memset(buf,0,MAX_BUF);

  }
  /*3.4. 数据是否读取完毕*/
  /*3.4.1 没有读完,重复3.2至此*/
  memset(buf,0,MAX_BUF);
  memset(rcv_buf,0,MAX_BUF);


  /*3.4.2 读取完毕,向串口写入发送完毕数据包*/
  write(uart_fd,end_str,strlen(end_str)); 

  close(pic_fd);
  close(uart_fd);


  return 0;
}

Makefile


src = $(wildcard *.c)
targets = $(patsubst %.c, %.o, $(src))

CC = gcc
CFLAGS = -Wall -g 

all:app

app:$(targets)
    $(CC) zigbee.o uart.o -o app $(CFLAGS)

%.o:%.c
    $(CC) -c $< $(CFLAGS)

.PHONY:clean all
clean:
    -rm -rf $(targets)  app

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值