XN297L 2.4G无线模块 寄存器读写测试

本文详细记录了对XN297L无线模块的管脚确认过程,通过分析封装和线路布局确定了管脚顺序。接着,作者编写了四线SPI的读写寄存器测试代码,验证了模块的功能,并通过向TX_ADDR寄存器写入特定数据并读回,确认了SPI通信的正确性。文章强调了理解数据手册和观察电路布局在问题解决中的重要性。
摘要由CSDN通过智能技术生成

简单记录下XN297L 四线SPI读写寄存器

前言

        为避免吃灰,研究了下面买了很久的板子。因为便宜,照例只有发送板,没有接收板。配对不大可能,拆机比较现实。关于拆机价值最难利用的就是打磨过的MCU和其他IC。MCU是16p,12脚VCC,5脚GND,无从考证,放弃了。2.4g模块是本文重点。那个带天线独立于主板之外的红色小板就是2.4g模块,牛屎芯片,无管脚定义。主板上有丝印297,可以确认是XN297L无疑。剩下的就是确认管脚顺序了。

04e57f86436c46d38188919178239b0b.jpeg


一、管脚确认

        查了一下XN297L数据手册,XN297L有两种封装,QFN20 3x3 和SOP8。

95ebce62d48645acb8f56819095a6181.jpeg

        开始认为SOP8小一点,牛屎糊起来更方便,可能是SOP8,于是找了SOP8的三线SPI程序编写了测试程序。管脚不知道,但先试吧,怎么试都不行。后来又研究了一下封装,感觉QFN20 3x3更为可能:

83fca63370964b46915609b491c18c88.png

         因为红色小板上引出了8个管脚,应该是VCC、GND、CE、CSN、SCK、MOSI、MISO、IRQ。sop8正好8个管脚,但XC1、XC2接的是晶振,ANT接天线,只剩5个需要引出。所以排除sop8封装。

        下面就要确认管脚顺序。如果盲目试管脚,不考虑VCC、GND、IRG(悬空),会有5*4*3*2*1种可能,非人力可为。换一种思路猜管脚顺序其实也很简单,VCC、GND万用表可以确认。其他6个管脚可以看线路的走势辨别,因为为了布线方便,管脚之间的前后关系应该是不会变的。于是得到下图

c1d9a6541f2b498b8e3f85e54e2f527f.png

二、XN297 四线SPI读写寄存器测试

        通过读写寄存器可以确认XN297是XN297,并且管脚正确。main.c源码如下:

#include <STC89C5xRC.H>
#include <intrins.h>

sbit CE=P1^0;
sbit CS=P1^1;
sbit SCK=P1^2;
sbit MOSI=P1^3;
sbit MISO=P1^4;

const unsigned char TX_ADDRESS_DEF[5] = {0xcc,0xCC,0xCC,0xCC,0xCC};    		//RF 地址:接收端和发送端需一致

#define         HIGH                    (1)
#define         LOW                     (0)
#define         CSN_HIGH                (CSN |= HIGH)
#define         CSN_LOW                 (CSN &= LOW)
#define         SCK_HIGH                (SCK |= HIGH)
#define         SCK_LOW                 (SCK &= LOW)

#define         SPI_DATA_HIGH           (DATA |= HIGH)
#define         SPI_DATA_LOW            (DATA &= LOW)
#define         SPI_DATA_STATUS         (DATA)
#define         SPI_DATA_OUTPUT_MODE     ;
#define         SPI_DATA_INPUT_MODE      ;
#define         CE_HIGH                  RF_WriteReg(CE_FSPI_ON, 0)
#define         CE_LOW                   RF_WriteReg(CE_FSPI_OFF, 0)

