本人求NRF905与AT89C51单片机构成的无线收发应用电路及程序,qq 2396427729

2024-12-28 14:24:23
推荐回答(2个)
回答1:

电路的话比较简单,我直接用现成的开发版,上面有几个按键和led指示灯,搞10根杜邦线和nRF905模块连起来就行了,引脚定义见程序。有不解的地方欢迎进一步提问。

/******************************************************************************************\
日期:2012年4月23日
硬件配置:单片机型号:STC89C52RC,晶振11.0592M,射频芯片通过10根导线与单片机IO口连接
射频芯片nRf905,模块自带天线长度约10cm,发射频率433M,频道1
其他外设:2个按键,2个led灯,一个串口,按键一端接单片机,一端接地,led一端接单片机,另一端串联电阻后接电源
功能:用于测试nRF905,可通过串口发送接收,波特率9600,也可通过按键发送,led显示
核心函数:Init905() RxPacket() TxPacket()
/*******************************************************************************************/
//#include
//#include "ISD51.h"
#include
#include
#include
#include
#define INT8U unsigned char
#define INT16U unsigned int
#define TIMER1 0XFD //256-(110592/(12*32*96))
//*****************************************************************************
//寄存器宏定义
//*****************************************************************************
#define WRC 0x00 //W_RF_CONFIG
#define RRC 0x10 //R_RF_CONFIG
#define WTP 0x20 //W_TX_PAYLOAD
#define RTP 0x21 //R_TX_PAYLOAD
#define WTA 0x22 //W_TX_ADDRESS
#define RTA 0x23 //R_TX_ADDRESS
#define RRP 0x24 //R_RX_PAYLOAD
#define RAD 0x40 //R_ADC_DATA
#define WAC 0x44 //W_ADC_CONFIG
#define RAC 0x46 //R_ADC_CONFIG
#define WTU 0x50 //W_TEST_UNLOCK (use with data A5)
#define WTR 0x52 //W_TEST_REGISTER
#define RTR 0x53 //R_TEST_REGISTER
#define CC 0x80 //CHANNEL_CONFIG
#define SAV 0xC0 //START_ADC_CONV
#define HFREQ 1 // 0=433MHz, 1=868/915MHz 19/08/2004 set 915mhz
#define POWER 3 // 0=min power...3 = max power
///////////////////////////////////////////////////////////////////////////////
#define RFLEN 32 //数据长度,最大32
INT8U data UartRecCnt=0; //串口接收计数
#define do_uart() if(UartRecCntINT8U RxBuf[RFLEN]={0}; //接收数据缓冲区
INT8U TxBuf[RFLEN]={0}; //发送数据缓冲区
//********定义与9e5不一样******************************************************
//I/O口定义
//*****************************************************************************
sbit LED1 =P1^0;
sbit LED2 =P1^1;
sbit LED3= P1^2;
sbit LED4= P1^3;
sbit KEY1 =P1^6;
sbit KEY2 =P1^7;
/////////定义与9e5不一样//////////////////////////////////////////////////////
sbit TX_EN = P0^0;
sbit TRX_CE = P0^1;
sbit POW_UP = P0^2;
sbit CD = P0^3;
sbit AM = P0^4;
sbit DR = P0^5;
sbit MISO = P0^6;
sbit MOSI = P0^7;
sbit SCK = P2^0;
sbit CE_905 = P2^1; //*****************************************************************************
//配置寄存器
//*****************************************************************************
code INT8U Nrf905Config[10] = {
0x28, //频道设置
// 0x0e, //自动重发关,发送节电模式关,输出功率10dB,915MHZ
0x0c, //自动重发关,发送节电模式关,输出功率10dB,433MHZ
0x44, //收发地址都为4字节

RFLEN,// 0x04, //接收数据长度,4字节
RFLEN,// 0x04, //发送数据长度,4字节

0xe7, //4字节地址
0xe7,
0xe7,
0xe7,
// 0xdf //CRC开,16位校验,16M晶振,外部时钟使能500KHZ输出
0x58 //CRC开,8位校验,16M晶振,禁止外部时钟
};
/////////////////////////////////////////////////////////////////////////////////*****************************************************************************
//函数名:void Delay(INT8U n)
//输入:时间
//输出:无
//功能描述:廷时100us
//*****************************************************************************
void Delay(INT8U n)
{
INT8U i;
while(n--)
for(i=0;i<40;i++); //for(i=0;i<35;i++);
}//***************************** 该函数与nRF9e5不同 ****************************
//函数名:INT8U SpiReadWrite(INT8U b)
//输入:发送的数据
//输出:收到的数据
//功能描述:SPI发送接收一个字节
//*****************************************************************************
INT8U SpiReadWrite(INT8U dat)
{
INT8U i,temp;
temp = 0;
SCK = 0;
for(i=0; i<8; i++)
{
if(dat & 0x80)
{
MOSI = 1;
}
else MOSI = 0;
dat <<= 1; SCK = 1;
_nop_();
_nop_(); temp <<= 1;
if(MISO)temp++;
SCK = 0;
_nop_();
_nop_();
}
return temp;
}
//***************************** 该函数与nRF9e5不同 ****************************
//函数名:void InitCpu(void)
//输入:无
//输出:无
//功能描述:Cpu初始化
//*****************************************************************************
void InitCpu(void)
{

LED2=0;
LED1=0;
Delay(10);
}
//***************************** 该函数与nRF9e5不同 ****************************
//函数名:InitUart(void)
//输入:无
//输出:无
//功能描述:串口初始化
//*****************************************************************************
void InitUart(void)
{
SCON = 0x50; //串口方式1,允许接收
TMOD = 0x21; //定时器1工作方式2,定时器0工作方式1
TH1 = TIMER1;
TL1 = TIMER1;
TR1 = 1; //启动定时器1
ES = 1;
EA = 1;
}
//*****************************************************************************
//函数名:void SendCh(INT8U c)
//输入:发送的数据
//输出:无
//功能描述:发送一个字节
//*****************************************************************************
void SendCh(INT8U c)
{
// EA = 0;
// TI = 0;
SBUF = c;
while(!TI);//等待发送完成
TI = 0;
// EA = 1;
}
/*******************************************************************************************/
//发送字符串到串口
void SendStr(INT8U *p)
{
while(*p!='\0')
{ SBUF=*p; //待发送的数据写入缓冲区
while(!TI); //等待发送完成
TI=0; //清零发送标志位
p++; //指针加1
}
}
/*****************************************************************************
//函数名:void Init905(void)
//输入:无
//输出:无
//功能描述:Nrf905初始化,这里我们配置成32位地址。
//******************************************************************************/
void Init905(void)
{
INT8U i;
POW_UP = 1; //905上电
//Delay(200);
SCK = 0; // Spi clock line init high

TRX_CE=0;
TX_EN=0; //配置模式
CE_905 = 0;
SpiReadWrite(WRC);
for(i=0; i<10; i++)
{
SpiReadWrite(Nrf905Config[i]); //写入配置寄存器
}
CE_905 = 1;
}//*****************************************************************************
//函数名:TransmitPacket(INT8U *pBuf)
//输入:发送的数据
//输出:无
//功能描述:发送发送缓冲区的数据
//*****************************************************************************
void TransmitPacket(INT8U *pBuf)
{
INT8U i;

CE_905 = 0;
SpiReadWrite(WTP);
for(i=0; i {
SpiReadWrite(pBuf[i]);//写入发送数据缓冲区
}
CE_905 = 1;

TX_EN = 1;
TRX_CE = 1; //使能发送
Delay(1);
TRX_CE = 0;
}
//*****************************************************************************
//函数名:INT8U Recepacket(INT8U *pBuf)
//输入:接收数据缓冲区
//输出:成功返回1,否则返回0
//功能描述:接收数据存在缓冲区内
//*****************************************************************************
INT8U Recepacket(INT8U *pBuf)
{
INT8U i;
TX_EN = 0;TRX_CE = 1; //进入接收模式
if(!DR)return 0; //查询DR的状态
//原始代码采用的是等待超时的方法
/* ResetTimer(1);//复位超时计数器。
while(DR == 0)//有收到切换到空闲状态时退出接收状态。
{
if(ReadTimer(1) > 300)//300MS超时退出。
{
TRX_CE = 0;
return 0;
}
}*/
TRX_CE = 0; // Set nRF905 in standby mode
CE_905 = 0; // Spi enable for write a spi command
SpiReadWrite(RRP);// Read payload command
for(i=0; i {
pBuf[i] = SpiReadWrite(0);
}
while(DR);//直到DR为高。
/* {
SpiReadWrite(0);
}*/
CE_905 = 1;
return 1;
}
/*串口接收中断函数*/
void int_rec(void) interrupt 4 using 2
{
if(RI) //查询接收标志位(有数据发送过来时置为1)
{
RI = 0; //接收标志位清零
//SendCh(SBUF);//让从电脑上传到单片机的数据,传回的电脑显示
do_uart();//对接受到得字符操作
}
}
/************************************************************************/
//功能:把串口接收的数据通过无线发射出去
//采取延时读取串口接收计数的方法,判读串口发送数据是否完毕,提高发送效率
void UartToRf(void )
{
INT8U Tmp=0; //临时变量,暂存UartRecCnt
do
{
Tmp=UartRecCnt;
Delay(5); //延时,等待
}
while(Tmp!=UartRecCnt); //判段来自串口的字符串是否发送完毕 TransmitPacket(TxBuf); //通过射频发送
memset(TxBuf,0,UartRecCnt); //清空缓冲区
UartRecCnt=0; // 串口接受计数清零
}//载波监听发送,重试3次,仍失败不发送
unsigned char CDSend(void)
{
unsigned char i=0;
do
{
if(!CD) //载波监听
{
TransmitPacket(TxBuf);//发送数据
return 0; //发送成功,返回0
}
SendCh(0x30+i);
Delay(rand()&0x0f);//随机延时
LED3=~LED3;
}while(++i<3); //最多3次
SendStr("fail");
return 1; //发送失败,返回1
}/***********************主程序*************************************************/
main()
{
Init905(); //初始化Nrf905
InitCpu(); //初始化CPU
// InitTimer();
InitUart(); //初始化串口。
LED2 = 1;
LED1 = 1; //两个LED灭。
//SendCh('R');
while(1)
{
LED2=1; LED1=1;
if(KEY1 == 0) //按键1按下
{
TxBuf[0] = 0x31;
//TransmitPacket(TxBuf);//发送数据
CDSend();
}
if(KEY2 == 0) //按键2按下
{
TxBuf[0] = 0x32;
//TransmitPacket(TxBuf);//发送数据
CDSend();
}
if(Recepacket(RxBuf)) //接收到数据。
{
if(RxBuf[0] == 0x31)
{
LED1 = 0;
Delay(5);
}
else if(RxBuf[0] == 0x32)
{
LED2 = 0;
Delay(5);
}
SendStr(RxBuf); //将从无线收到的数据发到串口
}
if(UartRecCnt) //串口收到数据时相应处理
{
/*Delay(2*RFLEN); //延时,等待字符串发送完毕.时间过短的话会出现串口数据未发完,缓冲区已情况的情况
TransmitPacket(TxBuf); //通过射频发送
memset(TxBuf,0,UartRecCnt); //清空缓冲区
UartRecCnt=0; // 串口接受计数清零
*/
UartToRf(); //新编发送函数

}

}
}
//end

回答2:

这个不好搞 无线的是很复杂的 也不是很稳定 一般人都怕