⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rf24e1.c

📁 基于无线单片机24e1的组网程序。在无线传感器之类的应用中的成功案例。
💻 C
📖 第 1 页 / 共 2 页
字号:
//========================================================

//电池监控系统用无线传输模块
//文件名:RF24E1.C
//描述:无线收发模块处理,无线子系统的初始化配置;spi操作;
//无线收发操作;子系统工作在shockburst接收模式下
//收到无线数据,LED指示
//喂狗操作
//By:Andylee 2006-6-13
//anssett@163.com
//程序编译时,必须设置好XRAM的起始地址和大小,否则有可能程序不可运行!!!
//2006-6-26
//=========================================================
#include <BATTERY.H>
#include <stdlib.h>
extern unsigned char idata inCnt;
extern unsigned char idata outCnt;
extern unsigned char xdata inBuf[135];//120+1+8+4
extern unsigned char xdata outBuf[256];		//发送缓冲区
extern unsigned char idata cTxdDptr;
unsigned char idata Loc;
unsigned char idata Rxtimeout;

unsigned char idata adcResult_list[4][2];//接收节点四个通道采样值
unsigned char xdata Group1_Table[120];//节点地址列表,放在内部sram里面
unsigned char idata ptnode; 			//最多120个节点,包括2组,每组60点,对应120节电池
unsigned char idata cRxdTime;//串口接收延时
unsigned char xdata Node_V[480];
unsigned char xdata Node_T[480];//配置120个节点的信息缓存
//|    节点1  |    节点1  |......|    节点10   |-----------Node_V
//|ch1 L|ch1 H|ch2 L|ch2 H|......|ch1 L|ch1 H  |
//|    节点1  |    节点1  |......|    节点10   |-----------Node_T
//|ch1 L|ch1 H|ch2 L|ch2 H|......|ch1 L|ch1 H  |
unsigned int idata NodeBufCnt=0;//用于往里存放
unsigned int idata NdBfoutV=0;//&Node_V[0];//用于串出计数
unsigned int idata NdBfoutT=0;//&Node_T[0];
//unsigned char xdata *PtAddr=(unsigned char xdata *)(0x0fe8);//指向本机无线地址和节点地址的存放位置。
unsigned char idata Group1_Num=0;//节点数量
//unsigned int idata LocalADC[2];//本地adc采样值,电压,电流
union
	{
	unsigned char adcByte[4];
	struct
		{
		unsigned int local_V;
		unsigned int local_A;
		}adc_value;
	}idata LOCAL_ADC;
unsigned char idata ReqTimeout;
unsigned char idata CallTime=0;				//呼叫次数

//unsigned int xdata ADC_LIST[2][16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
//									0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
unsigned char idata ADC_Cnt=0;
unsigned int idata ADC_SUM[2]={0,0};

//bit t_500ms;
bit NodeResistered=0;
bit rFaddrResistered=0;
extern bit bRxd;
bit enrF=0;//启动巡检
sbit led=P0^6;
sbit dog=P0^5;
sbit Led_Tx=P0^3; 			    //LED点灯发送
sbit Led_Rx=P0^4;				//LED点灯接收
sbit CS_R=P0^0;					//eeprom 的偏选脚,
sbit e2rom_cs=P0^0;				//外部e2rom的偏选

//===========crc==================
//unsigned int code crc_ta[16]=
//{ /* CRC余式表 */
//         0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,
//         0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,
//};
union
{
	unsigned int iWord;
	struct
	{
		unsigned char cHigh;
		unsigned char cLow;
	}iData;
}idata CheckSumTemp;

unsigned char idata count;



bit RxdCheckSum( void );
void TxdCheckSum( void);
void CheckSum( unsigned char xdata*p );

