你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32G031无线温湿度仪开源项目 -4,Zigbee模块(DRF1609H)的初始化

[复制链接]
STMCU小助手 发布时间:2021-11-13 22:00
本项目中使用了Zigbee模块(DRF1609H),作为无线数据传输使用,初始化DRF1609H主要涉及以下几个方面的内容:
1,设置节点的类型,可以设置为:Router、End Device。Zigbee网络有3种类型的节点:Coordinator、Router、End Device,Cordinator接在电脑上面收集数据,我们这里是采集节点,所以只设置为Router或End Device。
2,检测节点是否加入了网络
3,如果节点没有加入网络,则启动自动扫描加入网络

1,节点类型的设置:
首先读取DRF1609H的参数:G031向DRF1609H发送读取参数指令,发完参数后,有一个500MS的超时等待参数的回复,参数回复总共是53个字节,放在receiveConfigData里面。

  1.         //--Read DRF1609H Configures --
  2.         drf1609h_readModule();
  3.         HAL_UART_Receive( &huart1, receivedConfigData, 53, 500 );
复制代码
  1. //------------------------------
  2. void  drf1609h_readModule(void)
  3. {
  4.         drf1609h_sendedIns = sendIns_read;
  5.         HAL_UART_Transmit_DMA( &huart1, readIns, 9 );
  6. }
复制代码
读取参数完成后,把读取到的参数整理后放入drf1609这个结构体中:以后取用的时候就非常方便了,建议用户不要改这部分代码,直接拷贝使用就好了。

  1.         //---If DRF1609H Error or Read Error ------
  2.         while( readParameterProcess(receivedConfigData, 53) == 0 )
  3.         {
  4.                 drf1609h_readModule();
  5.                 HAL_UART_Receive( &huart1, receivedConfigData, 53, 500 );
  6.         }
复制代码
  1. //------------------------------
  2. uint8_t  readParameterProcess(uint8_t  *inputData,  uint16_t  inputLen)
  3. {
  4.         uint8_t  result=0;

  5.         uint8_t  tempXY=0;
  6.         uint8_t  tempRight=0;
  7.         uint8_t  i=0;
  8.         
  9.         tempXY = getXY(inputData, inputLen);
  10.         
  11.         if(inputData[0]==0xFA) { tempRight++; }
  12.         if(inputData[1]==0x31) { tempRight++; }
  13.         if(inputData[2]==0x0A) { tempRight++; }
  14.         if(inputData[inputLen-1]==tempXY) { tempRight++; }
  15.         
  16.         if(tempRight==4)
  17.         {
  18.                 //------
  19.                 drf1609.pointType = inputData[readHeaderLen +0];
  20.                 drf1609.PAN_ID = inputData[readHeaderLen +1]*256 + inputData[readHeaderLen +2];
  21.                 drf1609.Channel = inputData[readHeaderLen +3];
  22.                 drf1609.transferModel = inputData[readHeaderLen +4];
  23.                 drf1609.userAddress = inputData[readHeaderLen +5]*256 + inputData[readHeaderLen +6];
  24.                 drf1609.X7X8 = inputData[readHeaderLen +7]*256 + inputData[readHeaderLen +8];
  25.                 drf1609.uartBraudRate = inputData[readHeaderLen +9];
  26.                 drf1609.uartDataBits = inputData[readHeaderLen +10];
  27.                 drf1609.uartStopBits = inputData[readHeaderLen +11];
  28.                 drf1609.uartParity = inputData[readHeaderLen +12];
  29.                 drf1609.X13X14 = inputData[readHeaderLen +13]*256 + inputData[readHeaderLen +14];
  30.                 drf1609.antennaSelect = inputData[readHeaderLen +15];
  31.                
  32.                 //-------
  33.                 for(i=0; i<8; i++)
  34.                 {
  35.                         drf1609.macAddress<i> = inputData[readHeaderLen +16 +i];
  36.                 </i>}
  37.                
  38.                 //--------
  39.                 drf1609.prePointType = inputData[readHeaderLen +24];
  40.                 drf1609.prePAN_ID = inputData[readHeaderLen +25]*256 + inputData[readHeaderLen +26];
  41.                 drf1609.preChannel = inputData[readHeaderLen +27];
  42.                 drf1609.preTransferModel = inputData[readHeaderLen +28];
  43.                 drf1609.preUserAddress = inputData[readHeaderLen +29]*256 + inputData[readHeaderLen +30];
  44.                 drf1609.X31X32 = inputData[readHeaderLen +31]*256 + inputData[readHeaderLen +32];
  45.                 drf1609.preUartBraudRate = inputData[readHeaderLen +33];
  46.                 drf1609.preUartDataBits = inputData[readHeaderLen +34];
  47.                 drf1609.preUartStopBits = inputData[readHeaderLen +35];
  48.                 drf1609.preUartParity = inputData[readHeaderLen +36];
  49.                 drf1609.X37X38 = inputData[readHeaderLen +37]*256 + inputData[readHeaderLen +38];
  50.                 drf1609.preAntennaSelect = inputData[readHeaderLen +39];
  51.                
  52.                 //-----------
  53.                 drf1609.shortAddress = inputData[readHeaderLen +40]*256 + inputData[readHeaderLen +41];
  54.                 drf1609.X42 = inputData[readHeaderLen +42];
  55.                 drf1609.isSecurity = inputData[readHeaderLen +43];
  56.                
  57.                 for(i=0; i<4; i++)
  58.                 {
  59.                         drf1609.securityCode = inputData[readHeaderLen +44 +i];
  60.                 }

  61.                 result =1;
  62.         }

  63.         return result;
  64. }
