本帖最后由 阿比安吉 于 2014-12-23 16:15 编辑
小弟使用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 // TheSPI clock is a maximum of 500 kHz // witha SYSCLK of 24.5 MHz when this //example is used with the SPI0_Slave // codeexample.
//----------------------------------------------------------------------------- // 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 // 1uints 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 bdatasta; //状态标志 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 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(unsignedchar* 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) { ; } }
// 辅助函数
void SYSCLK_Init (void) { OSCICN = 0x87; // configure internal oscillator for // 24.5MHz RSTSRC = 0x04; // enable missing clock detector }
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 }
void SPI0_Init() { SPI0CFG = 0x43; // Enable the SPI as aMaster
SPI0CN = 0x0D; // 4-wire Single Master, SPIenabled
//SPI clock frequency equation from the datasheet SPI0CKR =(SYSCLK/(2*SPI_CLOCK))-1; }
//----------------------------------------------------------------------------- // Support Routines //-----------------------------------------------------------------------------
uchar SPI_RW(uchar val) { SPIF=0; SPI0DAT=val; while(SPIF==0); returnSPI0DAT; }
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); // 返回状态寄存器 }
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); // 返回寄存器数据 }
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 = SPI_RW(0); // 逐个字节从nRF24L01读出 NSSMD0 = 1; // CSN拉高,结束数据传输 return(status); // 返回状态寄存器 }
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); // 逐个字节写入nRF24L01 NSSMD0 = 1; // CSN拉高,结束数据传输 return(status); // 返回状态寄存器 }
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); }
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(unsignedchar* 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来清楚中断标志 returnrevale; }
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); }
|