/*unsigned char code RxTxConfig[] = {
    RF_DATA_LENGTH * 8, RF_DATA_LENGTH * 8,	 	//信道2和1的数据长(单位为位)
	0x00, 0x00, 0x00, 0x00, 0x00, 				//信道2的地址(如没有5字节长,则较低的位为有效位,下同)
	0xaa, 0xbb, 0x12, 0x34, 0x83,  				//信道1的地址
												//地址的位数(B0100_00xx),
												//CRC位数(16位Bxxxx_xx1x,8位Bxxxx_xx0x,CRC允许(Bxxxx_xxx0,0禁止,1允许)
	B1000_0001,//------------------------------------------------------------------------------------------------------------

							//位7,RX2_EN,为0只有信道1接收,为1允许2个信道同时接收
							//位6,CM,通讯方式,0:direct mode,1:ShockBurst mode,24e1只能为1
							//位5,RF DATA RATE,0:250Kbps,1:1Mbps,250Kbps时可提高接收灵敏度10dbm,1Mbps时要求16M晶体
							//位4,3,2,晶体频率,为该值+1再*4,如为2,则为12M晶体,3 ,16M
							//位1,0:发射功率:00:-20,	01:-10 10:-5 11:0dbm	 
	B0100_1111,//------------------------------------------------------------------------------------------------------------ 	 				
							//B0110_1111,1信道接收,shockBurst方式 ,1Mbps,16Mhz,0 DBm
							//B1111_111x,表示频率, 实际频率为2400+(B1111_111x >> 1)
							//位0,RX_EN,为0发送,为1接收
	B0000_0100,	 			//2402Mhz,接收方式	 (最后一位 RX_EN 为1表接收方式)
};							//这里设定为发射模式
*/
struct  RFConfig
{
    unsigned char n;
    unsigned char buf[15];
};

typedef struct RFConfig RFConfig;

#define ADDR_INDEX  8   // Index to address bytes in RFConfig.buf 
#define ADDR_COUNT  4   // Number of address bytes

RFConfig idata tconf =	//定义在xram是因为buf[15]中的地址段可能要动态修改。
{
    15,
    RF_DATA_LENGTH*8, RF_DATA_LENGTH*8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xaa, 0xbb, 0x12, 0x34, 0x81, 0x4f, 0x04
};

RFConfig idata rconf =	//定义在xram是因为buf[15]中的地址段可能要动态修改。
{
    15,
    RF_DATA_LENGTH*8, RF_DATA_LENGTH*8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xaa, 0xbb, 0x12, 0x34, 0x81, 0x4f, 0x05
};

//================================================================
//函数功能:100us软件延时程序
//filename:Delay100us()
//input:
//output:none
//================================================================
void Delay100us(unsigned char n)
{
    	unsigned char i;
    	while(n--)
        for(i=0;i<35;i++)
            ;
}
//================================================================
//函数功能:毫秒软件延时程序
//filename:Delay100us()
//input:
//output:none
//================================================================

