[原创] NXP LPC1768宝马开发板 第十七NRF24L01 2.4G无线通信

旺宝电子   2015-2-6 10:13 楼主
第十七章  宝马1768——NRF24L01 2.4G无线通信
开发环境:集成开发环境μVision4 IDE版本4.60.0.0
主机系统:Microsoft Windows XP
开发平台:旺宝NXP LPC1768开发板


17.1 2.4G无线模块
17.2 硬件描述
17.3 程序说明
17.4  实验现象

本章我们主要介绍的是宝马开发板的预留接口2.4G无线模块,学习本章可以了解到2.4G通信原理,及使用两板进行通信。我们到目前为止,使用SPI接口的器件有字库(W25Q16)SD卡、2.4G、还有我们后面会接触到的XPT2046触摸芯片。都是使用SPI接口与MCU通信,看来掌握SPI的操作是很重要的。
12.4G无线模块:
nRF24L01是一款新型单片射频收发器件无线模块,工作全球免申请2.4 GHz2.5 GHz ISM频段,最大发射功率0dBm1mW。内置频率合成器、功率放大器、晶体振荡器、调制器等功能模块,并融合了增强型ShockBurst技术,其中输出功率和通信频道可通过程序进行配置。nRF24L01功耗低,在以-6dBm的功率发射时,工作电流也只有9 mA;接收时,工作电流只有12.3 mA,多种低功率工作模式(掉电模式和空闲模式)使节能设计更方便。
主要特性:
1)支持六路通道的数据接收
2)低工作电压:1.9-3.6V低电压工作
3)高速率:2Mbps(软件设置1Mbps2Mbps
4)多点频:125频点,满足多点通信和调频通信需要(2400+RF_CH
5)nRF24L01集成了所有与RF协议相关的高速信号处理部分
6)SPI接口可以方便和单片机进行通信
图片1.png
如上图,nRF24L01与单片机的接口,具体功能如下表描述
引脚
名称
描述
1
GND
2
VCC
电源
3
CE
发送接收使能
4
CSN
片选(低电平使能)
5
SCK
SPI时钟
6
MOSI
SPI从机接收
7
MISO
SPI从机发送
8
IRQ
可屏蔽中断引脚(低电平使能)
工作模式:
1) nRF24L01有四种工作模式:
2) 收发模式
3) 配置模式
4) 空闲模式
5) 关机模式
图片2.png
数据发射:发射数据时,首先将nRF24L01配置为发射模式:接着把接收节点地址TX_ADDR和有效数据TX_PLD按照时序由SPI口写入nRF24L01缓存区,TX_PLD必须在CSN为低时连续写入,而TX_ADDR在发射时写入一次即可,然后CE置为高电平并保持至少10μs,延迟130μs后发射数据;若自动应答开启,那么nRF24L01在发射数据后立即进入接收模式,接收应答信号(自动应答接收地址应该与接收节点地址TX_ADDR一致)。如果收到应答,则认为此次通信成功,TX_DS置高,同时TX_PLDTX FIFO中清除;若未收到应答,则自动重新发射该数据(自动重发已开启),若重发次数(ARC)达到上限,MAX_RT置高,TX FIFO中数据保留以便再次重发;MAX_RTTX_DS置高时,使IRQ变低,产生中断,通知MCU。最后发射成功时,若CE为低则nRF24L01进入空闲模式1;若发送堆栈中有数据且CE为高,则进入下一次发射;若发送堆栈中无数据且CE为高,则进入空闲模式2
数据接收:接收数据时,首先将nRF24L01配置为接收模式,接着延迟130μs进入接收状态等待数据的到来。当接收方检测到有效的地址和CRC时,就将数据包存储在RX FIFO中,同时中断标志位RX_DR置高,IRQ变低,产生中断,通知MCU去取数据。若此时自动应答开启,接收方则同时进入发射状态回传应答信号。最后接收成功时,若CE变低,则nRF24L01进入空闲模式1
NRF24L01的读写时序:
LPC1768通过SSP0接口对nRF24L01进行配置,具体指令及寄存器请参考手册,其指令格式如下
命令字:由高位到低位(每字节)
数据字节:低字节到高字节,每一字节高位在前
任何一条新指令均由CSN 的由高到低的转换开始,下图为SPI操作及时序。 在写寄存器之前一定要进入待机模式或掉电模式。
图片3.png
读操作
图片4.png
写操作
   
2、硬件描述:
   了解了NRF24L01的基本工作模式和读写时序,我们再来看看它是如何与1768连接的。
图片5.png
3、程序说明:
   本次实验使用两块宝马开发板(带nRF24L01无线模块)进行通信,板A为主动发射端,板B为被动接收端。
A:初始化完成后,进入主循环通过无线模块发送数据
B:初始化完成后进入循环查询NRF24L01是否有数据接收到,当接收到板A发送过来的数据后,将数据通过串口打印出来。
如下图是LPC1768nRF24L01的接口描述,其中P1.20P1.23P1.24分别为SSP0SCKMISOMOSI引脚,P1.21CSNP2.0CEP2.1接可屏蔽中断引脚。
图片6.png
LPC1768nRF24L01的配置及读写代码如下:
uchar SPI1_NRF_SendByte(unsigned char byte)
{
  LPC_SSP0->DR = byte;
  while (LPC_SSP0->SR & 0x10);      //等待发送完成          
                return (LPC_SSP0->DR);       //返回接收到的值
}
/*写数据到寄存器,并返回寄存器读回的数据*/
uchar SPI_RW_Reg(uchar reg, uchar value)       
{
unsigned int Data = 0;   
Select_NRF();                                                    //选择NRF24L01片选
Data=SPI1_NRF_SendByte(reg);                    //指定NRF24L01寄存器
SPI_NRF_SendByte(value);                                //写入数据
NotSelect_NRF();                                                 //禁止NRF24L01片选
return(Data);                                //返回NRF24L01 写寄存器的状态信息
}
/*读取寄存器中的数据*/
unsigned char SPI_Read(unsigned char reg)
{
unsigned char Data;
Select_NRF();                                                        //选择NRF24L01片选
SPI1_NRF_SendByte(reg);                                //指定NRF24L01寄存器
        Data=SPI1_NRF_SendByte(0);                //读出数据
        NotSelect_NRF();                                             //禁止NRF24L01片选
        return (Data);
}
/*读取批量数据并存在pBuf缓冲区*/
uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar bytes)
{
        unsigned char status,i;
          Select_NRF();                //选择NRF24L01片选
          status=SPI_NRF_SendByte(reg); //读出指定NRF24L01寄存器的状态信息
          for(i=0; i读出指定长度的数据
    {                 
                pBuf=SPI1_NRF_SendByte(0);                 
        }       
          NotSelect_NRF();             //禁止NRF24L01片选
          return(status);                //返回指定NRF24L01寄存器的状态信息
}
/*写缓冲*/
uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar bytes)
{
        unsigned char status,byte_ctr;
          Select_NRF();                   //选择NRF24L01片选
          status=SPI1_NRF_SendByte(reg);          //指定NRF24L01寄存器
         
          for(byte_ctr=0; byte_ctr写入指定长度的数据
    {
                SPI1_NRF_SendByte(*pBuf++);         
        }       
          NotSelect_NRF();          //禁止NRF24L01片选
          return(status);                  //返回NRF24L01 写寄存器的状态信息
}
/*ssp0初始化*/
void  ssp0_init(void)
{  
  LPC_SC->PCONP       |= (1 << 21);            //Enable power to SSPI0 block
  LPC_GPIO1->FIODIR   |=  (1<<21);     //P1.21初始化SSEL         
  LPC_GPIO1->FIOPIN   |=  (1<<21);     //设置为高电平
  LPC_PINCON->PINSEL3 &= ~(0<<10);    //P1.21做普通IO
  LPC_GPIO3->FIODIR   |=  (1<<26);     //P3.26输出        
  LPC_GPIO3->FIOPIN   &= ~(1<<26);     //P3.26输出低电平 关闭SD
  LPC_PINCON->PINSEL3 &= ~(3<<8);                          
  LPC_PINCON->PINSEL3 |=  (3<<8);            // P1.20设置为SCK0              
  LPC_PINCON->PINSEL3 &= ~((3<<14) | (3<<16));              
  LPC_PINCON->PINSEL3 |=  ((3<<14) | (3<<16));         // P1.23设置为MISO0, P1.24 设置为MOSI0   
  LPC_SC->PCLKSEL1 &= ~(3<<10);       // PCLKSP0 = CCLK/4 ( 25MHz)   
  LPC_SC->PCLKSEL1 |=  (1<<10);        // PCLKSP0 = CCLK   (100MHz)   
  LPC_SSP0->CPSR = 250;                 //72MHz / 250 = 400kBit      
                                                                                          //maximum of 18MHz is possible   
  LPC_SSP0->CR0  = 0x0007;              // 8Bit, CPOL=0, CPHA=0        
  LPC_SSP0->CR1  = 0x0002;               // SSP0 enable, master        
}
/*初始化RF24L01内部数据*/
void config_24L01()
{
RF24L01_Gpio_Init();        //IO初始化
NotSelect_NRF();                //禁止SPI2 NRF24L01+的片选。
ssp0_init();                                //ssp0初始化
}
/*24L01初始化*/
void Init_24L01(void)
{       
uchar Channel=2;                //工作通道频率=2400+2=2.402G
config_24L01();
SPI_RW_Reg(WRITE_REGL + CONFIG,0x79);         //屏蔽所有中断、接收模式
SPI_RW_Reg(WRITE_REGL + EN_AA,0x00);        //禁止自动应答
SPI_RW_Reg(WRITE_REGL + EN_RXADDR,0x01);        //接收数据通道0允许
SPI_RW_Reg(WRITE_REGL + SETUP_AW,0x03);//接收发射地址宽度5字节
SPI_RW_Reg(WRITE_REGL + SETUP_RETR,0x00);        //禁止自动重发
SPI_RW_Reg(WRITE_REGL + RF_CH,Channel);                //设置工作通道频率
SPI_RW_Reg(WRITE_REGL + RF_SETUP,0x07);        //传输速率1Mbps0dBm
SPI_RW_Reg(WRITE_REGL + STATUS,0x70);                //清空中断标志
SPI_Write_Buf(WRITE_REGL+RX_ADDR_P0,TX_ADDRESS, RX_ADR_WIDTH); //数据通道0接收地址
SPI_Write_Buf(WRITE_REGL + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);                                            //发送地址       
SPI_RW_Reg(WRITE_REGL + RX_PW_P0,0x04);       
//接收数据通道0有效数据宽度4字节
CSN(0);               
SPI_NRF_SendByte(0xE2);        //清除RX FIFO寄存器
CSN(1);               
CSN(0);               
SPI_NRF_SendByte(0xE1);        //清除TX FIFO寄存器
CSN(1);               
}
/*发送数据*/
void send(uchar *Buffdata,uchar Length)
{
CE(0);       
SPI_RW_Reg(WRITE_REGL + CONFIG,0x1e);//CRC16位校验 发送模式
SPI_RW_Reg(FLUSH_TX,0);        //清除TX FIFO寄存器 用于发射模式下
SPI_Write_Buf(WR_TX_PLOAD, Buffdata ,Length);
//TX有效数据Buffdata Length字节
CE(1);       
Delay1ms(5);
CE(0);       
SPI_RW_Reg(WRITE_REGL + STATUS,0x70);        //清除中断标志
}
/*设置接收模式*/
void Set_RF_RX_Mode(uchar DataLength)
{
SPI_RW_Reg(WRITE_REGL + RX_PW_P0,DataLength);        //设置接收数据通道0有效数据宽度DataLength
SPI_RW_Reg(WRITE_REGL + CONFIG,0x5f);//CRC 16位  接收模式
SPI_RW_Reg(WRITE_REGL + STATUS,0x70);//清除中断标志
SPI_RW_Reg(FLUSH_RX,0);        //清除RX FIFO寄存器 用于接收模式下
CE(1);       
}
其中具体的寄存器定义及其设置可以参考源程序中24L01头文件的定义和NRF24L01手册。本历程包含了发送和接收,通过宏定义来设置
当作为接收板时修改宏定义如下:
图片7.png
当作为发送板时修改宏定义如下:
图片8.png
当定义为接收板时条件编译选择运行红色框框内的程序,当定义为发送板时,条件编译选择运行蓝色框框内的程序。从下面的程序中可以看出当作为接收板时开始串口打印数据“NRF24L01接收板”后初始化NRF模块,循环查询是否有数据接收到。当作为发送板时从串口打印数据“NRF24L01发送板”后初始化NRF模块,每隔100ms通过NRF24L01发送四个字符“ab0d 图片9.png
4、实验现象:
   将开发板USB转串口(usb1)与电脑相连,插上nRF24L01,下载程序后,重新上电,打开串口调试助手(波特率9600),板A从串口打印出来“NRF24L01发送板”,板B从串口打印出来“NRF24L01接收板”,随后打印NRF24L01接收到的数据。

http://openmcu.taobao.com]77[/url]

回复评论 (3)

不错,继续更新。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
我的博客
点赞  2015-2-6 13:31
XP还在用么,换win7能支持不
点赞  2015-2-6 19:53
引用: qwqwqw2088 发表于 2015-2-6 19:53
XP还在用么,换win7能支持不



可以用W7的
http://openmcu.taobao.com]77[/url]
点赞  2015-2-9 14:49
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复