/********************SPI  REGISTER  ********************/
#define		R_REGISTER			0x00                            //SPI read RF data
#define		W_REGISTER			0x20                            //SPI write RF data
#define		R_RX_PAYLOAD		        0x61                            //Read RX Payload
#define		W_TX_PAYLOAD		        0xA0                            //Write TX Payload
#define		FLUSH_TX			0xE1                            //Flush RX FIFO
#define		FLUSH_RX			0xE2                            //Flush TX FIFO
#define		REUSE_TX_PL			0xE3                            //Reuse TX Payload
#define		ACTIVATE			0x50                            //ACTIVATE
#define		DEACTIVATE			0x50                            //DEACTIVATE
#define		R_RX_PL_WID			0x60                            //Read width of RX data 
#define		W_ACK_PAYLOAD		        0xA8                            //Data with ACK
#define		W_TX_PAYLOAD_NOACK	        0xB0                            //TX Payload no ACK Request
#define		CE_FSPI_ON	                0xFD                            // CE HIGH
#define		CE_FSPI_OFF	                0xFC                            // CE LOW
#define		RST_FSPI	                0x53                            // RESET
#define		NOP_N				0xFF
             
/******************CONTROL  REGISTER*******************/
#define		CONFIG                          0x00            
#define		EN_AA				0x01
#define		EN_RXADDR			0x02
#define		SETUP_AW			0x03
#define		SETUP_RETR			0x04
#define		RF_CH				0x05
#define		RF_SETUP			0x06
#define		STATUS				0x07
#define		OBSERVE_TX			0x08
#define		DATAOUT			        0x09
#define		RX_ADDR_P0			0x0A
#define		RX_ADDR_P1			0x0B
#define		RX_ADDR_P2			0x0C
#define		RX_ADDR_P3			0x0D
#define		RX_ADDR_P4			0x0E
#define		RX_ADDR_P5			0x0F
#define		TX_ADDR				0x10
#define		RX_PW_P0			0x11
#define		RX_PW_P1			0x12
#define		RX_PW_P2			0x13
#define		RX_PW_P3			0x14
#define		RX_PW_P4			0x15
#define		RX_PW_P5			0x16
#define		FIFO_STATUS			0x17
#define		DEM_CAL				0x19
#define         RF_CAL2				0x1A
#define         DEM_CAL2			0x1B
#define		DYNPD				0x1C
#define		FEATURE				0x1D	
#define		RF_CAL				0x1E
#define		BB_CAL				0x1F

/
/*************************CONTROL CMD***********************************************/
#define         RF13dBm                         0x3F                            // 13dBm  发射档位功率设置
#define         RF10dBm                         0X0F                            // 10dBm 
#define         RF8dBm                          0x15                            // 8dbm      
#define         RF7dBm                          0x07                            // 7dbm   
#define         RF5dBm                          0x2c                            // 5dbm   
#define         RF4dBm                          0x06                            // 4dbm   
#define         RF2dBm                          0x05                            // 2dbm  
#define         RF0dBm                          0X0B                            // 0dBm  
#define         RF_3dBm                         0x04                            // -3dBm     
#define         RF_6dBm                         0x0A                            // -6dBm 
#define         RF_10dBm                        0x02                            // -10dBm 
#define         RF_18dBm                        0x01                            // -18dBm 
#define         RF_30dBm                        0x00                            // -30dBm 

#define         DR_1M                           0X00				//通信速率 1Mbps
#define         DR_2M                           0X40				//通信速率 2Mbps
#define         DR_250K                         0XC0                             //通信速率 250Kbps
#define         RX_DR_FLAG                      0X40                            // 接收中断标志位
#define         TX_DS_FLAG                      0X20                            // 发送完成中断标志位
#define         RX_TX_CMP_FLAG                  0X60                            // 发送接收完成中断标志位,ack_payload 模式下使用
#define         MAX_RT_FLAG                     0X10                            // 发送重传超时中断标志位
#define         TRANS_ENHANCE_MODE              1                               //传输类型增强型
#define         TRANS_BURST_MODE                2                               //传输类型普通型