void Delayms(unsigned char n)
{
    unsigned char j;
    while(n--)
        for(j=0;j<10;j++)
	    	Delay100us(10);

}
//================================================================
//函数功能:片内SPI接口操作
//filename:fSpiRdWr()
//input:char 读操作,输入参数0
//output:none
//================================================================
uchar SpiReadWrite(uchar dat){
	EXIF &= ~0x20;                          		// Clear SPI interrupt
   	SPI_DATA = dat;                           		// Move byte to send to SPI data register
    	while((EXIF & 0x20) == 0x00);            	// Wait until SPI hs finished transmitting
    	return SPI_DATA;
}
//================================================================
//函数功能:将无线子系统设置为接收模式
//on the spec.page26:
//If nFRF2401 subsystem is to be configured for 2 channel RX in ShockBuust
//a total of 120 bits must be shifted in during the first configuration after VDD is 
//applied.Once the wanted protocol,modus and RF channed are set ,only one bit(RXEN) is 
//shifted in to switch between RX and TX.So this function can do that like it.
//On the spec.page28
//After VDD is turned on shockburst configureation is done once and remains set whilst VDD is 
//present.during operation only the first byte for frequecy channel and Rx/Tx switch need
//to be changed!
//We can be so lazy!!
//filename:SetRxMode()
//input:none
//output:none
//================================================================
/*static void SetRxMode(void)
{
    	CE = 0;
    	CS = 1;
    	Delay100us(0);
    	SpiReadWrite(rconf.buf[14]);
    	CS = 0;
}*/
//================================================================
//函数功能:将无线子系统设置为发射模式
//filename:SetRxMode()
//input:none
//output:none
//================================================================
/*
static void SetTxMode(void)
{
    	CE = 0;
    	CS = 1;
    	Delay100us(0);
    	SpiReadWrite(tconf.buf[14]);
    	CS = 0;
}*/
//================================================================
//函数功能:将无线子系统初始化
//filename:SetRxMode()
//input:none
//output:none
//================================================================
void fRfInit(void){
	uchar b;

    PWR_UP = 1;                     	// Turn on Radio
    Delay100us(30);                 	// Wait > 3ms 
    SPICLK = 0;                     	// Max SPI clock (XTAL/8)
    SPI_CTRL = 0x02;                	// Connect internal SPI controller to Radio
   	CS = 1;                     		// RF SPI CS = 1,进行配置
	Delay100us(0);
    for(b=0;b<rconf.n;b++)				//初始化接收状态
    {
        SpiReadWrite(rconf.buf[b]);
    }
    CS = 0;	  							//退出配置状态
	Delay100us(0);
	CE = 1;								//启动接收	   			

}
void SysInit(void)
{
//void IO_Init(void)

    P0_ALT = 0x06;  					// Select alternate functions on pins P0.1 and P0.2,  TXD RXD 
    P0_DIR = 0x00;                 		// P0 work as output
    P0 = 0xff;                      	// all hight    
   	P1_DIR = 0x00;	



//void InitSerial(void) 

	TH1 = 0x98;      // 2400@16MHz (when T1M=1 and SMOD=1)
	CKCON |= 0x10;  // T1M=1 (/4 timer clock)
	PCON = 0x80;    // SMOD=1 (double baud rate)
	SCON = 0x52;    // Serial mode1, enable receiver
	TMOD = 0x20;    // Timer1 8bit auto reload 
	TR1 = 1;        // Start timer1

	ES = 1;
//void Timer0_Init(void)


	TMOD &= ~0x03;
	TMOD |= 0x01;                           // mode 1
	//CKCON |= 0x08;                        // T0M = 1 (/4 timer clock)
                                  			// Clear any pending Timer0 interrupts
	TH0=0xcb;
	TL0=0xea;								//10ms
	ET0 = 1;                                // Enable Timer0 interrupt
	TR0 = 1;                                // Start Timer0
//	EA=1;
//	EA=1;  

}
void InitADC(void)
{
	ADCCON = 0x20;                  //  NPD=1,内部参考电压
	ADCSTATIC &= 0x1c;
	ADCSTATIC |= 0x03;              // 12位ADC
}	


//================================================================
//函数功能:发射一个对查询命令('f')
//filename:TransmitCMD()
//input:节点地址的最低字节   2006-8-18该的
//output:none
//================================================================
/*
void TransmitCMD(unsigned char nda)
{
    unsigned char i;
    CE = 1;
    Delay100us(0);
	tconf.buf[ADDR_INDEX+ADDR_COUNT-1]=nda;
    for(i=0;i<ADDR_COUNT;i++)
	{
    SpiReadWrite(tconf.buf[ADDR_INDEX+i]);	//写目标地址
	}

    SpiReadWrite('f');						//写数据(8字节)
	CE = 0;
    Delay100us(3);                  	  	// Wait ~300us   
}
*/
/*****************************************************************************************
//函数名:RxPacket()
//输入:none
//输出:无
//功能描述:接收一组数据包
/*****************************************************************************************/
/*unsigned char RxPack(void)
{
    unsigned char b,jj=0;
    CE = 1;
    while(!DR1)
	{

		if(ReqTimeout>15)//50ms超时
		{

		ReqTimeout=0xff;
		return 0;
		}					
	}
	while(DR1)
	{
    b = SpiReadWrite(0);
	adcResult_list[jj][0]=b;
	b=SpiReadWrite(0);
	adcResult_list[jj++][1]=b;
	}
    CE = 0;
    return jj;
	ReqTimeout=0;
}*/




