立即注册 登录
返回首页

uid:109572的个人空间

日志

基于nRF24L01的无线温湿度程序

已有 1437 次阅读2016-3-18 18:10 | 程序, 无线

  nRF24L01程序:

#ifndef __NRF24L01_H__

#define __NRF24L01_H__

 

#include<reg52.h>

#define uchar unsigned char

#define uint unsigned int

 

//NRF24L01寄存器操作命令

#define READ_REG        0x00  //读配置寄存器,5位为寄存器地址

#define WRITE_REG       0x20  //写配置寄存器,5位为寄存器地址

#define RD_RX_PLOAD     0x61  //RX有效数据,1~32字节

#define WR_TX_PLOAD     0xA0  //TX有效数据,1~32字节

#define FLUSH_TX        0xE1  //清除TX FIFO寄存器.发射模式下用

#define FLUSH_RX        0xE2  //清除RX FIFO寄存器.接收模式下用

#define REUSE_TX_PL     0xE3  //重新使用上一包数据,CE为高,数据包被不断发送.

#define NOP             0xFF  //空操作,可以用来读状态寄存器  

//SPI(NRF24L01)寄存器地址

#define CONFIG          0x00  //配置寄存器地址;bit0:1接收模式,0发射模式;bit1:电选择;bit2:CRC模式;bit3:CRC使能;

                              //bit4:中断MAX_RT(达到最大重发次数中断)使能;bit5:中断TX_DS使能;bit6:中断RX_DR使能

#define EN_AA           0x01  //使能自动应答功能  bit0~5,对应通道0~5

#define EN_RXADDR       0x02  //接收地址允许,bit0~5,对应通道0~5

#define SETUP_AW        0x03  //设置地址宽度(所有数据通道):bit1,0:00,3字节;01,4字节;02,5字节;

#define SETUP_RETR      0x04  //建立自动重发;bit3:0,自动重发计数器;bit7:4,自动重发延时 250*x+86us

#define RF_CH           0x05  //RF通道,bit6:0,工作通道频率;

#define RF_SETUP        0x06  //RF寄存器;bit3:传输速率(0:1Mbps,1:2Mbps);bit2:1,发射功率;bit0:低噪声放大器增益

#define STATUS          0x07  //状态寄存器;bit0:TX FIFO满标志;bit3:1,接收数据通道号(最大:6);bit4,达到最多次重发

                              //bit5:数据发送完成中断;bit6:接收数据中断;

#define MAX_TX     0x10  //达到最大发送次数中断

#define TX_OK        0x20  //TX发送完成中断

#define RX_OK    0x40  //接收到数据中断

 

#define OBSERVE_TX      0x08  //发送检测寄存器,bit7:4,数据包丢失计数器;bit3:0,重发计数器

#define CD              0x09  //载波检测寄存器,bit0,载波检测;

#define RX_ADDR_P0      0x0A  //数据通道0接收地址,最大长度5个字节,低字节在前

#define RX_ADDR_P1      0x0B  //数据通道1接收地址,最大长度5个字节,低字节在前

#define RX_ADDR_P2      0x0C  //数据通道2接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;

#define RX_ADDR_P3      0x0D  //数据通道3接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;

#define RX_ADDR_P4      0x0E  //数据通道4接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;

#define RX_ADDR_P5      0x0F  //数据通道5接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;

#define TX_ADDR         0x10  //发送地址(低字节在前),ShockBurstTM模式下,RX_ADDR_P0与此地址相等

#define RX_PW_P0        0x11  //接收数据通道0有效数据宽度(1~32字节),设置为0则非法

#define RX_PW_P1        0x12  //接收数据通道1有效数据宽度(1~32字节),设置为0则非法

#define RX_PW_P2        0x13  //接收数据通道2有效数据宽度(1~32字节),设置为0则非法

#define RX_PW_P3        0x14  //接收数据通道3有效数据宽度(1~32字节),设置为0则非法

#define RX_PW_P4        0x15  //接收数据通道4有效数据宽度(1~32字节),设置为0则非法

#define RX_PW_P5        0x16  //接收数据通道5有效数据宽度(1~32字节),设置为0则非法

#define FIFO_STATUS     0x17  //FIFO状态寄存器;bit0,RX FIFO寄存器空标志;bit1,RX FIFO满标志;bit2,3,保留

                              //bit4,TX FIFO空标志;bit5,TX FIFO满标志;bit6,1,循环发送上一数据包.0,不循环;

//24L01发送接收数据宽度定义

#define TX_ADR_WIDTH    5     //5字节的地址宽度

#define RX_ADR_WIDTH    5     //5字节的地址宽度

#define TX_PLOAD_WIDTH  32    //20字节的用户数据宽度

#define RX_PLOAD_WIDTH  32    //20字节的用户数据宽度

//硬件端口定义(模拟SPI

sbit CE  =P1^5;    //SPI片选

sbit SCK =P1^4;   //同步时钟

sbit MISO=P1^3;   //主进从出

sbit IRQ =P1^2;   //中断

sbit MOSI=P1^1;   //主出从进

sbit CSN =P1^0;   //芯片使能

//本地子函数声明

void init_io(void); //io口初始化

void RX_Mode(void); //接收模式

void TX_Mode(void); //发送模式

uchar NRF24L01_TxPacket(uchar *txbuf); //发送一次数据

uchar NRF24L01_RxPacket(uchar *rxbuf); //接送一次数据

 

#endif

 

#include"nrf24l01.h"

 

uchar code TX_ADDRESS[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01};  // 定义一个静态发送地址

uchar code RX_ADDRESS[RX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01};  //

/**************************************************

函数: init_io()

描述:初始化IO

/**************************************************/

void init_io(void)

{

CE  = 0;        // 待机

CSN = 1;        // SPI禁止

SCK = 0;        // SPI时钟置低

IRQ = 1;        // 中断复位

}

/**************************************************

函数:SPI_RW()

描述;根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01

      读出一字节

/**************************************************/

uchar SPI_RW(uchar byte)

{

uchar i;

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

    {

    MOSI = (byte & 0x80);   // byte最高位输出到MOSI

    byte <<= 1;             // 低一位移位到最高位

    SCK = 1;                // 拉高SCKnRF24L01MOSI读入1位数据,同时从MISO输出1位数据

    byte |= MISO;        // MISObyte最低位

    SCK = 0;             // SCK置低

    }

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

}

/**************************************************

函数:SPI_Write_Reg()

描述:写数据valuereg寄存器

/**************************************************/

uchar SPI_Write_Reg(uchar reg, uchar value)

{

uchar status;

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

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

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

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

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

}

/**************************************************

函数:SPI_Read_Reg()

描述:从reg寄存器读一字节

/**************************************************/

uchar SPI_Read_Reg(uchar reg)

{

uchar reg_val;

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

   SPI_RW(reg);                // 选择寄存器

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

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

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

}

/**************************************************

函数:SPI_Read_Buf(

描述:从reg寄存器读出bytes个字节,通常用来读取接收通道

  数据或接收/发送地址

/**************************************************/

uchar SPI_Read_Buf(uchar reg, uchar * pBuf, uchar bytes)

{

uchar status, i;

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

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

   for(i=0; i<bytes; i++)

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

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

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

}

/**************************************************/

 

/**************************************************

函数:SPI_Write_Buf()

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

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

/**************************************************/

uchar SPI_Write_Buf(uchar reg, uchar * pBuf, uchar bytes)

{

uchar status, i;

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

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

   for(i=0; i<bytes; i++)

     SPI_RW(pBuf[i]);        // 逐个字节写入nRF24L01

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

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

}

/**************************************************

函数:RX_Mode()

描述:这个函数设置nRF24L01为接收模式,等待接收发送设备的数据包

/**************************************************/

void RX_Mode(void)

{

CE = 0;

   SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH);  // 接收设备接收通道0使用和发送设备相同的发送地址

   SPI_Write_Reg(WRITE_REG + EN_AA, 0x01);               // 使能接收通道0自动应答

   SPI_Write_Reg(WRITE_REG + EN_RXADDR, 0x01);           // 使能接收通道0

   SPI_Write_Reg(WRITE_REG + RF_CH, 40);                 // 选择射频通道0x40

   SPI_Write_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH);  // 接收通道0选择和发送通道相同有效数据宽度

   SPI_Write_Reg(WRITE_REG + RF_SETUP, 0x0f);            // 数据传输率2Mbps,发射功率0dBm,低噪声放大器增益

   SPI_Write_Reg(WRITE_REG + CONFIG, 0x0f);              // CRC使能,16CRC校验,上电,接收模式

   CE = 1;                                               // 拉高CE启动接收设备

}

/**************************************************

函数:TX_Mode()

描述:这个函数设置nRF24L01为发送模式,(CE=1持续至少10us),

  130us后启动发射,数据发送结束后,发送模块自动转入接收

  模式等待应答信号。

/**************************************************/

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, TX_ADDRESS, TX_ADR_WIDTH);  // 为了应答接收设备,接收通道0地址和发送地址相同

   SPI_Write_Reg(WRITE_REG + EN_AA, 0x01);       // 使能接收通道0自动应答

   SPI_Write_Reg(WRITE_REG + EN_RXADDR, 0x01);   // 使能接收通道0

   SPI_Write_Reg(WRITE_REG + SETUP_RETR, 0x0a);  // 自动重发延时等待250us+86us,自动重发10

   SPI_Write_Reg(WRITE_REG + RF_CH, 40);         // 选择射频通道0x40

   SPI_Write_Reg(WRITE_REG + RF_SETUP, 0x0f);    // 数据传输率2Mbps,发射功率0dBm,低噪声放大器增益

   SPI_Write_Reg(WRITE_REG + CONFIG, 0x0e);      // CRC使能,16CRC校验,上电

CE = 1;

}

//启动NRF24L01发送一次数据

//txbuf:待发送数据首地址

//返回值:发送完成状况

uchar NRF24L01_TxPacket(uchar *txbuf)

{

uchar sta;

CE=0;

   SPI_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH); //写数据到TX BUF  32个字节

  CE=1; //启动发送    

while(IRQ!=0); //等待发送完成

sta=SPI_Read_Reg(STATUS);   //读取状态寄存器的值    

SPI_Write_Reg(WRITE_REG+STATUS,sta);  //清除TX_DSMAX_RT中断标志

if(sta&MAX_TX) //达到最大重发次数

{

SPI_Write_Reg(FLUSH_TX,0xff); //清除TX FIFO寄存器 

return MAX_TX; 

}

if(sta&TX_OK) //发送完成

{

return TX_OK;

}

return 0xff; //其他原因发送失败

}

//NRF24L01JIE接收送一次数据

//txbuf:接收数据首地址

//返回值:0,接收完成;其他,错误代码

uchar NRF24L01_RxPacket(uchar *rxbuf)

{

uchar sta;         

sta=SPI_Read_Reg(STATUS);   //读取状态寄存器的值      

SPI_Write_Reg(WRITE_REG+STATUS,sta);  //清除TX_DSMAX_RT中断标志

if(sta&RX_OK) //接收到数据

{

SPI_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH); //读取数据

SPI_Write_Reg(FLUSH_RX,0xff); //清除RX FIFO寄存器 

return 0; 

}    

return 1; //没收到任何数据

}


路过

鸡蛋

鲜花

握手

雷人

全部作者的其他最新日志

评论 (0 个评论)

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

返回顶部