注册 登录
电子工程世界-论坛 返回首页 EEWORLD首页 频道 EE大学堂 下载中心 Datasheet 专题
bbs.pan.com的个人空间 https://home.eeworld.com.cn/space-uid-565503.html [收藏] [复制] [分享] [RSS]
日志

GenericApp实战:电压的采集与定时发送

已有 2323 次阅读2014-7-28 16:21 |个人分类:zigbee学习总结| zigbee

实验目的:终端设备采集自身工作电池电压,将数据发往协调器,协调器将数据通过串口发送到PC上的串口调试助手

CoordinateEB(协调器):

typedef union h
{
  unsigned char dat[18];
  struct rtfx
  {
  uint8 head[2];    //&&
  uint8 type[3];    //节点的类型
  uint8 myNWK[4];   //自身网络地址
  uint8 pNWK[4];    //父节点网络地址
  uint8 value[4];   //第一个字节value[0]为V表示电压,后面三位为数据
  uint8 tail;       //&
  }BUF;
}RTFX;

RTFX rtfx;      //保存发送过来的数据

void GenericApp_Init( byte task_id )        //任务初始化函数
{
  GenericApp_TaskID = task_id;
//  GenericApp_NwkState = DEV_INIT;
  GenericApp_TransID = 0;         //发送数据包的序列初始化为0

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

  //对节点描述符进行初始化
  // Fill out the endpoint description.
  GenericApp_epDesc.endPoint = GENERICAPP_ENDPOINT;
  GenericApp_epDesc.task_id = &GenericApp_TaskID;
  GenericApp_epDesc.simpleDesc
            = (SimpleDescriptionFormat_t *)&GenericApp_SimpleDesc;
  GenericApp_epDesc.latencyReq = noLatencyReqs;


  afRegister( &GenericApp_epDesc );   //afRegister()对节点的描述符进行注册,注册后,才能使用OSAL提供服务

 
  RegisterForKeys( GenericApp_TaskID );


#if defined ( LCD_SUPPORTED )
    HalLcdWriteString( "GenericApp", HAL_LCD_LINE_1 );
#endif
   
  ZDO_RegisterForZDOMsg( GenericApp_TaskID, End_Device_Bind_rsp );
  ZDO_RegisterForZDOMsg( GenericApp_TaskID, Match_Desc_rsp ); 
  
  /*以下为设置串口,定义在hal_uart.h文件里*/
  halUARTCfg_t uartConfig;     //该结构体变量实现串口的配置
  uartConfig.configured = TRUE;
  uartConfig.baudRate = HAL_UART_BR_9600;   //波特率9600
  uartConfig.flowControl = FALSE;     //流控制
  uartConfig.callBackFunc =   NULL;     //回调函数,类型为void (*halUARTCBack_t)(uint8 port,uint8 event)
  HalUARTOpen(0,&uartConfig);       //串口是否打开
}


void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
   uint8 changline[2] = {0x0a, 0x0d};
  switch(pkt->clusterId)    //对消息簇中的命令ID进行匹配
  {
  case GENERICAPP_CLUSTERID:     //这里的这个与发送方发送数据时的一样
    HalLedBlink(HAL_LED_1,0,50,500);      //LED1闪烁
    HalUARTWrite(0, changline, 2);
    osal_memcpy(&rtfx, pkt->cmd.Data, sizeof(rtfx));
    HalUARTWrite(0, rtfx.dat, sizeof(rtfx));
    HalUARTWrite(0, changline, 2);
    break;
  }
}


EndDeviceEB(终端):


typedef union h
{
  unsigned char dat[18];
  struct rtfx
  {
  uint8 head[2];    //&&
  uint8 type[3];    //节点的类型
  uint8 myNWK[4];   //自身网络地址
  uint8 pNWK[4];    //父节点网络地址
  uint8 value[4];   //第一个字节value[0]为V表示电压,后面三位为数据
  uint8 tail;       //&
  }BUF;
}RTFX;


void GenericApp_Init( byte task_id )        //任务初始化函数
{
  GenericApp_TaskID = task_id;
  GenericApp_NwkState = DEV_INIT;
  GenericApp_TransID = 0;         //发送数据包的序列初始化为0


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

  //对节点描述符进行初始化
  // Fill out the endpoint description.
  GenericApp_epDesc.endPoint = GENERICAPP_ENDPOINT;
  GenericApp_epDesc.task_id = &GenericApp_TaskID;
  GenericApp_epDesc.simpleDesc
            = (SimpleDescriptionFormat_t *)&GenericApp_SimpleDesc;
  GenericApp_epDesc.latencyReq = noLatencyReqs;


  afRegister( &GenericApp_epDesc );   //afRegister()对节点的描述符进行注册,注册后,才能使用OSAL提供服务


  RegisterForKeys( GenericApp_TaskID );

  // Update the display
#if defined ( LCD_SUPPORTED )
    HalLcdWriteString( "GenericApp", HAL_LCD_LINE_1 );
#endif
   
  ZDO_RegisterForZDOMsg( GenericApp_TaskID, End_Device_Bind_rsp );
  ZDO_RegisterForZDOMsg( GenericApp_TaskID, Match_Desc_rsp );
}


