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

关键词:CubeMX,CubeIDE,STM32G031C8T6,AHT10,DRF1609H

本项目中使用了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];
		}
		
		//--------
		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[i] = 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[i];
	}
	
	tempXY = getXY(writeIns, writeInsLen);
	
	writeIns[writeInsLen-1]= tempXY;	
}

2,检测节点是否加入网络

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

uint8_t  drf1609h_isJoinedNet()
//----------------------
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[i]=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;
}

检测的过程:
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

在这里插入图片描述

发布了8 篇原创文章 · 获赞 7 · 访问量 558

猜你喜欢

转载自blog.csdn.net/yihua2009/article/details/104291554