#define         RxMode                           1
#define         RxMode_RTTE                      2
#define         DEFAULT_CHANNEL                78				//初始化时的频率: 2478 MHz           
#define         PAYLOAD_WIDTH                  16				//Payload宽度:     8bytes				
#define         TRANSMIT_TYPE                  TRANS_BURST_MODE 		//使用普通型模式           TRANS_BURST_MODE    TRANS_ENHANCE_MODE
#define         DATA_RATE                      DR_1M                           //通信速率1Mbps            DR_2M    DR_1M  DR_250K
#define         RF_POWER                      (RF13dBm |DATA_RATE)		//发射功率13dBm 
#define         RF_MODE                       RxMode_RTTE  //  RxMode_RTTE 



typedef unsigned long Uint16;
typedef unsigned char Uint8;

void UART_int(Uint16 baud);
void Sentdata(Uint8 dat);
unsigned char XN297_Check(void);
Uint8 temp;
void SPI_init(void);
void RF_WriteReg( unsigned char reg,  unsigned char wdata);
void RF_WriteBuf( unsigned char reg, unsigned char *pBuf, unsigned char length);
	

void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}


void Delay10ms()		//@11.0592MHz
{
	unsigned char i, j;

	i = 18;
	j = 235;
	do
	{
		while (--j);
	} while (--i);
}


void RF_Init(void)
{
#if(DATA_RATE == DR_1M) 
    unsigned char  BB_cal_data[]    = {0x0A,0x6D,0x67,0x9C,0x46};                               //1M速率配置
    unsigned char  RF_cal_data[]    = {0xF6,0x37,0x5D};
    unsigned char  RF_cal2_data[]   = {0x45,0x21,0xef,0x2C,0x5A,0x50};
    unsigned char  Dem_cal_data[]   = {0x01};  
    unsigned char  Dem_cal2_data[]  = {0x0b,0xDF,0x02};  
#elif(DATA_RATE == DR_250K) 
  /*
    //  unsigned char  BB_cal_data[]    = {0x0A,0x6D,0x67,0x9C,0x46};                                 //250K速率配置
    unsigned char  BB_cal_data[]    = {0x0A,0xeD,0x7F,0x9C,0x46}; 
    unsigned char  RF_cal_data[]    = {0xF6,0x37,0x5D};
    unsigned char  RF_cal2_data[]   = {0xD5,0x21,0xeb,0x2C,0x5A,0x40};
    unsigned char  Dem_cal_data[]   = {0x1e};  
    unsigned char  Dem_cal2_data[]  = {0x0b,0xDF,0x02}; 
     */
   unsigned char   BB_cal_data[]    = { 0x12,0xec,0x6f,0xa1,0x46}; 
   unsigned char    RF_cal_data[]    = {0xF6,0x37,0x5d};
   unsigned char   RF_cal2_data[]   = {0xd5,0x21,0xeb,0x2c,0x5a,0x40};
   unsigned char    Dem_cal_data[]   = {0x1f};  
   unsigned char    Dem_cal2_data[]  = {0x0b,0xdf,0x02};
    
#endif
       
    
    SPI_init();
    RF_WriteReg(RST_FSPI, 0x5A);								//Software Reset    			
    RF_WriteReg(RST_FSPI, 0XA5);    
   // RF_WriteReg(W_REGISTER + FEATURE, 0x20);                                                    // enable Software control ce 
   
    if(PAYLOAD_WIDTH <33)											
{
	RF_WriteReg(W_REGISTER +FEATURE, 0x27);							//切换到32byte模式   使能CE
}
else
{
  RF_WriteReg(W_REGISTER +FEATURE, 0x38);							//切换到64byte模式	   
}   
    //CE_LOW;   
		CE=0;//5.1
    RF_WriteReg(FLUSH_TX, 0);									// CLEAR TXFIFO		    			 
    RF_WriteReg(FLUSH_RX, 0);									// CLEAR  RXFIFO
    RF_WriteReg(W_REGISTER + STATUS, 0x70);							// CLEAR  STATUS	
    RF_WriteReg(W_REGISTER + EN_RXADDR, 0x01);							// Enable Pipe0
    RF_WriteReg(W_REGISTER + SETUP_AW,  0x03);							// address witdth is 5 bytes
    RF_WriteReg(W_REGISTER + RF_CH,     DEFAULT_CHANNEL);                                       // 2478M HZ
    RF_WriteReg(W_REGISTER + RX_PW_P0,  PAYLOAD_WIDTH);						// 8 bytes
    RF_WriteBuf(W_REGISTER + TX_ADDR,   ( unsigned char*)TX_ADDRESS_DEF, sizeof(TX_ADDRESS_DEF));	// Writes TX_Address to PN006
    RF_WriteBuf(W_REGISTER + RX_ADDR_P0,( unsigned char*)TX_ADDRESS_DEF, sizeof(TX_ADDRESS_DEF));	// RX_Addr0 same as TX_Adr for Auto.Ack   
    RF_WriteBuf(W_REGISTER + BB_CAL,    BB_cal_data,  sizeof(BB_cal_data));
    RF_WriteBuf(W_REGISTER + RF_CAL2,   RF_cal2_data, sizeof(RF_cal2_data));
    RF_WriteBuf(W_REGISTER + DEM_CAL,   Dem_cal_data, sizeof(Dem_cal_data));
    RF_WriteBuf(W_REGISTER + RF_CAL,    RF_cal_data,  sizeof(RF_cal_data));
    RF_WriteBuf(W_REGISTER + DEM_CAL2,  Dem_cal2_data,sizeof(Dem_cal2_data));
    RF_WriteReg(W_REGISTER + DYNPD, 0x00);					
    RF_WriteReg(W_REGISTER + RF_SETUP,  RF_POWER);						// 13DBM  		
     
#if(TRANSMIT_TYPE == TRANS_ENHANCE_MODE)      
    RF_WriteReg(W_REGISTER + SETUP_RETR,0x03);							//  3 retrans... 	
    RF_WriteReg(W_REGISTER + EN_AA,     0x01);							// Enable Auto.Ack:Pipe0  	
#elif(TRANSMIT_TYPE == TRANS_BURST_MODE)                                                                
    RF_WriteReg(W_REGISTER + SETUP_RETR,0x00);							// Disable retrans... 	
    RF_WriteReg(W_REGISTER + EN_AA,     0x00);							// Disable AutoAck 
#endif

}