复制代码

接着比较读出来的节点类型与要设置的节点类型是否一致,如果不一致的话,就重新写入要设置的节点类型:  
  1.   if( drf1609H_setPontType != drf1609H_readPointType )
复制代码

写的过程:
1,产生写入参数
2,写入
3,接收回复的参数,看看写入是否正确

  1.                 getWriteIns(drf1609);

  2.                 drf1609h_writeModule();
  3.                 HAL_UART_Receive( &huart1, receivedConfigData, 5, 500 );
复制代码

写入正确以后,则重启模块(注意:DRF1609H的写入参数生效,都需要重启),这里是用一个IO口,控制DRF1609H的RESET脚拉低重启。
  1. if( is_InsBack(receivedConfigData, 5) )
  2.                 {
  3.                         if(receivedConfigData[2] == 0x0A)
  4.                         {
  5.                                 drf1609h_reset();
  6.                                 HAL_Delay(2000);
  7.                                 drf1609h_status = drf1609h_powerOn;
  8.                         }
  9.                         else
  10.                         {
  11.                                 errorStart=1;
  12.                         }
  13.                 }
  14.                 else
  15.                 {
  16.                         errorStart=1;
  17.                 }
复制代码

需要注意的是,getWriteIns(drf1609),这个函数是把drf1609结构体,直接变换成写入指令,建议用户不要修改这部分,直接拷贝使用

  1. //---------------------------------------------------
  2. void  getWriteIns(_zigbeeParameters  inputParameter)
  3. {
  4.         uint8_t   i=0;
  5.         uint8_t  tempXY=0;
  6.         
  7.         writeIns[0]= 0xFC;
  8.         writeIns[1]= 0x27;
  9.         writeIns[2]= 0x07;
  10.         
  11.         writeIns[writeHeaderLen +0]= inputParameter.pointType;
  12.         writeIns[writeHeaderLen +1]= (inputParameter.PAN_ID & 0xFF00)>>8;
  13.         writeIns[writeHeaderLen +2]= inputParameter.PAN_ID & 0x00FF;
  14.         writeIns[writeHeaderLen +3]= inputParameter.Channel;
  15.         writeIns[writeHeaderLen +4]= inputParameter.transferModel;
  16.         writeIns[writeHeaderLen +5]= (inputParameter.userAddress & 0xFF00)>>8;
  17.         writeIns[writeHeaderLen +6]= inputParameter.userAddress & 0x00FF;
  18.         writeIns[writeHeaderLen +7]= (inputParameter.X7X8 & 0xFF00)>>8;
  19.         writeIns[writeHeaderLen +8]= inputParameter.X7X8 & 0x00FF;
  20.         writeIns[writeHeaderLen +9]= inputParameter.uartBraudRate;
  21.         writeIns[writeHeaderLen +10]= inputParameter.uartDataBits;
  22.         writeIns[writeHeaderLen +11]= inputParameter.uartStopBits;
  23.         writeIns[writeHeaderLen +12]= inputParameter.uartParity;
  24.         writeIns[writeHeaderLen +13]= (inputParameter.X13X14 & 0xFF00)>>8;
  25.         writeIns[writeHeaderLen +14]= inputParameter.X13X14 & 0x00FF;
  26.         writeIns[writeHeaderLen +15]= inputParameter.antennaSelect;
  27.         
  28.         writeIns[writeHeaderLen +16]= inputParameter.prePointType;
  29.         writeIns[writeHeaderLen +17]= (inputParameter.prePAN_ID & 0xFF00)>>8;
  30.         writeIns[writeHeaderLen +18]= inputParameter.prePAN_ID & 0x00FF;
  31.         writeIns[writeHeaderLen +19]= inputParameter.preChannel;
  32.         writeIns[writeHeaderLen +20]= inputParameter.preTransferModel;
  33.         writeIns[writeHeaderLen +21]= (inputParameter.preUserAddress & 0xFF00)>>8;
  34.         writeIns[writeHeaderLen +22]= inputParameter.preUserAddress & 0x00FF;
  35.         writeIns[writeHeaderLen +23]= (inputParameter.X31X32 & 0xFF00)>>8;  //--AS ReadParameter's X31 X32
  36.         writeIns[writeHeaderLen +24]= inputParameter.X31X32 & 0x00FF;       //--AS ReadParameter's X31 X32
  37.         writeIns[writeHeaderLen +25]= inputParameter.preUartBraudRate;
  38.         writeIns[writeHeaderLen +26]= inputParameter.preUartDataBits;
  39.         writeIns[writeHeaderLen +27]= inputParameter.preUartStopBits;
  40.         writeIns[writeHeaderLen +28]= inputParameter.preUartParity;
  41.         writeIns[writeHeaderLen +29]= (inputParameter.X37X38 & 0xFF00)>>8;  //--AS ReadParameter's X37 X38
  42.         writeIns[writeHeaderLen +30]= inputParameter.X37X38 & 0x00FF;       //--AS ReadParameter's X37 X38
  43.         writeIns[writeHeaderLen +31]= inputParameter.preAntennaSelect;
  44.         writeIns[writeHeaderLen +32]= 0x1;
  45.         writeIns[writeHeaderLen +33]= inputParameter.isSecurity;
  46.         
  47.         for(i=0; i<4; i++)
  48.         {
  49.                 writeIns[writeHeaderLen +34 +i]= inputParameter.securityCode<span style="font-style: italic;"><span style="font-style: normal;">;
  50.         }
  51.         
  52.         tempXY = getXY(writeIns, writeInsLen);
  53.         
  54.         writeIns[writeInsLen-1]= tempXY;        
  55. }</span></span>
