小弟使用C8051f411和nRF24L01+搭建一个无线通信的模块,一个做发射模块一个做接收模块。这两天正在调试发射模块,现在遇到的问题是调用一次数据发送函数nRF24L01_TxPacket之后读取STATUS寄存器的值,这时候读到的是0x1F。但是按照寄存器说明表中,应该读取到0x2E才对请教各位大神这个是什么问题。是否与我在设定TX_MODE时,对寄存器EN_AA、EN_RXADDR、SETUP_RETR的配置有关?附上程序如下(程序中包含了串口程序,请无视):
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <C8051F410.h> // SFR declarations
#include <stdio.h>
//-----------------------------------------------------------------------------
// Global Constants
//-----------------------------------------------------------------------------
typedef unsigned char uchar;
typedef unsigned char uint;
#define SYSCLK 24500000 // Internal oscillator frequency in Hz
#define SPI_CLOCK 500000 // Maximum SPI clock
// The SPI clock is a maximum of 500 kHz
// with a SYSCLK of 24.5 MHz when this
// example is used with the SPI0_Slave
// code example.
//-----------------------------------------------------------------------------
// nRF24L01+ 相关宏设置
//-----------------------------------------------------------------------------
// SPI(nRF24L01) commands
#define READ_REG 0x00 // Define read command to register
#define WRITE_REG 0x20 // Define write command to register
#define RD_RX_PLOAD 0x61 // Define RX payload register address
#define WR_TX_PLOAD 0xA0 // Define TX payload register address
#define FLUSH_TX 0xE1 // Define flush TX register command
#define FLUSH_RX 0xE2 // Define flush RX register command
#define REUSE_TX_PL 0xE3 // Define reuse TX payload register command
#define NOP 0xFF // Define No Operation, might be used to read status register
// SPI(nRF24L01) registers(addresses)
#define CONFIG 0x00 // 'Config' register address
#define EN_AA 0x01 // 'Enable Auto Acknowledgment' register address
#define EN_RXADDR 0x02 // 'Enabled RX addresses' register address
#define SETUP_AW 0x03 // 'Setup address width' register address
#define SETUP_RETR 0x04 // 'Setup Auto. Retrans' register address
#define RF_CH 0x05 // 'RF channel' register address
#define RF_SETUP 0x06 // 'RF setup' register address
#define STATUS 0x07 // 'Status' register address
#define OBSERVE_TX 0x08 // 'Observe TX' register address
#define CD 0x09 // 'Carrier Detect' register address
#define RX_ADDR_P0 0x0A // 'RX address pipe0' register address
#define RX_ADDR_P1 0x0B // 'RX address pipe1' register address
#define RX_ADDR_P2 0x0C // 'RX address pipe2' register address
#define RX_ADDR_P3 0x0D // 'RX address pipe3' register address
#define RX_ADDR_P4 0x0E // 'RX address pipe4' register address
#define RX_ADDR_P5 0x0F // 'RX address pipe5' register address
#define TX_ADDR 0x10 // 'TX address' register address
#define RX_PW_P0 0x11 // 'RX payload width, pipe0' register address
#define RX_PW_P1 0x12 // 'RX payload width, pipe1' register address
#define RX_PW_P2 0x13 // 'RX payload width, pipe2' register address
#define RX_PW_P3 0x14 // 'RX payload width, pipe3' register address
#define RX_PW_P4 0x15 // 'RX payload width, pipe4' register address
#define RX_PW_P5 0x16 // 'RX payload width, pipe5' register address
#define FIFO_STATUS 0x17 // 'FIFO Status Register' register address
//-----------------------------------------------------------------------------
// Function Prototypes
//-----------------------------------------------------------------------------
#define TX_ADR_WIDTH 5 // 5 uints TX address width
#define RX_ADR_WIDTH 5 // 5 uints RX address width
#define TX_PLOAD_WIDTH 2 // 1 uints TX payload,每次发送MSB+LSB
#define RX_PLOAD_WIDTH 2 // 1 uints TX payload,每次接收MSB+LSB
uint const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址
uint const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址
uint bdata sta; //状态标志
sbit RX_DR =sta^6;
sbit TX_DS =sta^5;
sbit MAX_RT =sta^4;
sbit CE = P2^1;
sbit IRQ = P2^0;
void SYSCLK_Init (void);
void UART0_Init (void);
void PORT_Init (void);
void delay(unsigned int count);
void UART_send(unsigned char c);
void SPI0_Init(void);
uchar SPI_RW(uchar val);
uchar SPI_RW_Reg(uchar reg, uchar value);
uchar SPI_Read(uchar reg);
uchar SPI_Read_Buf(uchar reg, uchar * pBuf, uchar bytes);
uchar SPI_Write_Buf(uchar reg, uchar * pBuf, uchar bytes);
unsigned char nRF24L01_RxPacket(unsigned char* rx_buf);
void nRF24L01_TxPacket(unsigned char * tx_buf);
void RX_Mode(void);
void TX_Mode(void);
//-----------------------------------------------------------------------------
// main() Routine
//-----------------------------------------------------------------------------
void main (void)
{
unsigned char i=0x00;
unsigned char TxBuf[2]={0};
unsigned char RxBuf[2]={0};
PCA0MD &= ~0x40; // Disable Watchdog timer
SYSCLK_Init ();
UART0_Init ();
PORT_Init ();
SPI0_Init();
TX_Mode();
RxBuf[0] = 0xEB;
RxBuf[1] = 0x9D;
nRF24L01_TxPacket(TxBuf);
i = SPI_Read(READ_REG+STATUS);
while (1)
{
;//nRF24L01_TxPacket(TxBuf);
}
}
//-----------------------------------------------------------------------------
// Initialization Subroutines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// SYSCLK_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// This routine initializes the system clock to use the internal oscillator
// at its maximum frequency.
// Also enables the Missing Clock Detector.
//-----------------------------------------------------------------------------
void SYSCLK_Init (void)
{
OSCICN = 0x87; // configure internal oscillator for
// 24.5MHz
RSTSRC = 0x04; // enable missing clock detector
}
//-----------------------------------------------------------------------------
// Port_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
//-----------------------------------------------------------------------------
void PORT_Init (void)
{
P0MDOUT = 0x1D; //将P0.0 P0.2 P0.3 P0.4即SCK MOSI NSS TX0置于Push-Pull
P2MDOUT = 0x03; //将P2.0 P2.1置于Push-Pull
XBR0 = 0x03; //启用UART0 SPI0
XBR1 = 0x40; //Enable Crossbar
}
//-----------------------------------------------------------------------------
// SPI0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Configures SPI0 to use 4-wire Single Master mode. The SPI timing is
// configured for Mode 0,0 (data centered on first edge of clock phase and
// SCK line low in idle state).
//
//-----------------------------------------------------------------------------
void SPI0_Init()
{
SPI0CFG = 0x43; // Enable the SPI as a Master
SPI0CN = 0x0D; // 4-wire Single Master, SPI enabled
// SPI clock frequency equation from the datasheet
SPI0CKR = (SYSCLK/(2*SPI_CLOCK))-1;
}
//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Configure the UART0 using Timer1, for <BAUDRATE> and 8-N-1.
//-----------------------------------------------------------------------------
void UART0_Init (void)
{
SCON0 = 0x10; // SCON0: 8-bit variable bit rate
// level of STOP bit is ignored
// RX enabled
// ninth bits are zeros
// clear RI0 and TI0 bits
if (SYSCLK/BAUDRATE/2/256 < 1) {
TH1 = -(SYSCLK/BAUDRATE/2);
CKCON |= 0x08; // T1M = 1; SCA1:0 = xx
} else if (SYSCLK/BAUDRATE/2/256 < 4) {
TH1 = -(SYSCLK/BAUDRATE/2/4);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 01
CKCON |= 0x01;
} else if (SYSCLK/BAUDRATE/2/256 < 12) {
TH1 = -(SYSCLK/BAUDRATE/2/12);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 00
} else if (SYSCLK/BAUDRATE/2/256 < 48) {
TH1 = -(SYSCLK/BAUDRATE/2/48);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 10
CKCON |= 0x02;
} else {
while (1); // Error. Unsupported baud rate
}
TL1 = TH1; // init Timer1
TMOD &= ~0xf0; // TMOD: timer 1 in 8-bit autoreload
TMOD |= 0x20;
TR1 = 1; // START Timer1
TI0 = 1; // Indicate TX0 ready
}
//-----------------------------------------------------------------------------
// Support Routines
//-----------------------------------------------------------------------------
/**************************************************
函数:SPI_RW()
描述:
根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01
读出一字节
/**************************************************/
uchar SPI_RW(uchar val)
{
SPIF=0;
SPI0DAT=val;
while(SPIF==0);
return SPI0DAT;
}
/**************************************************
函数:SPI_RW_Reg()
描述:
写数据value到reg寄存器
/**************************************************/
uchar SPI_RW_Reg(uchar reg, uchar value)
{
uchar status;
NSSMD0 = 0; // CSN置低,开始传输数据
status = SPI_RW(reg); // 选择寄存器,同时返回状态字
SPI_RW(value); // 然后写数据到该寄存器
NSSMD0 = 1; // CSN拉高,结束数据传输
return(status); // 返回状态寄存器
}
/**************************************************/
/**************************************************
函数:SPI_Read()
描述:
从reg寄存器读一字节
/**************************************************/
uchar SPI_Read(uchar reg)
{
uchar reg_val;
NSSMD0 = 0; // CSN置低,开始传输数据
SPI_RW(reg); // 选择寄存器
reg_val = SPI_RW(0); // 然后从该寄存器读数据
NSSMD0 = 1; // CSN拉高,结束数据传输
return(reg_val); // 返回寄存器数据
}
/**************************************************/
/**************************************************
函数:SPI_Read_Buf()
描述:
从reg寄存器读出bytes个字节,通常用来读取接收通道
数据或接收/发送地址
/**************************************************/
uchar SPI_Read_Buf(uchar reg, uchar * pBuf, uchar bytes)
{
uchar status, i;
NSSMD0 = 0; // CSN置低,开始传输数据
status = SPI_RW(reg); // 选择寄存器,同时返回状态字
for(i=0; i<bytes; i++)
pBuf[i] = SPI_RW(0); // 逐个字节从nRF24L01读出
NSSMD0 = 1; // CSN拉高,结束数据传输
return(status); // 返回状态寄存器
}
/**************************************************/
/**************************************************
函数:SPI_Write_Buf()
描述:
把pBuf缓存中的数据写入到nRF24L01,通常用来写入发
射通道数据或接收/发送地址
/**************************************************/
uchar SPI_Write_Buf(uchar reg, uchar * pBuf, uchar bytes)
{
uchar status, i;
NSSMD0 = 0; // CSN置低,开始传输数据
status = SPI_RW(reg); // 选择寄存器,同时返回状态字
for(i=0; i<bytes; i++)
SPI_RW(pBuf[i]); // 逐个字节写入nRF24L01
NSSMD0 = 1; // CSN拉高,结束数据传输
return(status); // 返回状态寄存器
}
/**************************************************/
/**************************************************
函数:RX_Mode()
描述:
这个函数设置nRF24L01为接收模式,等待接收发送设备的数据包
/**************************************************/
void RX_Mode(void)
{
CE = 0;
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 接收设备接收通道0使用和发送设备相同的发送地址
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 使能接收通道0自动应答
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 使能接收通道0
SPI_RW_Reg(WRITE_REG + RF_CH, 40); // 选择射频通道0x40
SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH); // 接收通道0选择和发送通道相同有效数据宽度
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // CRC使能,16位CRC校验,上电,接收模式
CE = 1; // 拉高CE启动接收设备
delay(130);
}
/**************************************************/
/**************************************************
函数:TX_Mode()
描述:
这个函数设置nRF24L01为发送模式,等待发送数据包
/**************************************************/
void TX_Mode(void)
{
CE = 0;
SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 写入发送地址
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 为了应答接收设备,接收通道0地址和发送地址相同
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 使能接收通道0自动应答
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 使能接收通道0
SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a); // 自动重发延时等待250us+86us,自动重发10次
SPI_RW_Reg(WRITE_REG + RF_CH, 40); // 选择射频通道0x40
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // CRC使能,16位CRC校验,上电
CE = 1;
delay(130);
}
/**************************************************/
/******************************************************************************************************/
/*函数:unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)
/*功能:数据读取后放如rx_buf接收缓冲区中
/******************************************************************************************************/
unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)
{
unsigned char revale=0;
sta=SPI_Read(STATUS); // 读取状态寄存其来判断数据接收状况
if(RX_DR) // 判断是否接收到数据
{
CE = 0; //SPI使能
SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// read receive payload from RX_FIFO buffer
revale =1; //读取数据完成标志
}
SPI_RW_Reg(WRITE_REG+STATUS,sta); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志
return revale;
}
/***********************************************************************************************************
/*函数:void nRF24L01_TxPacket(unsigned char * tx_buf)
/*功能:发送 tx_buf中数据
/**********************************************************************************************************/
void nRF24L01_TxPacket(unsigned char * tx_buf)
{
CE=0; //StandBy I模式
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 装载接收端地址
SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // 装载数据
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送
CE=1; //置高CE,激发数据发送 .
delay(10);
}
void UART_send(unsigned char c)
{
while(TI0==0)
{};
TI0=0;
SBUF0=c;
}
void delay (unsigned int count)
{
for (count; count > 0; count--);
}
//-----------------------------------------------------------------------------
// End Of File
//-----------------------------------------------------------------------------
|
|