NRF24L01实现msp430单片机通信(SPI)

本文介绍了一种基于24L01无线模块的简单应用实例,包括配置参数、SPI通信过程及发送接收数据的具体实现。通过具体代码展示了如何初始化模块进入发送或接收模式,并实现每秒发送一次数据。

24l01.h

#ifndef _24L01_H_

#define _24L01_H_




/***************************************************/
typedef unsigned char     BYTE;


#define uchar unsigned char


//24L01发送接收数据宽度定义
#define TX_ADR_WIDTH    5   //5字节的地址宽度
#define RX_ADR_WIDTH    5   //5字节的地址宽度
#define TX_PLOAD_WIDTH  7  //20字节的用户数据宽度
#define RX_PLOAD_WIDTH  7  //20字节的用户数据宽度




#define nRF_TX_Mode 0x00
#define nRF_RX_Mode 0x01
///****************************************************************//
// 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
//========================
//STATUS REG ?μ?÷
#define MAX_RT   0x10  //′?μ?×?′ó·¢?í′?êy?D??
#define TX_OK   0x20  //TX·¢?ííê3é?D??
#define RX_OK   0x40  //?óê?μ?êy?Y?D??
/**************************************************/
#define nRF24L01_CE_1         P4OUT |=  BIT4              //CE = 1
#define nRF24L01_CE_0         P4OUT &=~ BIT4            //CE = 0
#define nRF24L01_CSN_1       P4OUT |=  BIT5             //CSN = 1
#define nRF24L01_CSN_0       P4OUT &=~ BIT5            //CSN = 0
#define nRF24L01_SCK_1       P5OUT |=  BIT3              //SCK = 1
#define nRF24L01_SCK_0       P5OUT &=~ BIT3            //SCK = 0
#define nRF24L01_MOSI_1   P5OUT |=  BIT2         //MOSI = 1
#define nRF24L01_MOSI_0   P5OUT &=~ BIT2       //MOSI = 0
#define nRF24L01_MISO_IN     ((P5IN>>1)  & 0x01)    //读入MISO,P5.1//((P5IN >> 1) & 0x04) 
/**************************************************/
/**************************************************/
///===============REG setting data===============
//===0x00 CONFIG===============
#define MASK_RX_DR 0x40
#define MASK_TX_DS 0x20
#define MASK_MAX_RT 0x10
#define EN_CRC 0x08
#define CRCO 0x04// 0---1byte,1---2byte
#define PWR_UP 0x02// 1---power up,0---power down
#define PRIM_RX 0x01// 1---RX mode,0---TX mode
//===0x01 EN_AA================
//使能自响应通道,默认5通道全开
#define ENAA_P5 0x20
#define ENAA_P4 0x10
#define ENAA_P3 0x08
#define ENAA_P2 0x04
#define ENAA_P1 0x02
#define ENAA_P0 0x01
#define ENAA_DisableALL 0x00
//===0x02 EN_RXADDR============
#define ERX_P5 0x20
#define ERX_P4 0x10
#define ERX_P3 0x08
#define ERX_P2 0x04
#define ERX_P1 0x02
#define ERX_P0 0x01
#define ERX_None 0x00
//===0x03 SETUP_AW=============
#define AW_3Bytes 0x01
#define AW_4Bytes 0x02
#define AW_5Bytes 0x03
//===0x04 SETUP_RETR============
#define AutoReTxDalay_250uS 0x00//default
#define AutoReTxDalay_500uS 0x10
#define AutoReTxDalay_750uS 0x20
#define AutoReTxDalay_1000uS 0x30
#define AutoReTxDalay_1250uS 0x40
#define AutoReTxDalay_1500uS 0x50
#define AutoReTxDalay_1750uS 0x60
#define AutoReTxDalay_2000uS 0x70
#define AutoReTxDalay_2250uS 0x80
#define AutoReTxDalay_2500uS 0x90
#define AutoReTxDalay_2750uS 0xA0
#define AutoReTxDalay_3000uS 0xB0
#define AutoReTxDalay_3250uS 0xC0
#define AutoReTxDalay_3500uS 0xD0
#define AutoReTxDalay_3750uS 0xE0
#define AutoReTxDalay_4000uS 0xF0
#define AutoReTx_Disable 0x00
#define AutoReTxTimes_1 0x01
#define AutoReTxTimes_2 0x02
#define AutoReTxTimes_3 0x03//default
#define AutoReTxTimes_4 0x04
#define AutoReTxTimes_5 0x05
#define AutoReTxTimes_6 0x06
#define AutoReTxTimes_7 0x07
#define AutoReTxTimes_8 0x08
#define AutoReTxTimes_9 0x09
#define AutoReTxTimes_10 0x0A
#define AutoReTxTimes_11 0x0B
#define AutoReTxTimes_12 0x0C
#define AutoReTxTimes_13 0x0D
#define AutoReTxTimes_14 0x0E
#define AutoReTxTimes_15 0x0F
//===0x06 RF_SETUP============
#define RF_DR_1Mbps 0x00
#define RF_DR_2Mbps 0x08
//#define RF_PWR_




uchar SPI_RW(uchar byte);
uchar SPI_RW_Reg(BYTE reg, BYTE value);
BYTE SPI_Read(BYTE reg);
uchar SPI_Read_Buf(BYTE reg, BYTE *pBuf, BYTE bytes);
uchar SPI_Write_Buf(BYTE reg, BYTE const *pBuf, BYTE bytes);
void RX_Mode(void);
void TX_Mode(void);
void nRF24L01_Init(unsigned char Mode);
void nRF24L01_Send(void);
void nRF24L01_Revceive(void);
uchar NRF_Check(void);
void nRF24L01_IO_set(void);


#endif


24l01.c


#include  <msp430x14x.h>
#include "24l01.h"


unsigned char TestBuf=0;




uchar  const TX_ADDRESS[TX_ADR_WIDTH]  = {0x6d,0x61,0x67,0x69,0x63}; // Define a static TX address
uchar rx_buf[RX_PLOAD_WIDTH];        
uchar tx_buf[TX_PLOAD_WIDTH]={0xB3,0x73,0x6b,0x79,0x00,0x00,0x00};//,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02};
uchar flag,q;


//******************************************************************************************
//延时函数
//******************************************************************************************


void delay_50us(unsigned int i)
{
//for(unsigned char i=0; i<77; i++);
unsigned long j;
for(;i>0;i--)
{
for(j=0;j<33;j++);//50.4us
}
}


void delay_100ms(unsigned int i)
{
unsigned long j;
for(;i>0;i--)
{
for(j=0;j<144200;j++);
}
}


void msDelay(unsigned int ms)
{
    unsigned int i,j;

    for(i=0;i<ms;i++)
    {
       j=1329;;
       while(j--);
    }
}
void delay_1ms(unsigned int i)
{
unsigned long j;
for(;i>0;i--)
{
//for(j=0;j<640;j++);//8M--->880us
for(j=0;j<730;j++);//8M--->1ms
//for(j=0;j<80;j++);//1M
//for(j=0;j<200;j++);//1M 1ms延时是对的,但345数据在12ms就准备完成了,这影响后面计数
}
}
void inerDelay_us(int n)
{
for(;n>0;n--);
}


//***********************************************************************************
void CE_Pin(BYTE state)
{
    if(state)
    nRF24L01_CE_1;
  else
    nRF24L01_CE_0;
}


//***********************************************************************************
//***********************************************************************************
void CSN_Pin(BYTE state)                                // Set/reset CSN pin
{
    if(state)
    nRF24L01_CSN_1;
  else
    nRF24L01_CSN_0;
}
//***********************************************************************************
//***********************************************************************************
void SCK_Pin(BYTE state)                                // Set/reset SCK pin
{
  if(state)
    nRF24L01_SCK_1;
  else
    nRF24L01_SCK_0;
}
//***********************************************************************************
//***********************************************************************************
void MOSI_Pin(BYTE state)                               // Set/reset MOSI pin
{
  if(state)
    nRF24L01_MOSI_1;
  else
    nRF24L01_MOSI_0;
}
//***********************************************************************************
//***********************************************************************************


BYTE MISO_Pin(void)                                     // Read MISO pin
{
  return nRF24L01_MISO_IN;
}
//**************************************************
//Function: SPI_RW();


//escription:
 // Writes one byte to nRF24L01, and return the byte read
 // from nRF24L01 during write, according to SPI protocol
//**************************************************/
uchar SPI_RW(uchar byte)
{
uchar bit_ctr;
    for(bit_ctr=0;bit_ctr<8;bit_ctr++)   // output 8-bit
    {
    MOSI_Pin(byte&0x80);         // output 'byte', MSB to MOSI
    byte = (byte << 1);           // shift next bit into MSB..
    SCK_Pin(1);// Set SCK high..
    byte|=MISO_Pin();        // capture current MISO bit
    SCK_Pin(0);              // ..then set SCK low again
    }
    return(byte);            // return read byte
}
/**************************************************/


//**************************************************
//Function: SPI_RW_Reg();


//Description:
 // Writes value 'value' to register 'reg'
//**************************************************/
uchar SPI_RW_Reg(BYTE reg, BYTE value)
{
        uchar status;
  CSN_Pin(0);                   // CSN low, init SPI transaction
  status = SPI_RW(reg);      // select register
  SPI_RW(value);             // ..and write value to it..
  CSN_Pin(1);                   // CSN high again


  return(status);            // return nRF24L01 status byte
        
}
/**************************************************/


/**************************************************
Function: SPI_Read();


Description:
  Read one byte from nRF24L01 register, 'reg'
**************************************************/
BYTE SPI_Read(BYTE reg)
{
BYTE reg_val;


  CSN_Pin(0);                // CSN low, initialize SPI communication...
  SPI_RW(reg);            // Select register to read from..
  reg_val = SPI_RW(0);    // ..then read registervalue
  CSN_Pin(1);                // CSN high, terminate SPI communication


  return(reg_val);        // return register value
}
/**************************************************/


/**************************************************
Function: SPI_Read_Buf();


Description:
  Reads 'bytes' #of bytes from register 'reg'
  Typically used to read RX payload, Rx/Tx address
**************************************************/
uchar SPI_Read_Buf(BYTE reg, BYTE *pBuf, BYTE bytes)
{
uchar status,byte_ctr;


  CSN_Pin(0);                     // Set CSN low, init SPI tranaction
  status = SPI_RW(reg);       // Select register to write to and read status byte


  for(byte_ctr=0;byte_ctr<bytes;byte_ctr++)
    pBuf[byte_ctr] = SPI_RW(0);    // Perform SPI_RW to read byte from nRF24L01


  CSN_Pin(1);                           // Set CSN high again


  return(status);                    // return nRF24L01 status byte
}
/**************************************************/


/**************************************************
Function: SPI_Write_Buf();


Description:
  Writes contents of buffer '*pBuf' to nRF24L01
  Typically used to write TX payload, Rx/Tx address
**************************************************/
uchar SPI_Write_Buf(BYTE reg, BYTE const *pBuf, BYTE bytes)
{
uchar status,byte_ctr;


  CSN_Pin(0);                  // Set CSN low, init SPI tranaction
  status = SPI_RW(reg);    // Select register to write to and read status byte
  for(byte_ctr=0; byte_ctr<bytes; byte_ctr++) // then write all byte in buffer(*pBuf)
    SPI_RW(*pBuf++);
  CSN_Pin(1);                 // Set CSN high again
  return(status);          // return nRF24L01 status byte
}
/**************************************************/


//***********************************************************************************
/**************************************************
Function: RX_Mode();


Description:
  This function initializes one nRF24L01 device to
  RX Mode, set RX address, writes RX payload width,
  select RF channel, datarate & LNA HCURR.
  After init, CE is toggled high, which means that
  this device is now ready to receive a datapacket.
**************************************************/
void RX_Mode(void)
{
        CE_Pin(0);
SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);    // D′±?μ?μ??·
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, RX_ADR_WIDTH); // D′?óê???μ??·
SPI_RW_Reg(WRITE_REG + EN_AA, ENAA_DisableALL);  //???1×??ˉó|′e
SPI_RW_Reg(WRITE_REG + SETUP_RETR,AutoReTx_Disable);//???1×??ˉ??·¢
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);  //  ?êDí?óê?μ??·??óD?μμà0
SPI_RW_Reg(WRITE_REG + RF_CH, 0);        //   éè??D?μà1¤×÷?a2.4GHZ£?ê?·¢±?D?ò???
SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //éè???óê?êy?Y3¤?è
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x27);   //éè??·¢é??ù?ê?a250kHZ£?·¢é?1|?ê?a×?′ó?μ0dB
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);   // IRQê?·¢íê3é?D???ìó|£?16??CRC £?·¢?í
        CE_Pin(1);
}
/**************************************************/


/**************************************************
Function: TX_Mode();


Description:
  This function initializes one nRF24L01 device to
  TX mode, set TX address, set RX address for auto.ack,
  fill TX payload, select RF channel, datarate & TX pwr.
  PWR_UP is set, CRC(2 bytes) is enabled, & PRIM:TX.


  ToDo: One high pulse(>10us) on CE will now send this
  packet and expext an acknowledgment from the RX device.
**************************************************/
void TX_Mode(void)
{
CE_Pin(0);

  SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);    // D′±?μ?μ??·
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, RX_ADR_WIDTH); // D′?óê???μ??·
SPI_RW_Reg(WRITE_REG + EN_AA, ENAA_DisableALL);  //???1×??ˉó|′e
SPI_RW_Reg(WRITE_REG + SETUP_RETR,AutoReTx_Disable);//???1×??ˉ??·¢
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);  //  ?êDí?óê?μ??·??óD?μμà0
SPI_RW_Reg(WRITE_REG + RF_CH, 0);        //   éè??D?μà1¤×÷?a2.4GHZ£?ê?·¢±?D?ò???
SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //éè???óê?êy?Y3¤?è
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x27);   //éè??·¢é??ù?ê?a250kHZ£?·¢é?1|?ê?a×?′ó?μ0dB
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e);   // IRQê?·¢íê3é?D???ìó|£?16??CRC £?·¢?í
CE_Pin(1);


}




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


void nRF24L01_Init(unsigned char Mode)
{
TestBuf = SPI_Read(RX_ADDR_P4);//return is 0xC5,if connection is ok


if(Mode == nRF_TX_Mode)
TX_Mode();
else RX_Mode();
delay_1ms(2);//24L01 掉电模式到待机模式需要1.5ms
}




void nRF24L01_Send(void)
{
SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // Writes data to TX payload
}


void nRF24L01_Revceive(void)
{
TestBuf = SPI_Read(STATUS);
SPI_RW_Reg(WRITE_REG+STATUS,TestBuf);
if(TestBuf&RX_OK)
{
SPI_Read_Buf(RD_RX_PLOAD, rx_buf, RX_PLOAD_WIDTH);
SPI_RW_Reg(FLUSH_RX, 0xff);
//Cycle_Cnt = (rx_buf[4]<<8)|rx_buf[5];
}

}
/*
 * 函数名:NRF_Check
 * 描述  :主要用于NRF与MCU是否正常连接
 * 输入  :无
 * 输出  :SUCCESS/ERROR 连接正常/连接失败
 * 调用  :外部调用
 */
uchar NRF_Check(void)
{
uchar buf[5]={0xC2,0xC2,0xC2,0xC2,0xC2};
uchar buf1[5];
uchar i; 
 
/*写入5个字节的地址.  */  
SPI_Write_Buf(WRITE_REG+TX_ADDR,buf,5);


/*读出写入的地址 */
SPI_Read_Buf(TX_ADDR,buf1,5); 
 
/*比较*/               
for(i=0;i<5;i++)
{       
if(buf1[i]!=0xC2)
break;            

      
if(i==5)
return 1 ;        //MCU与NRF成功连接 
else
return 0 ;        //MCU与NRF不正常连接
              
}


void nRF24L01_IO_set(void)
{
      P4DIR |= BIT4;         //ce
      //P4OUT = BIT4;         //ce
      P4DIR |= BIT5;         //csn
      P5DIR |= BIT3;         //sck
      P5DIR |= BIT2;         //mosi out
      P5DIR &=~BIT1;         //MISO IN 
      P1DIR &=~BIT4;         //IRQ
      
      SCK_Pin(0);
      CE_Pin(0);
}


main.c

/****************POWSOS__430******************************
程序功能:24L01无线模块间隔1s发送一次数据
----------------------------------------------------------
测试说明:观察接收板D1~D7
*********************************************************/
#include  <msp430x14x.h>
#include "24l01.h"
extern unsigned char TestBuf;
/*******************************************
函数名称:Init_Clock
功    能:设置系统时钟选用外部晶振8M
参    数:无
返回值  :无
********************************************/
void Init_Clock(void)
{
    unsigned char i;
  /*------选择系统主时钟为8MHz-------*/
    BCSCTL1 &= ~XT2OFF;                 //打开XT2高频晶体振荡器
    do
    {
        IFG1 &= ~OFIFG;                 //清除晶振失败标志
        for (i = 0xFF; i > 0; i--);     //等待8MHz晶体起振
    }
    while ((IFG1 & OFIFG));             //晶振失效标志仍然存在?
    BCSCTL2 |= SELM_2 + SELS;           //MCLK和SMCLK选择高频晶振
}


int main( void )
{


    WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT 
    Init_Clock();
    nRF24L01_IO_set();
    NRF_Check();
    nRF24L01_Init(nRF_TX_Mode);


    while(1)
    {
  
      nRF24L01_Send();
     delay_100ms(10);
 
    }
    
}

  //实现收发改地址即可



良心货,有学习MSP430程序的网友拿去,各种例题,源码,可以直接拿来用的例程。 程序目录: MSP430F149+1602数码显示实时时钟 MSP430F149,IAR,ADC采样之后对太阳点光源进行跟踪 MSP430F149 AD7705程序 MSP430 BH1750测量光强(已测试) Launch Pad NOKIA5110 Clock 使用MSP430单片机控制超声波测距并使用5110显示 基于MSP430的MP3 源码+电路图+PCB+字库+SD卡 基于MSP430单片机控制坦克打靶C语言源程序代码 MSP430F149 GSM基本控制,初始化接收短息,解读短信 ADXL重力加速度传感器实现计步器程序(利用MSP430F135实现) 利用MSP430的PWM功能实现电机的调速(实现精确调速) TI公司MSP430芯片评估板lantchpad的电容式触摸板的源码 基于MSP430F149单片机的1602程序代码 基于MSP430F149单片机nRF24L01无线通信程序 基于MSP430F149单片机的串口0驱动程序 基于MSP430F149单片机的温湿度传感器SHT1X驱动程序 基于MSP430F149的12864的显示图片 基于MSP430F149的AD转换,在液晶1602上显示 基于MSP430F149的触摸手写程序 基于MSP430F149为主芯片下的红外线解码资料源程序 基于MSP430F249的GPS+GPRS车载GPS 基于MSP430单片机的电子式互感器采集器的程序 基于MSP430单片机的智能电表 基于MSP430的触摸屏校正程序 基于MSP430的温度传感器DS18B20对温度的检测显示 基于单片机MSP430的DS1302的时钟芯片编程,实现时钟显示 利用MSP430实现的超低功耗触摸屏 使用MSP430低功耗微处理器制作的斜度计(开发平台是IAR) 通过MSP430(149)单片机控制DHT11温湿度传感器 MSP430F149单片机与RF2401硬件SPI无线通信 MSP430f149控制LCD12864显示汉字、字母 MSP430F149通过SPI接口控制ADS1216 MSP430F449实现频率测量,呼吸灯,自己写的,调试OK MSP430x13x, MSP430F14x, MSP430F15x, MSP430F16x Code Examples MSP430x14x读写FM25L256程序 MSP430x14x模糊逻辑马达控制-源程序,已通过测试 MSP430单片机短息收发程序 MSP430平台 AM2301测量光强(已测试) MSP430热电偶开发程序,高精度测量,带标定 MSP430热电阻开发,高精度测量,带标定,修正 MSP430小车解决方案含Protel源代码 MSP430与指纹识别
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值