CC2530接入OneNET-实现数据上传和命令下发

前言:
之前物联网课设时就想用CC2530单片机和ESP8266-01S来实现数据上传和远程控制,当时在网上也找了很多资料,无果。本来是不想再碰这个的,由于我同学做毕设需要用到,所以再努力了一把,也终于解决了困扰很久的问题。先分享给大家,希望可以帮到正在做课设或是毕设的各位!!!

功能介绍:
使用CC2530单片机实现数据上传和远程控制的功能。大概流程如下:终端采集数据无线发送到协调器,协调器再将数据上传到OneNET云平台,在云平台上可以下发命令控制LED灯。

前期准备:
1、有OneNET的账号
2、刷入 OneNET 提供的 ESP8266 固件
刷固件的工具,提取码:8266
需要下载的固件位置:
在这里插入图片描述
下载注意:
在这里插入图片描述
硬件准备:
1、两块CC2530板子
2、WIFI模块esp8266-01s或者esp8266-01
3、USB转串口模块,用于烧录固件
4、HC-SR04超声波测距模块,用于终端采集距离数据(也有使用温湿度的源码)

模块接线:
ESP8266-01S: TX–P0_5 RX–P0_4 VCC–3.3V GND–GND
ESP8266-01: TX–P0_5 RX–P0_4 VCC–3.3V GND–GND EN–3.3V
HC-SR04: TRIG — P1_1 ECHO — P0_6 VCC --5V

演示图片:
1、实物图
在这里插入图片描述
2、协调器串口输出数据
在这里插入图片描述
3、设备处于在线状态
在这里插入图片描述
4、终端采集的数据Distance
在这里插入图片描述
5、下发命令
在设备列表中的详情/数据流/更多可以找到下发命令
发送字符串LED1翻转P1_0引脚处的LED灯,发送LED2翻转P2_0处的LED灯
在这里插入图片描述
6、设备响应下发的指令
在这里插入图片描述
代码实现:
SampleApp.c文件

/*********************************************************************
超声波引脚连接说明 andy
 TRIG ---- P1_1      
 ECHO ---- P0_6  
 VCC ---5V
 */
#include "OSAL.h"
#include "ZGlobals.h"
#include "AF.h"
#include "aps_groups.h"
#include "ZDApp.h"
#include "stdio.h"
#include "string.h"
#include <stdlib.h>
#include "Hcsr04.h" 

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

/* HAL */
#include "hal_lcd.h"
#include "hal_led.h"
#include "hal_key.h"
#include "MT_UART.h"
#include "MT_APP.h"
#include "MT.h"
#include "hal_uart.h" /*  串口头文件  */
/*
  需要修改的地方:WIFI名字、密码、OneNET的登录信息
*/
 //参数分别代表WIFI名称、密码
#define WIFI_INFO      "AT+CWJAP=XIAOCHUN,3118003167\r\n"
 //参数分别代表设备ID、产品ID、鉴权信息
#define OneNET_INFO    "AT+IOTCFG=879125822,486413,0713\r\n"

//SampleApp_ClusterList就是一个簇,
//包含了命令SAMPLEAPP_PERIODIC_CLUSTERID、SAMPLEAPP_FLASH_CLUSTERID
const cId_t SampleApp_ClusterList[SAMPLEAPP_MAX_CLUSTERS] =
{
  SAMPLEAPP_PERIODIC_CLUSTERID,
  SAMPLEAPP_FLASH_CLUSTERID
};
/*简单设备描述符--使用一个网络地址可以描述一个节点,在一个节点上有很多端口
故用简单描述符来描述一个端口*/
const SimpleDescriptionFormat_t SampleApp_SimpleDesc =
{
  SAMPLEAPP_ENDPOINT,               //端口号,这里是20,可以在1-240随便取 
  SAMPLEAPP_PROFID,                 //应用规范ID       
  SAMPLEAPP_DEVICEID,               //应用设备ID   
  SAMPLEAPP_DEVICE_VERSION,         //应用版本号  
  SAMPLEAPP_FLAGS,                  //保留
  SAMPLEAPP_MAX_CLUSTERS,           //输入簇包含的命令个数,这里是2
  (cId_t *)SampleApp_ClusterList,   //输入簇列表
   SAMPLEAPP_MAX_CLUSTERS,          //输出簇包含的命令个数
  (cId_t *)SampleApp_ClusterList     //  输出簇列表
};

