小蜜蜂笔记
嵌入式开发与物联网应用教育践行者

【赛题详解】2019年物联网国赛任务三题1-无线通信系统(附解题思路与关键源码)

题目要求

Zigbee通讯拥有短距离无线通讯的能力,选用一个Zigbee节点盒(蓝色),一个Zigbee模块(黑色),实现点对点的数据传输通讯,考核选手Zigbee点对点知识的掌握,利用给定的工程实现任务。
要求如下:
<1> Zigbee网络号PAN ID信道号Channel ID请参考纸质附件给定的值。
<2> 程序开始运行Zigbee节点盒LED1、LED2灯亮,Zigbee模块D4、D3、D6、D5灯亮
<3> 单击Zigbee节点盒SW1后,板上的LED1、LED2灯进入交替亮灭状态(如LED1亮则LED2灭,LED2亮则LED1灭);同时发送一个信息给Zigbee模块,当Zigbee模块收到这个信息后Zigbee模块板上的D4、D3、D6、D5灯进入流水灯状态。
<4> 单击Zigbee模块上的SW1后,板上的D5、D6、D3、D4灯进入流水状态;同时发送一个信息给Zigbee节点盒,当Zigbee节点盒收到这个信息后Zigbee节点盒板上的LED1、LED2进入呼吸灯状态;
<5> 单击Zigbee模块上的SW2后,重置两个Zigbee板上的灯,Zigbee模块D4、D3、D6、D5灯亮;Zigbee节点盒LED1、LED2灯亮
<6> 能重复实现以上步骤。
<7> Zigbee节点盒要实现与PC端串口的通讯功能,以便接收PC端软件由串口发送过来的数据后,通过无线通讯转发给Zigbee模块,再由Zigbee模块将这个数据通过串口发送给Android端软件。
<8> Zigbee模块要实现与Android端串口的通讯功能,以便接收Android端软件由串口发送过来的数据后,通过无线通讯转发给Zigbee节点盒,再由节点盒将这个数据通过串口发送给PC端软件。

补充说明
<1> 在两块Zigbee板上的小辣椒(天线)上贴上“任务三题1”标签纸,Zigbee节点盒通过USB转串口线接入开发机电脑,Zigbee模块通过公母直连串口线接入到移动互联终端,两个Zigbee板都要接上电源待裁判评判。
<2> Zigbee节点盒与PC端连接的串口为COM8、波特率为115200Zigbee模块与移动互联终端连接的串口为COM2,波特率为115200,要求编译后的工程软件直接运行就能读取到相应的信息。

任务三题1的第<7><8>项功能,还是任务五题1<3>和第<4>的实现基础,也就是说,这个RF无线数据透传功能无法实现,任务五题1的部分功能也无法得分。
任务五题1:点对点聊天系统。
<3> 当在输入消息文本框里输入相应的文本之后,点击发送按钮,将这条文本信息显示在现实文本框的最后一行,同时把这条消息通过串口发送给任务三题1提供的Zigbee模块,由模块转发给Zigbee节点盒最终由PC端接收并显示该信息。
<4> Android端接收到从Zigbee模块串口发送过来相应的信息,则直接把该信息显示在现实文本框的最后一行。

参考资料:基于BaiscRF点对点通信的灯光控制
参考资料:
基于BaiscRF点对点通信的串口收发
参考资料:
Zigbee模块XMF09B国赛兼容版资料汇总
参考资料:
BasicRF点对点无线通信的应用开发核心要点
参考资料:
BasicRf点对点与Z-Stack组网国赛官方提供API函数汇总
参考资料:十大传感器模块的接口电路与API函数资料汇总

HEX烧写代码下载:2019年国赛任务三题1-Zigbee节点盒
HEX烧写代码下载:2019年国赛任务三题1-Zigbee模块

解题思路

这是一道非常优秀的BasicRF综合应用题目,仅仅掌握BasicRF点对点无线通信相关的内容是很难在一个小时左右完成题目的。这道题目的重要知识点至少包括:
<1> 基于BasicRF点对点通信的无线数据收发。
<2> 基于BasicRF点对点通信的串口数据收发。
<3> 基于BasicRF点对点通信的I/O端口控制。
<4> 呼吸灯的是程序现实。
<5> 简单通信协议的设计。
<6> 多状态切换的系统框架设计。