复制代码

2,检测节点是否加入网络
检测节点是否加入网络,我们这里使用了读取DRF1609H节点信号强度指令,如果读取信号强度成功(回复的数据是正确的),则表明DRF1609H已经加入了网络并且与Coordinator通讯正常。
这个函数用来检测DRF1609H是否加入了网络,加入则回复1,没有则回复0:
注意:这里是检测10次,没有加入也回复1,主要考虑在低功耗情况下,如果Coordinator没有开机,如果节点一直检测,则对耗电不利,用户应根据实际情况修改使用。

  1. uint8_t  drf1609h_isJoinedNet()
  2. 1
  3. //----------------------
  4. uint8_t  drf1609h_isJoinedNet()
  5. {
  6.         uint8_t   result=0;
  7.         uint8_t   i=0;

  8.         //MX_USART1_UART_Init();
  9.         //HAL_Delay(10);
  10.         for(i=0; i<8; i++)
  11.         {
  12.                 receivedSignalData<span style="font-style: italic;"><span style="font-style: normal;">=0;
  13.         }

  14.         drf1609h_requestSignalIndex();
  15.         HAL_UART_Receive( &huart1, receivedSignalData, 8, 500 );
  16.         HAL_Delay(1000);

  17.         if( checkSignalData(receivedSignalData, 8) )
  18.         {
  19.                 result=1;
  20.                 receivedSignalData[8] = drf1609.pointType;
  21.                 HAL_UART_Transmit_DMA( &huart1, receivedSignalData, 9 );
  22.         }
  23.         else
  24.         {
  25.                 haveTryToJoinTimers++;
  26.                 if(haveTryToJoinTimers >= maxJoinTimers)
  27.                 {
  28.                         result=1;
  29.                 }
  30.                 else
  31.                 {
  32.                         result=0;
  33.                 }
  34.         }


  35.         return   result;
  36. }</span></span>