endPointDesc_t SampleApp_epDesc;  //端口描述符

uint8 SampleApp_TaskID;          //任务ID    

devStates_t SampleApp_NwkState;  //保存节点状态的变量  

uint8 SampleApp_TransID;         //数据发送序号

afAddrType_t SampleApp_Periodic_DstAddr; //广播


/*  串口基本定义    */
#define MY_DEFINE_UART0_PORT 0   //自定义串口号(0,1);
#define MY_DEFINE_UART1_PORT 1   //自定义串口号(0,1);
#define RX_MAX_LENGTH       20    //接收缓冲区最大值: 20个字节;
uint8   RX_BUFFER[RX_MAX_LENGTH]; //接收缓冲区;
/*********************************************************************
 * LOCAL FUNCTIONS
 */
void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pckt );//处理终端数据 发送数据到云平台
void SampleApp_SendPeriodicMessage( void );  //消息处理函数
void SampleApp_HandleKeys( uint8 shift, uint8 keys ); //按键事件处理函数

void Uart0_Config(void); //串口0配置函数
void Uart1_Config(void); //串口1配置函数
void Uart0CallBackFunction(uint8 port , uint8 event); //回调函数声明,定义在最后面;
void Uart1CallBackFunction(uint8 port , uint8 event); //回调函数声明,定义在最后面;

/*应用层初始化函数*/
void SampleApp_Init( uint8 task_id )
{ 
  
  unsigned char tmp[10];
  SampleApp_TaskID = task_id;  //初始化任务优先级
  SampleApp_NwkState = DEV_INIT;//将设备的状态初始化为DEV_INIT,表示该节点没有连接到Zigbee网络
  SampleApp_TransID = 0;   //将发送数据包的序号初始化为0
 
  SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
  SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
  SampleApp_Periodic_DstAddr.addr.shortAddr = 0x0000; 
 //对节点描述符进行初始化
  SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT;
  SampleApp_epDesc.task_id = &SampleApp_TaskID;
  SampleApp_epDesc.simpleDesc
            = (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc;
  SampleApp_epDesc.latencyReq = noLatencyReqs;
 //用afRegister函数将节点描述符进行注册,注册后才能使用OSAL提供的服务
  afRegister( &SampleApp_epDesc );
  //注册按键事件
  RegisterForKeys( SampleApp_TaskID );
 //串口初始化
  Uart0_Config();
  Uart1_Config();

  osal_memset(tmp,0,10);
  tmp[0] = HAL_UART_DMA+0x30; //1
  tmp[1] = HAL_UART_ISR+0x30; //2
  tmp[2] = HAL_UART_USB+0x30; //0
  //HalUARTWrite(0, tmp, 6);
  HalUARTWrite(0, "\r\nuart ok\r\n\r\n", 18);//串口测试

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

/*消息处理函数*/
uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
{
  afIncomingMSGPacket_t *MSGpkt;
  (void)task_id;  // Intentionally unreferenced parameter
    
  if ( events & SYS_EVENT_MSG )
  {
    MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
    while ( MSGpkt )
    {
      switch ( MSGpkt->hdr.event )
      {
        //当接收到此终端的无线消息
        case AF_INCOMING_MSG_CMD:
          SampleApp_MessageMSGCB( MSGpkt );
          break;
        
        case ZDO_STATE_CHANGE:  //协调器不执行定时发送命令
          //读取节点的设备类型,如果是终端节点,实现无线数据发送
          SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
          if ( //(SampleApp_NwkState == DEV_ZB_COORD) ||//协调器不执行定时发送命令
                 (SampleApp_NwkState == DEV_ROUTER)
              || (SampleApp_NwkState == DEV_END_DEVICE) )
          {
             Init_UltrasoundRanging(); //初始化超声波
             //3S后执行SAMPLEAPP_SEND_PERIODIC_MSG_EVT事件
            osal_start_timerEx( SampleApp_TaskID,
                              SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
                              SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );
          }
          else
          {
            // Device is no longer in the network
          }
          break;

        default:
          break;
      }
      Delay_ms(10);
      osal_msg_deallocate( (uint8 *)MSGpkt );
      MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
    }
    // return unprocessed events
    return (events ^ SYS_EVENT_MSG);
  }
  //  (setup in SampleApp_Init()). 协调器不执行定时发送函数
  if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )
  {
    SampleApp_SendPeriodicMessage();
    //3S后再次执行
    osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
        (SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) );
    return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT);
  }
  return 0;
}

