本项目中使用了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里面。
- //--Read DRF1609H Configures --
- drf1609h_readModule();
- HAL_UART_Receive( &huart1, receivedConfigData, 53, 500 );
复制代码- //------------------------------
- void drf1609h_readModule(void)
- {
- drf1609h_sendedIns = sendIns_read;
- HAL_UART_Transmit_DMA( &huart1, readIns, 9 );
- }
复制代码 读取参数完成后,把读取到的参数整理后放入drf1609这个结构体中:以后取用的时候就非常方便了,建议用户不要改这部分代码,直接拷贝使用就好了。
- //---If DRF1609H Error or Read Error ------
- while( readParameterProcess(receivedConfigData, 53) == 0 )
- {
- drf1609h_readModule();
- HAL_UART_Receive( &huart1, receivedConfigData, 53, 500 );
- }
复制代码- //------------------------------
- uint8_t readParameterProcess(uint8_t *inputData, uint16_t inputLen)
- {
- uint8_t result=0;
- uint8_t tempXY=0;
- uint8_t tempRight=0;
- uint8_t i=0;
-
- tempXY = getXY(inputData, inputLen);
-
- if(inputData[0]==0xFA) { tempRight++; }
- if(inputData[1]==0x31) { tempRight++; }
- if(inputData[2]==0x0A) { tempRight++; }
- if(inputData[inputLen-1]==tempXY) { tempRight++; }
-
- if(tempRight==4)
- {
- //------
- drf1609.pointType = inputData[readHeaderLen +0];
- drf1609.PAN_ID = inputData[readHeaderLen +1]*256 + inputData[readHeaderLen +2];
- drf1609.Channel = inputData[readHeaderLen +3];
- drf1609.transferModel = inputData[readHeaderLen +4];
- drf1609.userAddress = inputData[readHeaderLen +5]*256 + inputData[readHeaderLen +6];
- drf1609.X7X8 = inputData[readHeaderLen +7]*256 + inputData[readHeaderLen +8];
- drf1609.uartBraudRate = inputData[readHeaderLen +9];
- drf1609.uartDataBits = inputData[readHeaderLen +10];
- drf1609.uartStopBits = inputData[readHeaderLen +11];
- drf1609.uartParity = inputData[readHeaderLen +12];
- drf1609.X13X14 = inputData[readHeaderLen +13]*256 + inputData[readHeaderLen +14];
- drf1609.antennaSelect = inputData[readHeaderLen +15];
-
- //-------
- for(i=0; i<8; i++)
- {
- drf1609.macAddress<i> = inputData[readHeaderLen +16 +i];
- </i>}
-
- //--------
- drf1609.prePointType = inputData[readHeaderLen +24];
- drf1609.prePAN_ID = inputData[readHeaderLen +25]*256 + inputData[readHeaderLen +26];
- drf1609.preChannel = inputData[readHeaderLen +27];
- drf1609.preTransferModel = inputData[readHeaderLen +28];
- drf1609.preUserAddress = inputData[readHeaderLen +29]*256 + inputData[readHeaderLen +30];
- drf1609.X31X32 = inputData[readHeaderLen +31]*256 + inputData[readHeaderLen +32];
- drf1609.preUartBraudRate = inputData[readHeaderLen +33];
- drf1609.preUartDataBits = inputData[readHeaderLen +34];
- drf1609.preUartStopBits = inputData[readHeaderLen +35];
- drf1609.preUartParity = inputData[readHeaderLen +36];
- drf1609.X37X38 = inputData[readHeaderLen +37]*256 + inputData[readHeaderLen +38];
- drf1609.preAntennaSelect = inputData[readHeaderLen +39];
-
- //-----------
- drf1609.shortAddress = inputData[readHeaderLen +40]*256 + inputData[readHeaderLen +41];
- drf1609.X42 = inputData[readHeaderLen +42];
- drf1609.isSecurity = inputData[readHeaderLen +43];
-
- for(i=0; i<4; i++)
- {
- drf1609.securityCode = inputData[readHeaderLen +44 +i];
- }
- result =1;
- }
- return result;
- }
复制代码
接着比较读出来的节点类型与要设置的节点类型是否一致,如果不一致的话,就重新写入要设置的节点类型: - if( drf1609H_setPontType != drf1609H_readPointType )
复制代码
写的过程:
1,产生写入参数
2,写入
3,接收回复的参数,看看写入是否正确
- getWriteIns(drf1609);
- drf1609h_writeModule();
- HAL_UART_Receive( &huart1, receivedConfigData, 5, 500 );
复制代码
写入正确以后,则重启模块(注意:DRF1609H的写入参数生效,都需要重启),这里是用一个IO口,控制DRF1609H的RESET脚拉低重启。
- if( is_InsBack(receivedConfigData, 5) )
- {
- if(receivedConfigData[2] == 0x0A)
- {
- drf1609h_reset();
- HAL_Delay(2000);
- drf1609h_status = drf1609h_powerOn;
- }
- else
- {
- errorStart=1;
- }
- }
- else
- {
- errorStart=1;
- }
复制代码
需要注意的是,getWriteIns(drf1609),这个函数是把drf1609结构体,直接变换成写入指令,建议用户不要修改这部分,直接拷贝使用
- //---------------------------------------------------
- void getWriteIns(_zigbeeParameters inputParameter)
- {
- uint8_t i=0;
- uint8_t tempXY=0;
-
- writeIns[0]= 0xFC;
- writeIns[1]= 0x27;
- writeIns[2]= 0x07;
-
- writeIns[writeHeaderLen +0]= inputParameter.pointType;
- writeIns[writeHeaderLen +1]= (inputParameter.PAN_ID & 0xFF00)>>8;
- writeIns[writeHeaderLen +2]= inputParameter.PAN_ID & 0x00FF;
- writeIns[writeHeaderLen +3]= inputParameter.Channel;
- writeIns[writeHeaderLen +4]= inputParameter.transferModel;
- writeIns[writeHeaderLen +5]= (inputParameter.userAddress & 0xFF00)>>8;
- writeIns[writeHeaderLen +6]= inputParameter.userAddress & 0x00FF;
- writeIns[writeHeaderLen +7]= (inputParameter.X7X8 & 0xFF00)>>8;
- writeIns[writeHeaderLen +8]= inputParameter.X7X8 & 0x00FF;
- writeIns[writeHeaderLen +9]= inputParameter.uartBraudRate;
- writeIns[writeHeaderLen +10]= inputParameter.uartDataBits;
- writeIns[writeHeaderLen +11]= inputParameter.uartStopBits;
- writeIns[writeHeaderLen +12]= inputParameter.uartParity;
- writeIns[writeHeaderLen +13]= (inputParameter.X13X14 & 0xFF00)>>8;
- writeIns[writeHeaderLen +14]= inputParameter.X13X14 & 0x00FF;
- writeIns[writeHeaderLen +15]= inputParameter.antennaSelect;
-
- writeIns[writeHeaderLen +16]= inputParameter.prePointType;
- writeIns[writeHeaderLen +17]= (inputParameter.prePAN_ID & 0xFF00)>>8;
- writeIns[writeHeaderLen +18]= inputParameter.prePAN_ID & 0x00FF;
- writeIns[writeHeaderLen +19]= inputParameter.preChannel;
- writeIns[writeHeaderLen +20]= inputParameter.preTransferModel;
- writeIns[writeHeaderLen +21]= (inputParameter.preUserAddress & 0xFF00)>>8;
- writeIns[writeHeaderLen +22]= inputParameter.preUserAddress & 0x00FF;
- writeIns[writeHeaderLen +23]= (inputParameter.X31X32 & 0xFF00)>>8; //--AS ReadParameter's X31 X32
- writeIns[writeHeaderLen +24]= inputParameter.X31X32 & 0x00FF; //--AS ReadParameter's X31 X32
- writeIns[writeHeaderLen +25]= inputParameter.preUartBraudRate;
- writeIns[writeHeaderLen +26]= inputParameter.preUartDataBits;
- writeIns[writeHeaderLen +27]= inputParameter.preUartStopBits;
- writeIns[writeHeaderLen +28]= inputParameter.preUartParity;
- writeIns[writeHeaderLen +29]= (inputParameter.X37X38 & 0xFF00)>>8; //--AS ReadParameter's X37 X38
- writeIns[writeHeaderLen +30]= inputParameter.X37X38 & 0x00FF; //--AS ReadParameter's X37 X38
- writeIns[writeHeaderLen +31]= inputParameter.preAntennaSelect;
- writeIns[writeHeaderLen +32]= 0x1;
- writeIns[writeHeaderLen +33]= inputParameter.isSecurity;
-
- for(i=0; i<4; i++)
- {
- writeIns[writeHeaderLen +34 +i]= inputParameter.securityCode<span style="font-style: italic;"><span style="font-style: normal;">;
- }
-
- tempXY = getXY(writeIns, writeInsLen);
-
- writeIns[writeInsLen-1]= tempXY;
- }</span></span>
复制代码
2,检测节点是否加入网络
检测节点是否加入网络,我们这里使用了读取DRF1609H节点信号强度指令,如果读取信号强度成功(回复的数据是正确的),则表明DRF1609H已经加入了网络并且与Coordinator通讯正常。
这个函数用来检测DRF1609H是否加入了网络,加入则回复1,没有则回复0:
注意:这里是检测10次,没有加入也回复1,主要考虑在低功耗情况下,如果Coordinator没有开机,如果节点一直检测,则对耗电不利,用户应根据实际情况修改使用。
- uint8_t drf1609h_isJoinedNet()
- 1
- //----------------------
- uint8_t drf1609h_isJoinedNet()
- {
- uint8_t result=0;
- uint8_t i=0;
- //MX_USART1_UART_Init();
- //HAL_Delay(10);
- for(i=0; i<8; i++)
- {
- receivedSignalData<span style="font-style: italic;"><span style="font-style: normal;">=0;
- }
- drf1609h_requestSignalIndex();
- HAL_UART_Receive( &huart1, receivedSignalData, 8, 500 );
- HAL_Delay(1000);
- if( checkSignalData(receivedSignalData, 8) )
- {
- result=1;
- receivedSignalData[8] = drf1609.pointType;
- HAL_UART_Transmit_DMA( &huart1, receivedSignalData, 9 );
- }
- else
- {
- haveTryToJoinTimers++;
- if(haveTryToJoinTimers >= maxJoinTimers)
- {
- result=1;
- }
- else
- {
- result=0;
- }
- }
- return result;
- }</span></span>
复制代码
检测的过程:
1,发送读取信号强度指令
2,等待接收回复数据
3,如果接收回复数据成功(已经加入网络),这里将收到的数据加上自己的节点类型发送给Coordinator,通知节点已经加入成功
- drf1609h_requestSignalIndex();
- HAL_UART_Receive( &huart1, receivedSignalData, 8, 500 );
- HAL_Delay(1000);
- if( checkSignalData(receivedSignalData, 8) )
- {
- result=1;
- receivedSignalData[8] = drf1609.pointType;
- HAL_UART_Transmit_DMA( &huart1, receivedSignalData, 9 );
- }
复制代码
3,启动节点自动加入网络
如果连按三次DRF1609H的Function按键,则开始自动扫描,如果扫描到Coordinator,则可以自动加入网络,并从Coordinator处获得“给Router预设的参数”,所以节点是不要设置的,我们节点的板子上也没有把DRF1609H的串口留出来,而是通过连按三次按键,自动加入网络,自动取得参数。
1,检测DRF1609H是否加入网络,用的是读取信号强度的指令
2,如果没有加入网络,则启动自动加入网络
3,启动后,等待12秒,再读取信号强度,判断是否加入了网络
注意,板子上有按键,如果是低功耗模式,建议不要启动这个功能,用按键手工加入网络,如果Coordinator没开机,一直扫描网络,会很快耗光电池。
- //-- Do 5 timers get Signal Index ----//
- for(i=0; i<5; i++)
- {
- drf1609h_requestSignalIndex();
- HAL_UART_Receive( &huart1, receivedSignalData, 8, 500 );
- HAL_Delay(500);
- if( checkSignalData(receivedSignalData, 8) )
- {
- tempVal++;
- i=5;
- }
- else
- {
- notGetSignalVal++;
- }
- }
复制代码- drf1609h_autoJoinNet_Start();
- HAL_Delay(12000);
复制代码
进去自动加入网络的代码看看,其实就是模拟三次按键:
开始以后,DRF1609H上的2个灯会快闪,观察到一个灯灭,一个灯慢闪以后,说明已经加入网络。
- //---------------------------------------
- /* This Simulate Function Key to start
- * point auto join net
- * ____ ______ ______ ______
- * |__| |__| |__|
- *
- * 120 200 120 200 120 200
- *
- * ----------------------------------*/
- void drf1609h_autoJoinNet_Start()
- {
- uint8_t i=0;
- set_autoJoinNetPin_output();
- set_autoJoinNetPin_out_1();
- HAL_Delay(100);
- for(i=0; i<3; i++)
- {
- set_autoJoinNetPin_out_0();
- HAL_Delay(120);
- set_autoJoinNetPin_out_1();
- HAL_Delay(200);
- }
- set_autoJoinNetPin_input();
- }
复制代码
4,DRF1609H的相关指令
主要有读取参数、读取信号强度、写入参数等指令,项目里面都已经列出来了
如果需要增加其它的功能,要参考DRF1609H的说明书
- uint8_t linkIns[9] = {0xFC, 0x06, 0x04, 0x44, 0x54, 0x4B, 0x52, 0x46, 0x81}; //---INS01
- uint8_t restartIns[9] = {0xFC, 0x06, 0x06, 0x44, 0x54, 0x4B, 0xAA, 0xBB, 0x50}; //---INS02
- uint8_t readIns[9] = {0xFC, 0x06, 0x0E, 0x44, 0x54, 0x4B, 0x52, 0x46, 0x8B}; //---INS05
- uint8_t writeIns[42]; //--INS06
- uint8_t requestSignalIns[9] = {0xFC, 0x06, 0x0C, 0x44, 0x54, 0x4B, 0x52, 0x46, 0x89}; //--INS08
复制代码
|