基于stm32f103zet6之NRF905无线模块的学习

又是因为比赛的需要,所以用起了这个无线模块,模块也是因为凑巧在同学那里搞来的,他说他现在不用,所以我就拿来主义,练练手嘛!昨天下午开始研究了,昨晚测试的时候发现有些问题,今天上午有课,没办法,值得下午来调试调试了。所幸调试通过了,谢天谢地~~~~好的,既然这样,那么就总结一下这个无线模块需要注意的地方吧,毕竟以后可是能够拿来做遥控汽车的 嘿嘿。。。。

首先给大家传一份技术参考手册,这是中文的,但是有些地方如果你觉得有问题,那么请对照这英文手册看,我就是这样干的!

地址在这里

一、硬件

nrf905这个芯片我们就不谈了,涉及到高频、射频是比较复杂,主要针对如何使用这个模块谈一谈


这是涉及到我们编程的引脚图, 其中uclk在这里不用,下面请看管脚图


总结一下这个管脚表的比较重要的信息如下:

1、nrf905和单片机通信使用的是SPI协议,我这里用的是软件模拟spi,硬件spi有其他用途

2、电源3.3V没有问题,IO口电压完全兼容匹配,输出电流也是没有问题的

3、CD是载波检测信号,意思是当我们的模块作为接收的时候,一旦它接收到发射模块同一个频段的信号时,该引脚会被nrf905置高,平常为低!

4、AM是地址匹配的意思,当作为接收模块的时候,当接收地址和发射地址匹配的时候,那么该引脚会被nrf905置高,平常为低!

5、DR表示数据接收或者发送成功!当一个正确的数据包接收完毕, RF905自动移去字校验位,然后把DR引脚置高,平常为低!

注意了:CD、AM、DR3个引脚的状态在我们调试的时候是非常重要的,所以充分利用这几个引脚的功能!

硬件方面需要注意的地方我们已经说完了,接下来分析我的程序!

二、软件

首先是发送流程:

1、当微控制器有数据要发送时,通过SPI协议将地址和要发送的数据送传给RF905,SPI接口的速率在通信协议和器件配置时确定;  
2、微控制器置高TRX_CE和TX_EN,这就设置为了发送数据模式  
3、RF905发送流程:
(1) 射频寄存器自动开启;  
(2) 数据打包(加字头和CRC校验
(3) 发送数据包;  
(4) 当数据发送完成,

(1)(2)俩步自动完成!

4、AUTO_RETRAN被置高,RF905不断重发,直到TRX_
5、当TRX_CE被置低,RF905发送过程完成,自动进入空闲模式。 
注意:ShockBurstTM工作模式保证,一旦发送数据的过程开始,无论
TRX_EN和TX_EN引脚是高或低,发送过程都会被处理完。只有在前一
个数据包被发送完毕,RF905才能接受下一个发送数据包。

然后是接收流程:

1、当 TRX_CE 为高、TX_EN 为低时,RF905 进入 ShockBurstTM 接收模式; 
2、650us 后,RF905 不断监测,等待接收数据;  
3、当 RF905 检测到同一 频段的载波时,载波检测引脚被置高;  
4、当接收到一个相匹配的地址,AM 引脚被置高;  
5、当一个正确的数据包接收完毕, RF905 自动移去字头、地址和 CRC校验位,然后把 DR 引脚置高  
6、微控制器把 TRX_CE 置低,nRF905 进入空闲模式;  
7、 微控制器通过 SPI 口,以一定的速率把数据移到微控制器内;  
8、 当所有的数据接收完毕,nRF905 把 DR 引脚和 AM 引脚置低;  
9、nRF905 此时可以进入 ShockBu rstTM 接收模式、ShockBurstTM 发送模式或关机模式。  当正在接收一个数据包时,TRX_CE 或 TX_EN 引脚的状态发生改变,
RF905 立即把其工作模式改变,数据包则丢失。

需要注意的是:我们设置接收模式的时候,是需要先把数据写入nrf905模块,然后才使能发送引脚的!!!

接下来就是拿具体的程序来分析了

A.首先看我的主函数,很简单

int main(void)
{
	//初始化系统定时器
	SysTick_Init();
	USART1_Config();
	
	NRF905_Init();
	NRF905_Config();
	SetTxMode();
	while(1)
	{
		TxPacket(TxBuf);
		Delay_ms(2000);
	}
}
注意这个模式

B.然后就是这个配置NRF905的函数,这个可是关键啊,具体数据的选择,最好是能看一下芯片手册,这里我把代码贴出来

/**************************************************************************************
* 名    称: NRF905_Init
* 功    能: 配置NRF905寄存器
* 参    数: 无
* 调用方式:NRF905_Init();
* 返 回 值:无
**************************************************************************************/
void NRF905_Config(void)
{
	u8 i;
	NRF905_CSN_L;								// Spi enable for write a spi command
	NRF905_SPI_Write_Byte(WC);						// Write config command写放配置命令
	for (i = 0;i < RxTxConf.n; i++)						// Write configration words  写放配置字
	{
	   NRF905_SPI_Write_Byte(RxTxConf.buf[i]);
	}
	for(i = 0; i < 10; i ++)
	{
		printf(" %x \r",RxTxConf.buf[i]);
	}
	NRF905_CSN_H;								// Disable Spi
}
其实简单来说给它发的内容就是:

/**************************************************************************************
* 名    称: 配置寄存器中的内容!
**************************************************************************************/
RFConfig RxTxConf ={10,
	0x4c,	//CH_NO[7:0] 连同字节 1 的 CH_NO[8]和 HFREQ_PLL 控制 905 的载波频段 433MHZ
	0x0c, //7,6:no use;5:自动重发=0;4:接收灵敏度降低=0;3,2:发射功率=10dBm;1:433MHz;CH_NO[8]=0
	0x44, //7:no use;6,5,4:发送地址宽度4;3:no use;2,1,0:接收地址宽度4
	0x20, //7,6 no use;5-0:接收数据宽度32
	0x20, //7,6 no use;5-0:发送数据宽度32
	0xcc, //接收地址字节0(设备ID)
	0xcc, //接收地址字节1(设备ID)
	0xcc, //接收地址字节2(设备ID)
	0xcc, //接收地址字节3(设备ID)
	0x58	//7:CRC模式8位;6:CRC校验许可;5,4,3:011表示16MHz;2:UP_CLK_EN=0没有外部时钟;1,0:外部时钟频率	
};
这就是根据寄存器的格式含义来的,其实也没有什么好说的,但是我总是怀疑芯片手册上有些问题,那个应该是433.0MHZ

C.接下来看我们是怎么实现发送数据的吧,我把我的代码贴出来,然后对着分析就好了。

/**************************************************************************************
* 名    称: TxPacket
* 功    能: 发送数据包
* 参    数: 需要发送的内容
* 调用方式:TxPacket();
* 返 回 值: MISO的值
**************************************************************************************/
void TxPacket(u8 *TxBuf)
{
	u8 i;			
	NRF905_CSN_L;						// 使能SPI
	NRF905_SPI_Write_Byte(WTP);				// Write payload command
	for (i=0;i<32;i++)
	{
		NRF905_SPI_Write_Byte(TxBuf[i]);		// Write 32 bytes Tx data
	}
	for(i = 0; i < 32;i ++)
	{
		printf("%x \r",TxBuf[i]);
	}
	NRF905_CSN_H;						// Spi disable		
	Delay_us(2);				
	NRF905_CSN_L;						// Spi enable for write a spi command	
	NRF905_SPI_Write_Byte(WTA);				// Write address command
	for (i=0;i<4;i++)					// Write 4 bytes address
	{
		NRF905_SPI_Write_Byte(RxTxConf.buf[i+5]);
	}
	for(i = 0; i < 4;i ++)
	{
		printf("%x \r",RxTxConf.buf[i+5]);
	}
	NRF905_CSN_H;						// Spi disable
	NRF905_TRX_CE_H;					// Set TRX_CE high,start Tx data transmission	先写数据然后开启发送
 	Delay_ms(100);						//记得给反应时间
	while(!DR_read())  	
	{
		printf("DATA Send failed!!!\n");
	}
	printf("DATA send success !!!\n");
	NRF905_TRX_CE_L;					// Set TRX_CE low
}

上述的printf函数都是我加上的打印函数,方便调试的!

大家可能好奇之前的模式设置是不是出问题了,心想,当设置为发送的时候应该是两个都选择为高啊,但是这里要告诉你,传输数据的时候,我是这样理解的,选择模式的时候

先将EN失能。然后当我们通过SPI写入了数据之后才使用这句

	NRF905_TRX_CE_H;			// Set TRX_CE high,start Tx data transmission	先写数据然后开启发送
这样就是为了消除干扰吧,我是这样想的。

D.最后贴上部分驱动函数

/**************************************************************************************
* 名    称: SetTxMode
* 功    能: 设置NRF905发送状态
* 参    数: 无
* 调用方式:SetTxMode();
* 返 回 值:无
**************************************************************************************/
void SetTxMode(void)				
{	
	NRF905_TX_EN_H;
	NRF905_TRX_CE_L;		//为什么置低,先写数据后发送,所以要后拉高
  Delay_us(650);
}		
/**************************************************************************************
* 名    称: SetRxMode
* 功    能: 设置NRF905发送状态
* 参    数: 无
* 调用方式:SetRxMode();
* 返 回 值:无
**************************************************************************************/
void SetRxMode(void)
{
	NRF905_TX_EN_L;
	NRF905_TRX_CE_H;
  Delay_us(650);			
}
/**************************************************************************************
* 名    称: CD_read
* 功    能: 读取CD的值(载波检测)
* 参    数: 无
* 调用方式:CD_read();
* 返 回 值: CD的值
**************************************************************************************/
u8 CD_read(void)
{	
	u8 ReadValue;
	ReadValue = NRF905_CD_DATA;
	return ReadValue;
}
/**************************************************************************************
* 名    称: AM_read
* 功    能: 读取AM的值(地址匹配AM)
* 参    数: 无
* 调用方式:AM_read();
* 返 回 值: AM的值
**************************************************************************************/
u8 AM_read(void)
{	
	u8 ReadValue;
	ReadValue = NRF905_AM_DATA;
	return ReadValue;
}
/**************************************************************************************
* 名    称: DR_read
* 功    能: 读取CD的值(数据就绪DR)
* 参    数: 无
* 调用方式:DR_read();
* 返 回 值: DR的值
**************************************************************************************/
u8 DR_read(void)
{	
	u8 ReadValue;
	ReadValue = NRF905_DR_DATA;
	return ReadValue;
}
/**************************************************************************************
* 名    称: NRF905_SPI_Read_Bit
* 功    能: 读取MISO的值
* 参    数: 无
* 调用方式:NRF905_SPI_Read_Bit();
* 返 回 值: MISO的值,0或者1
**************************************************************************************/
static u8 NRF905_SPI_Read_Bit(void)
{	
	u8 ReadValue;
	ReadValue = NRF905_MISO_DATA;
	return ReadValue;
}
/**************************************************************************************
* 名    称: NRF905_SPI_Read_Byte
* 功    能: 读取MISO的值,字节的形式
* 参    数: 无
* 调用方式:NRF905_SPI_Read_Byte();
* 返 回 值: MISO的值
**************************************************************************************/
u8 NRF905_SPI_Read_Byte(void)
{
	u8 i;
	u8 Temp_data;	
	for (i = 0;i < 8;i ++)				// Setup byte circulation bits
	{	
		Temp_data = Temp_data << 1;		// Right shift Temp_data
		NRF905_SCK_H;				// Set clock line high
		if (NRF905_SPI_Read_Bit())
		{
			Temp_data |= 0x01;		// Read data
		}						
		NRF905_SCK_L;				// Set clock line low
	}
	return Temp_data;				// Return function parameter	
}
/**************************************************************************************
* 名    称: NRF905_SPI_Write_Byte
* 功    能: NRF905写1字节函数
* 参    数: DATA: 需要写入的字节
* 调用方式:NRF905_SPI_Write_Byte(0xaa);
* 返 回 值:无
**************************************************************************************/
void NRF905_SPI_Write_Byte(u8 DATA)
{
	u8 i,Temp_data;
	Temp_data = DATA;
	for (i=0;i<8;i++)
	{
		if (Temp_data & 0x80)				//总是发送最高位
		{
			NRF905_MOSI_H;
		}
		else
		{
			NRF905_MOSI_L;
		}
		NRF905_SCK_H;
		Temp_data=Temp_data<<1;
		NRF905_SCK_L;
	}
}
需要程序的可以留言.....
代码已经上传至 http://download.csdn.net/detail/king_bingge/5797627






评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值