解答该题目,你可以参考以下的步骤要点:
<1> 认真阅读题目,至少三遍以上, 把题目中的要点摘录至草稿纸上。
<2> 头脑中要初步形成总体的设计思路和清晰的实现步骤,最好能把基本的系统结构和应用逻辑勾勒过来,不然很难在短时间内完全解答该题目。
<3> 先设计一个单独的程序,实现呼吸灯的功能。呼吸灯的实现跟BasicRF点对点通信没有关系,但应该是本题的一个难点,你可以选择用定时器来实现PWM信号,也可以用普通延时函数来实现。用定时器会涉及一些寄存器的设置和中断的处理,所以,我采用了普通延时函数来实现,这也是一个比较快捷的方法。
<4> 再设计一个单独的程序,实现串口与RF无线之间的数据透传功能。也就是利用串口助手等工具在PC端通过串口向A节点发送数据,A节点收到后通过RF无线发送到B节点,B节点收到数据后,再通过串口发送给PC端并在另一个串口助手中显示出来。反之亦然。
注:看起来这里虽然多写了2个测试程序,但这是为了扫除题目中最大的两个技术障碍,使后面的应用程序开发的道路更顺畅平台。如果你对这两部分内容很熟练的话,这个2个测试程序就免了。
<5> 根据应用的具体要求和实现环境 设计点对点的通信协议。在这里我选择了32字节的数组作为无线传输的数据帧,其结构定义如下:
第0字节:系统命令字。
第1字节:数据域的有效长度。
第2字节~第31字节:数据域。
<6> 定义通信协议中系统命令字。本题选择状态机作为系统应用逻辑处理的基本思路,在这个步骤中实际上也把系统的具体切换状态确定了。 具体的命令字定义,大家可以参考后面的源码与注释。
<7> 按照系统设计思路和通信协议,设计具体的应用程序,并调试。

Zigbee模块与Zigbee节点盒的硬件资源

黑色Zigbee模块核心源码

/***************点对点通讯地址设置*****************/
#define RF_CHANNEL                11         // 频道 11~26
#define PAN_ID                    0x9527     //网络id 
#define MY_ADDR                   0x000b     //本机地址
#define SEND_ADDR                 0x000a     //目标地址
/**************************************************/
static basicRfCfg_t basicRfConfig;
/*==============变量定义与函数声明================*/
#define D3    P1_0
#define D4    P1_1
#define D5    P1_3
#define D6    P1_4
#define SW1   P1_2
#define SW2   P0_1

unsigned char sys_stat = 0;     //系统当前工作状态
unsigned char dat_Send[32];     //无线数据发送缓存
unsigned char dat_Recv[32];     //无线数据接收缓存
unsigned char len = 0;          //串口接收数据的长度

void Delay(unsigned int t);     //普通延时函数
void Init_Port();               //通用I/O端口初始化函数
void LED_On();                  //D3~D6灯全亮函数
void LED_RunningA();            //D4-D3-D6-D5流水灯函数
void LED_RunningB();            //D5-D6-D3-D4流水灯函数
void Scan_Keys();               //SW1和SW2按键扫描处理函数
void Recv_UR_Data();            //串口数据接收处理函数
void Recv_RF_Data();            //RF无线数据接收处理函数
// 无线RF初始化
void ConfigRf_Init(void)
{
    basicRfConfig.panId       =   PAN_ID;
    basicRfConfig.channel     =   RF_CHANNEL;
    basicRfConfig.myAddr      =   MY_ADDR;
    basicRfConfig.ackRequest  =   TRUE;
    while(basicRfInit(&basicRfConfig) == FAILED);
    basicRfReceiveOn();
}
/********************MAIN************************/
void main(void)
{
    halBoardInit();//选手不得在此函数内添加代码
    ConfigRf_Init();//选手不得在此函数内添加代码

    Init_Port();              //初始化LED灯与按键
    
    while(1)
    {
    /* user code start */ 
      Scan_Keys();            //轮询扫描按键
      Recv_UR_Data();         //接收处理串口数据
      Recv_RF_Data();         //接收无线数据,更新系统状态
      
      switch(sys_stat)        //系统当前状态
      {
        case 0:
          LED_On();           //D3-D6灯全亮
        break;
        
        case 1:
          LED_RunningA();     //D4-D3-D6-D5流水灯
        break;
        
        case 2:
          LED_RunningB();     //D5-D6-D3-D4流水灯
        break;
      }
    /* user code end */
    }
}
/*===============按键扫描处理函数=================*/
void Scan_Keys()
{
  if(SW1 == 0)
  {
    Delay(5);
    if(SW1 == 0)
    {
      dat_Send[0] = 0xa1;
      basicRfSendPacket(SEND_ADDR, dat_Send, 32);
      sys_stat = 2;
      while(SW1 == 0);
    }
  }
  if(SW2 == 0)
  {
    Delay(5);
    if(SW2 == 0)
    {
      dat_Send[0] = 0xa2;
      basicRfSendPacket(SEND_ADDR, dat_Send, 32);
      sys_stat = 0;
      while(SW2 == 0);
    }
  }
}
/*=============串口数据接收处理函数===============*/
void Recv_UR_Data()
{
  len = halUartRxLen();
  if(len > 0)
  {
    len = halUartRead(&dat_Send[2], len);
    dat_Send[1] = len;
    dat_Send[0] = 0xb1;
    basicRfSendPacket(SEND_ADDR, dat_Send, 32);
    len = 0;
  }
}
/*=============无线数据接收处理函数===============*/
void Recv_RF_Data()
{
  if(basicRfPacketIsReady() == TRUE)
  {
    basicRfReceive(dat_Recv, 32, NULL);
    if(dat_Recv[0] == 0xa1)
    {
      sys_stat = 1;
    }
    else if(dat_Recv[0] == 0xb1)
    {
      halUartWrite(&dat_Recv[2], dat_Recv[1]);
    }
  }
}