UINT16 GenericApp_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( GenericApp_TaskID );  //osal_msg_receive()从消息队列上接收消息
    while ( MSGpkt )
    {
      switch ( MSGpkt->hdr.event )     //消息头部中的event进行匹配
      {
        case ZDO_CB_MSG:
          GenericApp_ProcessZDOMsgs( (zdoIncomingMsg_t *)MSGpkt );
          break;

        case ZDO_STATE_CHANGE:
          GenericApp_NwkState = (devStates_t)(MSGpkt->hdr.status);  //读取节点的设备信息
       
          if( (GenericApp_NwkState == DEV_ROUTER)
             || (GenericApp_NwkState == DEV_END_DEVICE))     //该节点路由器或终端
          {
            osal_set_event( GenericApp_TaskID, GENERICAPP_SEND_MSG_EVT);  //设置发送事件
          }
          break;

        default:
          break;
      }

      // Release the memory
      osal_msg_deallocate( (uint8 *)MSGpkt );  //接收到的消息处理完后,释放消息所占的存储空间

      // Next
      //处理完一个消息后,再从消息队列里接受消息,然后进行相应的处理,直到所有消息处理完
      MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );
    }

    // return unprocessed events
    return (events ^ SYS_EVENT_MSG);      //返回未处理的事件
  }


  if ( events & GENERICAPP_SEND_MSG_EVT )
  {
    sendVdd();    //这个函数是关键

    // Setup to send message again
    //参数1:标示哪个任务
    //参数2:事件名
    //参数3:定时的时间,单位毫秒
    osal_start_timerEx( GenericApp_TaskID,
                        GENERICAPP_SEND_MSG_EVT,
                      GENERICAPP_SEND_MSG_TIMEOUT );

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

  return 0;
}

//发送采集的电压信息
static void sendVdd()
{
  uint16 nwk;
  osal_memcpy(rtfx.BUF.head, "&&", 2);
  //根据网络状态,填写类型字段
  if(GenericApp_NwkState == DEV_ROUTER)
  {
    osal_memcpy(rtfx.BUF.type, "ROU", 3);
  }
  else if(GenericApp_NwkState == DEV_END_DEVICE)
  {
    osal_memcpy(rtfx.BUF.type, "DEV", 3);
  }
  //获取地址信息
  nwk = NLME_GetShortAddr();
  binary_To_hex(rtfx.BUF.myNWK, (uint8*)&nwk, 2);
  nwk = NLME_GetCoordShortAddr();
  binary_To_hex(rtfx.BUF.pNWK, (uint8*)&nwk, 2);
  rtfx.BUF.value[0] = 'V';
  unsigned int Vdd = read_vdd();
  rtfx.BUF.value[1] = Vdd / 10 + '0';
  rtfx.BUF.value[2] = '.';
  rtfx.BUF.value[3] = Vdd % 10 + '0';
  rtfx.BUF.tail = '&';
 
  afAddrType_t my_DstAddr;
  my_DstAddr.addrMode = (afAddrMode_t)Addr16Bit; 
  my_DstAddr.endPoint = GENERICAPP_ENDPOINT;
  my_DstAddr.addr.shortAddr = 0x0000;       //协调器网络地址
  if(AF_DataRequest(&my_DstAddr, &GenericApp_epDesc, GENERICAPP_CLUSTERID,
                 sizeof(rtfx.dat)+1, rtfx.dat,
                 &GenericApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS) == afStatus_SUCCESS)
  {


  }
}


//读取电压
unsigned int read_vdd()
{
  uint16 value;

  /* Clear ADC interrupt flag */
  ADCIF = 0;

  ADCCON3 = 0x1f;

  /* Wait for the conversion to finish */
  while ( !ADCIF );

  /* Get the result */
  value = ADCL;
  value |= ((uint16) ADCH) << 8;

  /*
   * value now contains measurement of Vdd/3
   * 0 indicates 0V and 32767 indicates 1.25V
   * voltage = (value*3*1.25)/32767 volts
   * we will multiply by this by 10 to allow units of 0.1 volts
   */

  value = value >> 6;   // divide first by 2^6
  value = (uint16)(value * 37.5);
  value = value >> 9;   // ...and later by 2^9...to prevent overflow during multiplication

  return value;

}

综合上述,只要自己添加自己的消息以及消息处理函数,在适当的时候设置事件即可达到效果。再者这里传输的是电压,如果是传感器的数据,那么组合起来就是一个传感网,这个可以自行实现,不难。


全部作者的其他最新日志
评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

热门文章