void SPI_init(void)
{
	CE =0;
	CS = 1;
	SCK = 0;
	MOSI = 1;
}

void SPI_Write_Byte(unsigned char dat)
{
    unsigned char i;
    for (i = 0; i < 8; i++)
    {
				SCK = 0;
        MOSI = dat & 0x80;
        
        dat <<= 1;
        SCK = 1;
    }
		SCK = 0;
}

unsigned char SPI_Read_Byte(void)
{
    unsigned char i, dat = 0;
    for (i = 0; i < 8; i++)
    {
				SCK = 0;
        dat <<= 1;
        SCK = 1;
        if (MISO)
        {
            dat |= 0x01;
        }
        
    }
		SCK = 0;
    return dat;
}




unsigned char Read_Register(unsigned char reg_addr)
{
    unsigned char dat;
    CS = 0;
    SPI_Write_Byte(reg_addr | 0x80);
    dat = SPI_Read_Byte();
    CS = 1;
    return dat;
}


void RF_WriteReg( unsigned char reg,  unsigned char wdata)
{
    CS=0;
    SPI_Write_Byte(reg);
    SPI_Write_Byte(wdata);
    CS=1;
}

void RF_WriteBuf( unsigned char reg, unsigned char *pBuf, unsigned char length)
{
     unsigned char j;
    CS=0;
    j = 0;
    SPI_Write_Byte(reg);
    for(j = 0;j < length; j++)
    {
        SPI_Write_Byte(pBuf[j]);
    }
    j = 0;
    CS=1;
}