//协调器收到终端数据 发送数据到云平台
void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
  uint16 flashTime;
   unsigned char dataBuf[36 ]; //确保数组能够装下发送的内容
   unsigned int distance = 0;
       
  switch ( pkt->clusterId )
  {
    case SAMPLEAPP_P2P_CLUSTERID:

      break;    
    case SAMPLEAPP_PERIODIC_CLUSTERID:            
      //收到终端数据后向平台发送数据
       // pkt->cmd.Data形如:100,为了到到100做如下操作 
        distance = atoi((char const *)pkt->cmd.Data);  //碰到非数字结束转换
        sprintf((char *)dataBuf,(char *)"AT+IOTSEND=0,Distance,%d\r\n",distance);
        HalUARTWrite(1, dataBuf,30);   
      break;

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

//终端采集数据 无线发送给协调器
void SampleApp_SendPeriodicMessage( void )
{
  unsigned char strBuf[4];
  uint16 date=0;
  UltrasoundRanging(LoadRegBuf);    
  date=256*H2+L2-L1-256*H1; 
  //得到距离
  distance=(uint)(date*1.7)/100; 
  sprintf((char *)strBuf,"%d",distance);
  //将strBuf无线发送给协调器
  if ( AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc,
                      SAMPLEAPP_PERIODIC_CLUSTERID,
                      4,
                      strBuf,
                      &SampleApp_TransID,
                      AF_DISCV_ROUTE,
                      AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
  {
  }
  else
  {
    // Error occurred in request to send.
  }
}

/*********************************************************************
                    一些自定义函数
*********************************************************************/
/*串口配置函数*/
void Uart0_Config(void)  //函数定义;
{ 
  halUARTCfg_t uartConfig; //定义串口配置结构体变量;
  uartConfig.configured            = TRUE;  //允许配置;
  uartConfig.baudRate              = HAL_UART_BR_115200;//波特率;
  uartConfig.flowControl           = FALSE;
  uartConfig.flowControlThreshold  = 64;   //don't care - see uart driver.
  uartConfig.rx.maxBufSize         = 128;  //串口接收缓冲区大小
  uartConfig.tx.maxBufSize         = 128;  //串口发送缓冲区大小
  uartConfig.idleTimeout           = 6;    //don't care - see uart driver.
  uartConfig.intEnable             = TRUE; //使能中断
  uartConfig.callBackFunc          = Uart0CallBackFunction; //指定回调函数名;
  HalUARTOpen(MY_DEFINE_UART0_PORT , &uartConfig); //打开串口
}
void Uart1_Config(void)  //函数定义;
{ 
  halUARTCfg_t uartConfig; //定义串口配置结构体变量;
  uartConfig.configured            = TRUE;  //允许配置;
  uartConfig.baudRate              = HAL_UART_BR_115200;//波特率;
  uartConfig.flowControl           = FALSE;
  uartConfig.flowControlThreshold  = 64;   //don't care - see uart driver.
  uartConfig.rx.maxBufSize         = 128;  //串口接收缓冲区大小
  uartConfig.tx.maxBufSize         = 128;  //串口发送缓冲区大小
  uartConfig.idleTimeout           = 6;    //don't care - see uart driver.
  uartConfig.intEnable             = TRUE; //使能中断
  uartConfig.callBackFunc          = Uart1CallBackFunction; //指定回调函数名;
  HalUARTOpen(MY_DEFINE_UART1_PORT , &uartConfig); //打开串口
}

/*********************************************************************
*
*     函数名:  UartCallBackFunction
*     函数功能:串口回调函数,接收到数据时会调用到该函数;
*     传入参数:port:串口号    event:事件 
*     返回参数:无
*
*********************************************************************/
static void Uart0CallBackFunction(uint8 port , uint8 event)
{
    uint8 RX_Length = 0; //接收到字符串大小;
    
    RX_Length = Hal_UART_RxBufLen(MY_DEFINE_UART0_PORT); //读取接收字符串大小;
    
    if(RX_Length != 0) //有数据存在;
    {
        //读取串口0数据;
        HalUARTRead(MY_DEFINE_UART0_PORT , RX_BUFFER , RX_Length);
        //输出串口0接收的数据
        HalUARTWrite(MY_DEFINE_UART0_PORT ,  RX_BUFFER , RX_Length);
    }
}

static void Uart1CallBackFunction(uint8 port , uint8 event)
{
    uint8 RX_Length = 0; //接收到字符串大小;
    static int s_count = 99;
    s_count++; 
    RX_Length = Hal_UART_RxBufLen(MY_DEFINE_UART1_PORT); //读取接收字符串大小;
    if(RX_Length==0) return ;  //如果长度为0,直接返回
 
     //读取串口1数据;
    HalUARTRead(MY_DEFINE_UART1_PORT , RX_BUFFER , RX_Length);
    //s_count从0加到100时进入,防止刷爆串口1
    if(strstr((char const *)RX_BUFFER,"WIFI DISCONNECT")&&(s_count%100==0))
    {
      //手动接入AP  后面自动接入
       HalUARTWrite(1, WIFI_INFO, strlen(WIFI_INFO));
        s_count=0; 
    }
    
    else if(strstr((char const *)RX_BUFFER,"WIFI GOT IP"))
    {
      //配置登录信息
       HalUARTWrite(1, OneNET_INFO, strlen(OneNET_INFO));
    }
    else if(strstr((char const *)RX_BUFFER,"Connect:0"))
    {
       HalUARTWrite(0, "Successful access OneNET\r\n", strlen("Successful access OneNET\r\n"));
    }
    //下发命令LED1
    else if(strstr((char const *)RX_BUFFER,"LED1"))
    {
        HalLedSet(HAL_LED_1, HAL_LED_MODE_TOGGLE);  //状态翻转
    }
    //下发命令LED2
    else if(strstr((char const *)RX_BUFFER,"LED2"))
    {
       HalLedSet(HAL_LED_2, HAL_LED_MODE_TOGGLE); 
    }
    //继续else if来添加其他命令
    
    //输入到串口0,方便看串口1接收的信息
    HalUARTWrite(MY_DEFINE_UART0_PORT ,  RX_BUFFER , RX_Length);
}

代码需要更改的地方:
在这里插入图片描述
代码存在的问题:
1、路由节点编译报错
尝试过网上的解答,没用。原本代码就有这个问题,暂时无法解决。
在这里插入图片描述
2、EndDeviceEB-1、2、3、4编译不通过,由于很久之前我觉得这部分多余,移除了这部分代码,下拉框的选项不会删。
在这里插入图片描述
代码位置说明:
1、终端采集数据代码 无线发送给协调器代码
在这里插入图片描述
2、实现远程控制的代码
在这里插入图片描述

追加内容:
鉴于大家平时接触最多的是DHT11温湿度传感器,故另外写了一份DHT11的源码。与超声波测距模块不同,DHT11有温度、湿度两个数据,协调器收到终端的数据后,需要把温湿度值分别拿到,再分别发送到串口1。具体可以看如下代码:
终端采集数据 无线发送给协调器
在这里插入图片描述
协调器收到终端数据 发送数据到云平台
在这里插入图片描述
如果出现温湿度读取数值为0的情况,可能是你的传感器和我的温湿度代码不匹配,建议可以另找合适温湿度程序。
最后:
需要源码的可以自行下载。代码下载链接
下载操作:
在这里插入图片描述

评论 44
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

⁽⁽ଘ晴空万里ଓ⁾⁾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值