头文件(终端节点和协调器共用)
/************************************************************************************************** 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 __cplusplusextern "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 1typedef 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 0uint8 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 8static 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 -2typedef 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 = gccCFLAGS = -Wall -g all:appapp:$(targets) $(CC) zigbee.o uart.o -o app $(CFLAGS)%.o:%.c $(CC) -c $< $(CFLAGS).PHONY:clean allclean: -rm -rf $(targets) app新闻热点
疑难解答