/*
 unsigned char ucRF_ReadReg( unsigned char reg)
{
     unsigned char data1;
    
    CS=0;
    SPI_Write_Byte(reg);
    data1 = SPI_Read_Byte();
    //SPI_DATA_OUTPUT_MODE;
    CS=1;
    
    return data1;
}

*/
void RF_ReadBuf( unsigned char reg, unsigned char *pBuf,  unsigned char length)
{
    unsigned char byte_ctr;

    CS=0;                   		                               			
    SPI_Write_Byte(reg);       		                                                		
    for(byte_ctr=0;byte_ctr<length;byte_ctr++)
    	pBuf[byte_ctr] = SPI_Read_Byte();
    SPI_DATA_OUTPUT_MODE;
    CS=1;                                                                 		
}


void RF_TxMode(void)
{

		CE=0;
    RF_WriteReg(W_REGISTER + CONFIG,  0X8E);							// 将RF设置成TX模式
    Delay10ms();
		CE=1;//5.1
    Delay10ms();
}

void main(void)
{
	
	UART_int(9600);
	EA =1;
	RF_Init();	
	RF_TxMode();
	
	Sentdata(0x33);
 
  // 进一步处理读取结果
	while(1){
		XN297_Check();
		Delay1000ms();
	}
}




unsigned char XN297_Check(void)
{
	unsigned char check_in_buf[5]={0x55,0xaa,0x55,0xaa,0x55};
	unsigned char check_out_buf[5]={0x00};
	unsigned char i;
	
	//CE_HIGH;
	RF_WriteBuf(W_REGISTER+TX_ADDR,check_in_buf,5);
	RF_ReadBuf(R_REGISTER+TX_ADDR,check_out_buf,5);
	for(i=0;i<5;i++)
	{
		Sentdata(check_out_buf[i]);
	}
	if((check_out_buf[0]==0x55)&&\
		(check_out_buf[1]==0xaa)&&\
		(check_out_buf[1]==0x55)&&\
		(check_out_buf[1]==0xaa)&&\
		(check_out_buf[1]==0x55))
		return 0;
	else
		return 1;
}



void UART_int(Uint16 baud)
{
	TMOD = (TMOD&0X0F)|0X20;
	TH1 = 256-11059200/32/12/baud;
	TL1	= TH1;
	TR1 = 1;
	ET1 = 0;
	SCON = 0X50;
	ES	= 1;
}
void Sentdata(Uint8 dat)
{
	SBUF =dat;
	while(TI==0);
	TI =0;
}

void UART() interrupt 4
{
	if(RI==1)
	{
		RI=0;
		temp =SBUF;
	}
}

主要用于测试的函数是:

unsigned char XN297_Check(void)
{
    unsigned char check_in_buf[5]={0x55,0xaa,0x55,0xaa,0x55};
    unsigned char check_out_buf[5]={0x00};
    unsigned char i;
    
    //CE_HIGH;
    RF_WriteBuf(W_REGISTER+TX_ADDR,check_in_buf,5);
    RF_ReadBuf(R_REGISTER+TX_ADDR,check_out_buf,5);
    for(i=0;i<5;i++)
    {
        Sentdata(check_out_buf[i]);
    }
    if((check_out_buf[0]==0x55)&&\
        (check_out_buf[1]==0xaa)&&\
        (check_out_buf[1]==0x55)&&\
        (check_out_buf[1]==0xaa)&&\
        (check_out_buf[1]==0x55))
        return 0;
    else
        return 1;
}
 

        就是向TX_ADDR寄存器写入0x55,0xaa,0x55,0xaa,0x55,然后通过RF_ReadBuf(R_REGISTER+TX_ADDR,check_out_buf,5)读出来保存到check_out_buf并发送给串口,通过串口助手得到:

1da13a2118ef4ba0a52658f1cd5d95f4.png

        收到“0x55,0xaa,0x55,0xaa,0x55”,说明假设成立。

三、总结

        1、XN297L不同的封装,对应有三线或四线SPI。

        2、猜管脚顺序最好看明白数据手册再来,事半功倍。

