终端节点:
/**************************************************************************************************
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