蓝色Zigbee节点盒核心源码

/*/***************点对点通讯地址设置*****************/
#define RF_CHANNEL                11         // 频道 11~26
#define PAN_ID                    0x9527     //网络id 
#define MY_ADDR                   0x000a     //本机地址
#define SEND_ADDR                 0x000b     //目标地址
/**************************************************/
static basicRfCfg_t basicRfConfig;
/*==============变量定义与函数声明================*/
#define LED1  P1_0
#define LED2  P1_1
#define SW1   P1_2

unsigned char pwm = 0;          //PWM信号变化单位
unsigned char pwm_duty = 0;     //PWM信号占空比
unsigned char pwm_stat = 0;     //PWM信号变化方向
unsigned char sys_stat = 0;     //系统当前工作状态
unsigned char dat_Send[32];     //无线数据发送缓存
unsigned char dat_Recv[32];     //无线数据接收缓存
unsigned char len = 0;          //串口接收数据的长度

void Delay(unsigned int t);     //普通延时函数
void Init_Port();               //通用I/O端口初始化函数
void LED_On();                  //LED1和LED2灯全亮函数
void LED_Changed();             //LED1和LED2交替亮灭函数
void LED_Breath();              //LED1和LED2呼吸灯函数
void Scan_Keys();               //SW1按键扫描处理函数
void Recv_UR_Data();            //串口数据接收处理函数
void Recv_RF_Info();            //RF无线数据接收处理函数
// 无线RF初始化
void ConfigRf_Init(void)
{
    basicRfConfig.panId       =   PAN_ID;
    basicRfConfig.channel     =   RF_CHANNEL;
    basicRfConfig.myAddr      =   MY_ADDR;
    basicRfConfig.ackRequest  =   TRUE;
    while(basicRfInit(&basicRfConfig) == FAILED);
    basicRfReceiveOn();
}
/********************MAIN************************/
void main(void)
{
    halBoardInit();//选手不得在此函数内添加代码
    ConfigRf_Init();//选手不得在此函数内添加代码

    Init_Port();            //初始化LED灯与SW1按键
    
    while(1)
    {
    /* user code start */    
      Scan_Keys();          //轮询扫描按键
      Recv_UR_Data();       //接收处理串口数据
      Recv_RF_Info();       //接收无线数据,更新系统状态
      
      switch(sys_stat)      //系统当前状态
      {
        case 0:
          LED_On();         //LED1和LED2全亮
        break;
        
        case 1:
          LED_Changed();    //LED1和LED2交替亮灭
        break;
        
        case 2:
          LED_Breath();     //LED1和LED2呼吸灯
        break;
      }
    /* user code end */
    }
}
/*===============按键扫描处理函数=================*/
void Scan_Keys()
{
  if(SW1 == 0)
  {
    Delay(100);
    if(SW1 == 0)
    {
      dat_Send[0] = 0xa1;
      basicRfSendPacket(SEND_ADDR, dat_Send, 32);
      sys_stat = 1;
      while(SW1 == 0);
    }
  }
}
/*=============串口数据接收处理函数===============*/
void Recv_UR_Data()
{
  len = halUartRxLen();
  if(len > 0)
  {
    halUartRead(&dat_Send[2], len);
    dat_Send[1] = len;
    dat_Send[0] = 0xb1;
    basicRfSendPacket(SEND_ADDR, dat_Send, 32);
    len = 0;
  }
}
/*=============无线数据接收处理函数===============*/
void Recv_RF_Info()
{
  if(basicRfPacketIsReady() == TRUE)
  {
    basicRfReceive(dat_Recv, 32, NULL);
    if(dat_Recv[0] == 0xa1)
    {
      sys_stat = 2;
    }
    else if(dat_Recv[0] == 0xa2)
    {
      sys_stat = 0;
    }
    else if(dat_Recv[0] == 0xb1)
    {
      halUartWrite(&dat_Recv[2], dat_Recv[1]);
    }
  }
}

注:5元购买完整工程源码。

赞(47)
未经允许不得转载:小蜜蜂笔记 » 【赛题详解】2019年物联网国赛任务三题1-无线通信系统(附解题思路与关键源码)

小蜜蜂笔记 更专业 更方便 更高效

联系我们精品小店