6b9978a04c884e37bc129e90626ddc88.jpg

2e3beddd0ba54143ad02c887dc515b8d.jpg

8aa7e5f10bb045ac97c3ef4a1456f67e.jpg

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: xn297l单片机程序是一种用于控制无线模块xn297l的程序。xn297l是一种低功耗2.4ghz ism频段的无线传输模块,能够实现无线数据传输和通信功能。xn297l单片机程序通常使用c语言编写,包括一系列指令和编程逻辑,用于控制xn297l模块的工作状态和数据传输。程序中通常包括模块初始化,数据读写函数,中断处理等基本功能。xn297l单片机程序可应用于无线遥控器、无线汽车、智能家居等众多领域,可实现灵活的无线数据传输功能。程序开发人员需了解xn297l模块的基本使用方法和指令,熟悉相关的电子知识和编程技巧,才能开发出可靠和高效的xn297l单片机程序。 ### 回答2: xn297l单片机是一款常用于无线通信的芯片,它采用了先进的射频技术和微控制器技术,可以实现低功耗、高性能的无线通信功能。 编写xn297l单片机程序,首先需要了解其硬件接口和功能,然后根据具体需求进行编程设计。在编写程序时,可以按照以下步骤进行: 1. 确定通信方式:xn297l支持多种通信方式,如SPI、IIC等,根据实际需求选择合适的通信方式。 2. 初始化芯片:在程序开始的阶段,需要对芯片进行初始化设置,包括设置SPI或IIC的工作模式、通信速率等参数。 3. 设置无线通信参数:根据具体需求,设置xn297l的频率、功率等通信参数,以便实现与其他设备的无线通信。 4. 配置寄存器xn297l有多个寄存器可以配置,根据需要设置各个寄存器的值,包括数据包长度、同步字等。这些寄存器的配置可以根据具体需求进行调整,以实现不同的功能。 5. 发送数据:通过编写发送函数,将需要发送的数据通过SPI或IIC传输给xn297l芯片,实现数据的发送。 6. 接收数据:通过编写接收函数,实现从xn297l芯片接收到其他设备发来的数据,并进行处理。 7. 处理数据:根据接收到的数据进行相应的处理操作,可以是解析数据、处理数据、控制其他设备等。 8. 循环执行:将上述步骤放在一个循环中,实现程序的持续执行,以实现长时间的无线通信功能。 总之,xn297l单片机程序的编写过程包括初始化设置、参数配置、数据发送和接收等步骤,需要根据具体需求进行设计和调整。这样可以使xn297l芯片能够更好地完成无线通信的功能。 ### 回答3: xn297l是一款单片机芯片,它有着强大的计算和控制能力,适用于各种嵌入式系统。编写xn297l单片机程序时,需要首先了解其硬件特性和指令集,然后根据具体应用需求进行程序设计。 编写xn297l单片机程序可以分为以下几个步骤: 1. 硬件初始化:根据系统要求,进行xn297l芯片的端口设置和外设初始化。这些包括设置IO口的输入输出方向、中断控制、定时器、串口等外设的配置。 2. 主程序逻辑:根据实际应用需求,编写主程序的逻辑代码。例如,如果需要控制一个电机,可以编写一个循环,根据传感器数据控制电机转动的方向和速度。 3. 中断服务程序:xn297l支持中断功能,可以在特定的事件触发时执行相应的中断服务程序。例如,可以利用定时器中断来实现定时采集传感器数据,或者外部中断来响应按钮输入等。 4. 调试和优化:编写完程序后,需要进行调试和优化,确保程序的正确性和稳定性。可以利用在线调试工具或者仿真器来进行调试,通过观察程序运行情况和变量的变化来定位错误,并进行修正和优化。 总之,编写xn297l单片机程序需要熟悉其硬件特性和指令集,根据应用需求进行程序设计,进行适当的调试和优化,以确保程序的正确运行。这样可以有效利用xn297l的计算和控制能力,实现各种嵌入式系统的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值