复制代码

检测的过程:
1,发送读取信号强度指令
2,等待接收回复数据
3,如果接收回复数据成功(已经加入网络),这里将收到的数据加上自己的节点类型发送给Coordinator,通知节点已经加入成功

  1.         drf1609h_requestSignalIndex();
  2.         HAL_UART_Receive( &huart1, receivedSignalData, 8, 500 );
  3.         HAL_Delay(1000);

  4.         if( checkSignalData(receivedSignalData, 8) )
  5.         {
  6.                 result=1;
  7.                 receivedSignalData[8] = drf1609.pointType;
  8.                 HAL_UART_Transmit_DMA( &huart1, receivedSignalData, 9 );
  9.         }
复制代码

3,启动节点自动加入网络
如果连按三次DRF1609H的Function按键,则开始自动扫描,如果扫描到Coordinator,则可以自动加入网络,并从Coordinator处获得“给Router预设的参数”,所以节点是不要设置的,我们节点的板子上也没有把DRF1609H的串口留出来,而是通过连按三次按键,自动加入网络,自动取得参数。
1,检测DRF1609H是否加入网络,用的是读取信号强度的指令
2,如果没有加入网络,则启动自动加入网络
3,启动后,等待12秒,再读取信号强度,判断是否加入了网络
注意,板子上有按键,如果是低功耗模式,建议不要启动这个功能,用按键手工加入网络,如果Coordinator没开机,一直扫描网络,会很快耗光电池。

  1.         //-- Do 5 timers get Signal Index ----//
  2.         for(i=0; i<5; i++)
  3.         {
  4.                 drf1609h_requestSignalIndex();
  5.                 HAL_UART_Receive( &huart1, receivedSignalData, 8, 500 );
  6.                 HAL_Delay(500);

  7.                 if( checkSignalData(receivedSignalData, 8) )
  8.                 {
  9.                         tempVal++;
  10.                         i=5;
  11.                 }
  12.                 else
  13.                 {
  14.                         notGetSignalVal++;
  15.                 }
  16.         }
复制代码
  1.             drf1609h_autoJoinNet_Start();
  2.             HAL_Delay(12000);
复制代码

进去自动加入网络的代码看看,其实就是模拟三次按键:
开始以后,DRF1609H上的2个灯会快闪,观察到一个灯灭,一个灯慢闪以后,说明已经加入网络。

  1. //---------------------------------------
  2. /*   This Simulate Function Key to start
  3. *   point auto join net
  4. *   ____    ______    ______    ______
  5. *       |__|      |__|      |__|
  6. *
  7. *       120  200  120  200  120  200
  8. *
  9. *   ----------------------------------*/
  10. void  drf1609h_autoJoinNet_Start()
  11. {
  12.         uint8_t  i=0;

  13.         set_autoJoinNetPin_output();
  14.         set_autoJoinNetPin_out_1();
  15.         HAL_Delay(100);

  16.         for(i=0; i<3; i++)
  17.         {
  18.                 set_autoJoinNetPin_out_0();
  19.                 HAL_Delay(120);

  20.                 set_autoJoinNetPin_out_1();
  21.                 HAL_Delay(200);
  22.         }

  23.         set_autoJoinNetPin_input();
  24. }
复制代码

4,DRF1609H的相关指令
主要有读取参数、读取信号强度、写入参数等指令,项目里面都已经列出来了
如果需要增加其它的功能,要参考DRF1609H的说明书

  1. uint8_t    linkIns[9] = {0xFC, 0x06, 0x04, 0x44, 0x54, 0x4B, 0x52, 0x46, 0x81};      //---INS01
  2. uint8_t    restartIns[9] = {0xFC, 0x06, 0x06, 0x44, 0x54, 0x4B, 0xAA, 0xBB, 0x50};   //---INS02
  3. uint8_t    readIns[9] = {0xFC, 0x06, 0x0E, 0x44, 0x54, 0x4B, 0x52, 0x46, 0x8B};      //---INS05
  4. uint8_t    writeIns[42];   //--INS06
  5. uint8_t    requestSignalIns[9] = {0xFC, 0x06, 0x0C, 0x44, 0x54, 0x4B, 0x52, 0x46, 0x89};    //--INS08
复制代码

20200213140400362.jpg

收藏 评论0 发布时间:2021-11-13 22:00

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版