/*****************************************************************************************
//函数名:ReadShowADC()
//输入:通道选择,0~7,8为电源电压;
//输出:the value of the certain chanel
//功能描述:显示相关通道的采样值
/*****************************************************************************************/
unsigned int ReadShowADC(unsigned char chindex)
{	unsigned long xdata long_temp;
	unsigned int xdata result;
   
	ADCCON |= chindex;
	ADCCON &= ~0x80;                // 
	ADCCON |= 0x80;                 // 开始转换			//
	while((EXIF & 0x10) == 0)       // 转换完成
        ;
	EXIF &= ~0x10;                  // 清除标致            
	result = (ADCDATAH<<8) + (ADCDATAL);// 读ADC值12位
	result >>= 4;
	long_temp=(unsigned long)(result)*1220;
    result=long_temp/0xfff;//实际值的1000倍
							//注:这里采样地是通道地原始值,系数在M128方处理了。

	return result;	
}

//================================================================
//函数功能:校验和
//filename:CheckSum()
//input:
//output:
//================================================================
void CheckSum(unsigned char xdata  *ptr)
{
//        unsigned char da;
        unsigned char i;
//       CrcTemp.iWord = 0xffff;
		CheckSumTemp.iWord = 0;
//		SBUF=*ptr;
        for( i=0; i<count; i++ )
        {
//                da=CrcTemp.iData.cHigh >> 4; /* 暂存CRC的高四位 */

//               CrcTemp.iWord <<= 4; /* CRC右移4位,相当于取CRC的低12位)*/

//                CrcTemp.iWord ^= crc_ta[da^(*ptr/16)]; /* CRC的高4位和本字节的前半字节相加后查表计算CRC,

//                然后加上上一次CRC的余数 */
//               da = CrcTemp.iData.cHigh >>4 ; /* 暂存CRC的高4位 */
//                CrcTemp.iWord <<= 4; /* CRC右移4位, 相当于CRC的低12位) */
//                CrcTemp.iWord ^= crc_ta[da^(*ptr&0x0f)]; /* CRC的高4位和本字节的后半字节相加后查表计算CRC,
//                然后再加上上一次CRC的余数 */
//               ptr++;
		CheckSumTemp.iWord+=*ptr++;
        }
//SBUF=*--ptr;
//       CrcTemp.iWord ^= 0xffff;
}
//================================================================
//函数功能:计算接收序列的CRC
//filename:RxdCrc()
//input:none
//output:数据报头位置(eb90eb90+数据报)
//================================================================
bit RxdCheckSum(void)
{
	count = inBuf[Loc]-2;
        CheckSum(&inBuf[Loc]);
	if( (CheckSumTemp.iData.cHigh==inBuf[Loc+count])&&(CheckSumTemp.iData.cLow==inBuf[Loc+count+1]) )
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

//================================================================
//函数功能:计算发送序列的CRC
//filename:TxdCrc()
//input:none
//output:
//================================================================
void TxdCheckSum(void)
{
	count = outBuf[4]-2;
    CheckSum(&outBuf[4]);
	outBuf[count+4] = CheckSumTemp.iData.cHigh;
	outBuf[count+5] = CheckSumTemp.iData.cLow;
}

//================================================================
//函数功能:查找数据报的位置
//filename:FindHead()
//input:none
//output:数据报头位置(eb90eb90+数据报)
//================================================================
unsigned char FindHead(void)
{
	unsigned char i;
	for( i=0; ( (i<inCnt) && (i<4) ); i++ )
	{
		if( (inBuf[i] == 0xeb)&&(inBuf[i+1] == 0x90)&&(inBuf[i+2] == 0xeb)&&(inBuf[i+3] == 0x90) )
			return i+4;		
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -