nrf24l01无线模块c语言程序,关于NRF24L01无线模块的C52双向通讯C程序(中文详解)...

#include

#include

typedef unsigned char uchar;

typedef unsigned char uint;

sbit  NC

=P2^0;

//没用,不接也可

sbit MISO =P2^5; //数字输出(从 SPI 数据输出脚)

sbit MOSI =P2^4; //数字输入(从 SPI 数据输入脚)

sbit SCK  =P1^7;

//数字输入(SPI 时钟)

sbit CE  =P2^1; //数字输入(RX

或 TX 模式选择)

sbit CSN =P2^2; //数字输入(SPI片选信号)

sbit IRQ =P2^6; //数字输入(可屏蔽中断)

sbit KEY1=P3^3;//按键S1

sbit KEY2=P3^2;//按键S2

sbit led1=P1^0; //LED0

sbit led2=P1^1; //LED1

sbit  led3 =P1^2;

//LED2

sbit  led4 =P1^3;

//LED3

sbit  led5 =P1^4;

//LED4

#define TX_ADR_WIDTH  5

// 5 uints TX address width

#define RX_ADR_WIDTH  5

// 5 uints RX address width

#define TX_PLOAD_WIDTH  20  // 20 uints TX payload

#define RX_PLOAD_WIDTH  20  // 20 uints TX payload

uint const TX_ADDRESS[TX_ADR_WIDTH]=

{0x34,0x43,0x10,0x10,0x01}; //本地地址

uint const RX_ADDRESS[RX_ADR_WIDTH]=

{0x34,0x43,0x10,0x10,0x01}; //接收地址

#define READ_REG  0x00  //

读寄存器指令

#define WRITE_REG  0x20 // 写寄存器指令

#define RD_RX_PLOAD  0x61

// 读取接收数据指令

#define WR_TX_PLOAD  0xA0

// 写待发数据指令

#define FLUSH_TX  0xE1 // 冲洗发送 FIFO指令

#define FLUSH_RX  0xE2  //

冲洗接收 FIFO指令

#define REUSE_TX_PL  0xE3

// 定义重复装载数据指令

#define NOP  0xFF  // 保留

#define CONFIG  0x00

// 配置收发状态,CRC校验模式以及收发状态响应方式

#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 CD  0x09  // 地址检测

#define RX_ADDR_P0  0x0A  // 频道0接收数据地址

#define RX_ADDR_P1  0x0B  // 频道1接收数据地址

#define RX_ADDR_P2  0x0C  // 频道2接收数据地址

#define RX_ADDR_P3  0x0D  // 频道3接收数据地址

#define RX_ADDR_P4  0x0E  // 频道4接收数据地址

#define RX_ADDR_P5  0x0F  // 频道5接收数据地址

#define TX_ADDR  0x10  //

发送地址寄存器

#define RX_PW_P0  0x11  //

接收频道0接收数据长度

#define RX_PW_P1  0x12  //

接收频道0接收数据长度

#define RX_PW_P2  0x13  //

接收频道0接收数据长度

#define RX_PW_P3  0x14  //

接收频道0接收数据长度

#define RX_PW_P4  0x15  //

接收频道0接收数据长度

#define RX_PW_P5  0x16  //

接收频道0接收数据长度

#define FIFO_STATUS  0x17

// FIFO栈入栈出状态寄存器设置

void Delay(unsigned int s);  //大延时

void inerDelay_us(unsigned char n); //小延时

void init_NRF24L01(void);  //NRF24L01

初始化

uint SPI_RW(uint dat);

//根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01读出一字节

uchar SPI_Read(uchar reg);

//从reg寄存器读一字节

void SetRX_Mode(void);  //数据接收配置

uint SPI_RW_Reg(uchar reg, uchar value);

//写数据value到reg寄存器

uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars);

//从reg寄存器读出bytes个字节,通常用来

//读取接收通道数据或接收/发送地址

uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars);

//把pBuf缓存中的数据写入到nRF24L01,通常用来写入发

//射通道数据或接收/发送地址

unsigned char nRF24L01_RxPacket(unsigned char* rx_buf);

//数据读取后放入rx_buf接收缓冲区中

void nRF24L01_TxPacket(unsigned char * tx_buf);

//发送 tx_buf中数据

void Delay(unsigned int s)

{

unsigned int i;

for(i=0; i

for(i=0; i

}

uint bdata sta;  //状态标志

sbit RX_DR =sta^6; //RX_DR 为 sta 的第六位

sbit TX_DS =sta^5; //TX_DS 为 sta 的第五位

sbit MAX_RT =sta^4; //MAX_RT 为 sta 的第四位

void inerDelay_us(unsigned char n) //延时,us 级

{

for(;n>0;n--)

_nop_();

}

void init_NRF24L01(void)

{

inerDelay_us(100);

CE=0;  // 芯片使能

CSN=1;  // 禁止

SPI

SCK=0;  // SPI时钟置低

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); // 写接收端地址

SPI_RW_Reg(WRITE_REG + EN_AA, 0x01);  //  频道0自动

ACK应答允许

SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);  //

允许接收地址只有频道0,如果需要多频道可以参考Page21

SPI_RW_Reg(WRITE_REG + RF_CH, 0);  //

设置信道工作为2.4GHZ,收发必须一致

SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH);

//设置接收数据长度,本次设置为32字节

SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07);  //设置发射速率为1MHZ,发射功率为最大值0dB

}

uint SPI_RW(uint dat)

{

uint i;

for(i=0;i<8;i++) // 循环8次

{

MOSI = (dat & 0x80);  //

dat的最高位输出到MOSI  MSB to MOSI

dat = (dat << 1);

// 从右向左进一位  shift next bit into MSB..

SCK = 1;  //

拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据  Set SCK

high..

dat |= MISO;  //读MISO到

dat 最低位  capture current MISO bit

SCK = 0;  // SCK置低  ..then set SCK low again

}

return(dat);  //返回读出的一字节  return read dat

}

uchar SPI_Read(uchar reg)

{

uchar reg_val;

CSN = 0;  //CSN置低,开始传输数据  CSN low,

initialize SPI communication...

SPI_RW(reg);  //选择寄存器  Select register to read

from..

reg_val = SPI_RW(0); //然后从该寄存器读数据  ..then

read registervalue

CSN = 1;  //CSN拉高,结束数据传输  CSN high,

terminate SPI communication

return(reg_val);  //返回寄存器数据  return register value

}

uint SPI_RW_Reg(uchar reg, uchar value)

{

uchar status;

CSN = 0;  // CSN置低,开始传输数据

CSN low,

init SPI transaction

status = SPI_RW(reg);  // 选择寄存器,同时返回状态字

select register

SPI_RW(value);  // 然后写数据到该寄存器

..and

write value to it..

CSN = 1;  // CSN拉高,结束数据传输

CSN high

again

return(status);  // 返回状态寄存器  return nRF24L01 status

uchar

}

uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)

{

uint status,i;

CSN = 0;  //CSN置低,开始传输数据  Set CSN low, init SPI

tranaction

status = SPI_RW(reg);  //选择寄存器,同时返回状态字 Select register to write to and

read status uchar

for(i=0;i

pBuf[i] = SPI_RW(0); //逐个字节从nRF24L01读出

CSN = 1;  //CSN拉高,结束数据传输

return(status);  //返回状态寄存器

return

nRF24L01 status uchar

}

uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)

{

uint status,i;

CSN = 0;  //CSN置低,开始传输数据

status = SPI_RW(reg);  //选择寄存器,同时返回状态字

inerDelay_us(10);

for(i=0; i

SPI_RW(*pBuf++); //逐个字节写入nRF24L01

CSN = 1;  //CSN拉高,结束数据传输

return(status);  //返回状态寄存器

}

void SetRX_Mode(void)

{

CE=0;

SPI_RW_Reg(WRITE_REG + CONFIG,

0x0f);//CRC使能,16位CRC校验,上电,接收模式

CE = 1;  //

拉高CE启动接收设备

inerDelay_us(130);

}

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)

{

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,激发数据发送

inerDelay_us(10);

}

void main(void)

{

unsigned char tf =0;

unsigned char TxBuf[20]={0}; // 要发送的数组

unsigned char RxBuf[20]={0}; // 接收的数据 数组

init_NRF24L01() ; //模块初始化

led1=1;led2=1;led3 =1;led4 =1; //led 灯关闭

Delay(1000);

while(1)

{

if(KEY1 ==0 ) //按键 1 按下

{

TxBuf[1] = 1 ; //赋值

tf = 1

;

led1=0; //本地led 灯闪烁

Delay(200);

led1=1;

Delay(200);

}

if(KEY2 ==0 )  //按键 2

按下

{

TxBuf[2] =1 ; //赋值

tf = 1 ;

led2=0; //本地led 灯闪烁

Delay(200);

led2=1;

Delay(200);

}

if (tf==1) //有键按下

{

nRF24L01_TxPacket(TxBuf); //发送数据 Transmit Tx buffer data

TxBuf[1] = 0x00; //清零

TxBuf[2] = 0x00;

tf=0;

Delay(1000);

}

SetRX_Mode();  //设置成接受模式

RxBuf[1] = 0x00;  //接收的数组相应位清零

RxBuf[2] = 0x00;

Delay(1000);

nRF24L01_RxPacket(RxBuf);  //接收数据

if(RxBuf[1]|RxBuf[2])

{

if( RxBuf[1]==1)

{

led3=RxBuf[0];

}

if( RxBuf[2]==1)

{

led4=RxBuf[4];

}

Delay(3000); //old is '1000'

}

RxBuf[1] = 0x00;  //清零

RxBuf[2] = 0x00;

led3=1;  //关灯

led4=1;

}

}

本程序存在的问题:反应不够灵敏,当在按键1和按键2之间切换的时候,对方的灯闪烁会有一定的延时,另外本程序没有消除按键的抖动。

对部分函数的解释:

uint SPI_RW(uint

dat)

最基本的函数,完成 GPIO模拟 SPI 的功能。将输出字节(MOSI)从 MSB

循环输出,

同时将输入字节(MISO)从

LSB 循环移入。上升沿读入,下降沿输出。 (从 SCK被初始化

为低电平可以判断出)

uchar SPI_Read(uchar

reg);

//从reg寄存器读一字节

读取寄存器值的函数:基本思路就是通过 READ_REG命令(也就是 0x00+寄存器地址)

,把

寄存器中的值读出来。对于函数来说也就是把 reg 寄存器的值读到 reg_val 中去。

uint

SPI_RW_Reg(uchar reg, uchar

value); //写数据value到reg寄存器

寄存器访问函数:用来设置 24L01 的寄存器的值。基本思路就是通过

WRITE_REG命令(也

就是

0x20+寄存器地址)把要设定的值写到相应的寄存器地址里面去,并读取返回值。对于

函数来说也就是把

value值写到 reg 寄存器中。

需要注意的是,访问

NRF24L01 之前首先要 enable 芯片(CSN=0; ) ,访问完了以后再 disable

芯片(CSN=1;

)。

uint

SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars);

//从reg寄存器读出bytes个字节,通常用来

//读取接收通道数据或接收/发送地址

接收缓冲区访问函数:主要用来在接收时读取 FIFO

缓冲区中的值。基本思路就是通过

READ_REG命令把数据从接收

FIFO(RD_RX_PLOAD)中读出并存到数组里面去。

uint

SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars);

//把pBuf缓存中的数据写入到nRF24L01,通常  //用来写入发

发射缓冲区访问函数:主要用来把数组里的数放到发射 FIFO缓冲区中。基本思路就是通过

WRITE_REG命令把数据存到发射 FIFO(WR_TX_PLOAD)中去。

Tx  模式初始化过程

1)写 Tx 节点的地址 TX_ADDR

2)写 Rx 节点的地址(主要是为了使能 Auto Ack)

RX_ADDR_P0

3)使能 AUTO ACK EN_AA

4)使能 PIPE 0 EN_RXADDR

5)配置自动重发次数 SETUP_RETR

6)选择通信频率 RF_CH

7)配置发射参数(低噪放大器增益、发射功率、无线速率) RF_SETUP

8 )  选择通道0  有效数据宽度

Rx_Pw_P0

9)配置 24L01 的基本参数以及切换工作模式 CONFIG。

Rx 模式初始化过程:

初始化步骤 24L01 相关寄存器

1)写 Rx 节点的地址 RX_ADDR_P0

2)使能 AUTO ACK EN_AA

3)使能 PIPE 0 EN_RXADDR

4)选择通信频率 RF_CH

5)  选择通道0  有效数据宽度

Rx_Pw_P0

6)配置发射参数(低噪放大器增益、发射功率、无线速率) RF_SETUP

7)配置 24L01 的基本参数以及切换工作模式 CONFIG。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值