【MSPM0G3507+NRF24L01】2.4G无线传输加串口屏显示(附发送端和接收端完整代码)

一、所用材料

        1、TI官方的MSPM0G3507

        2、NRF24L01

二、实现功能

        两块单片机之间通过NRF24L01实现无线通信,接收的数据通过串口屏显示。两块单片机都是用TI官方的MSPM0G3507。

三、实现过程

  3.1 CCS配置

        发送端和接收端配置相同

        1、开启蓝色LED灯

        2、分别开启CS CE IRQ

        3、配置时钟

         4、开启硬件SPI

         5、开启串口

3.2 文件路径

        

        别忘记添加头文件的路径

3.3 添加代码

        发送端和接收端除了empty.c,其余文件相同        

       1、board.c

#include "board.h"
#include "stdio.h"
#include "string.h"
#include "stdio.h"
#include <string.h>
#include <stdarg.h>

volatile unsigned int delay_times = 0;
volatile unsigned char uart_data = 0;

void board_init(void)
{
    // SYSCFG初始化
    SYSCFG_DL_init();

}

//搭配滴答定时器实现的精确us延时
void delay_us(unsigned long __us)
{
    uint32_t ticks;
    uint32_t told, tnow, tcnt = 38;

    // 计算需要的时钟数 = 延迟微秒数 * 每微秒的时钟数
    ticks = __us * (32000000 / 1000000);

    // 获取当前的SysTick值
    told = SysTick->VAL;

    while (1)
    {
        // 重复刷新获取当前的SysTick值
        tnow = SysTick->VAL;

        if (tnow != told)
        {
            if (tnow < told)
                tcnt += told - tnow;
            else
                tcnt += SysTick->LOAD - tnow + told;

            told = tnow;

            // 如果达到了需要的时钟数,就退出循环
            if (tcnt >= ticks)
                break;
        }
    }
}
//搭配滴答定时器实现的精确ms延时
void delay_ms(unsigned long ms)
{
    delay_us( ms * 1000 );
}

void delay_1us(unsigned long __us){ delay_us(__us); }
void delay_1ms(unsigned long ms){ delay_ms(ms); }


//串口发送单个字符
void uart1_send_char(char ch)
{
    //当串口0忙的时候等待,不忙的时候再发送传进来的字符
    while( DL_UART_isBusy(UART_1_INST) == true );
    //发送单个字符
    DL_UART_Main_transmitData(UART_1_INST, ch);

}
//串口发送字符串
void uart1_send_string(char* str)
{
    //当前字符串地址不在结尾 并且 字符串首地址不为空
    while(*str!=0&&str!=0)
    {
        //发送字符串首地址中的字符,并且在发送完成之后首地址自增
        uart1_send_char(*str++);
    }
}


void uart0_send_char(char ch)
{
    //当串口0忙的时候等待,不忙的时候再发送传进来的字符
    while( DL_UART_isBusy(UART_0_INST) == true );
    //发送单个字符
    DL_UART_Main_transmitData(UART_0_INST, ch);

}
//串口发送字符串
void uart0_send_string(char* str)
{
    //当前字符串地址不在结尾 并且 字符串首地址不为空
    while(*str!=0&&str!=0)
    {
        //发送字符串首地址中的字符,并且在发送完成之后首地址自增
        uart0_send_char(*str++);
    }
}

//int fputc(int ch, FILE *f)
//{
//    DL_UART_transmitData(UART_1_INST, (uint8_t)ch);//发送数据
//    while(DL_UART_isBusy(UART_1_INST));
//    return (ch);
//}
//
//int fputs(const char *_ptr, register FILE *_fp)
//{
//    unsigned int i, len;
//    len = strlen(_ptr);
//    for(i=0 ; i<len ; i++)
//        DL_UART_transmitData(UART_1_INST, (uint8_t)_ptr[i]);//发送数据
//    return len;
//}

       2、board.h

#ifndef __BOARD_H__
#define __BOARD_H__

#include <ti/driverlib/m0p/dl_interrupt.h>
#include "ti_msp_dl_config.h"


void board_init(void);

void delay_us(unsigned long __us);
void delay_ms(unsigned long ms);
void delay_1us(unsigned long __us);
void delay_1ms(unsigned long ms);

void uart1_send_char(char ch);
void uart1_send_string(char* str);

void uart0_send_char(char ch);
void uart0_send_string(char* str);

#endif

        3、NRF24L01.c   


#include <NRF24L01.h>

#include "stdio.h"


const char *g_ErrorString = "RF24L01 is not find !...";


void drv_delay_500Ms( unsigned int ms)
{
      while(ms--)
      {
            delay_ms(500);
      }
}

/**
  * @brief :NRF24L01读寄存器
  * @param :
           @Addr:寄存器地址
  * @note  :地址在设备中有效
  * @retval:读取的数据
  */
uint8_t NRF24L01_Read_Reg( uint8_t RegAddr )
{
    uint8_t btmp;

    RF24L01_SET_CS_LOW( );       //片选

    drv_spi_read_write_byte( NRF_READ_REG | RegAddr );    //读命令 地址
    btmp = drv_spi_read_write_byte( 0xFF );               //读数据

    RF24L01_SET_CS_HIGH( );      //取消片选

    return btmp;
}

/**
  * @brief :NRF24L01读指定长度的数据
  * @param :
  * @reg:地址
  * @pBuf:数据存放地址
  * @len:数据长度
  * @note  :数据长度不超过255,地址在设备中有效
  * @retval:读取状态
  */
void NRF24L01_Read_Buf( uint8_t RegAddr, uint8_t *pBuf, uint8_t len )
{
      uint8_t btmp;

      RF24L01_SET_CS_LOW( );                                    //片选

      drv_spi_read_write_byte( NRF_READ_REG | RegAddr );        //读命令 地址
      for( btmp = 0; btmp < len; btmp ++ )
      {
            *( pBuf + btmp ) = drv_spi_read_write_byte( 0xFF ); //读数据
      }
      RF24L01_SET_CS_HIGH( );                                   //取消片选
}

/**
  * @brief :NRF24L01写寄存器
  * @param :无
  * @note  :地址在设备中有效
  * @retval:读写状态
  */
void NRF24L01_Write_Reg( uint8_t RegAddr, uint8_t Value )
{
    RF24L01_SET_CS_LOW( );                                   //片选

    drv_spi_read_write_byte( NRF_WRITE_REG | RegAddr );      //写命令 地址
    drv_spi_read_write_byte( Value );                        //写数据

    RF24L01_SET_CS_HIGH( );                                  //取消片选
}

/**
  * @brief :NRF24L01写指定长度的数据
  * @param :
  * @reg:地址
  * @pBuf:写入的数据地址
  * @len:数据长度
  * @note  :数据长度不超过255,地址在设备中有效
  * @retval:写状态
  */
void NRF24L01_Write_Buf( uint8_t RegAddr, uint8_t *pBuf, uint8_t len )
{
    uint8_t i;

    RF24L01_SET_CS_LOW( );                                //片选

    drv_spi_read_write_byte( NRF_WRITE_REG | RegAddr );   //写命令 地址
    for( i = 0; i < len; i ++ )
    {
        drv_spi_read_write_byte( *( pBuf + i ) );         //写数据
    }

    RF24L01_SET_CS_HIGH( );                               //取消片选
}

/**
  * @brief :清空TX缓冲区
  * @param :无
  * @note  :无
  * @retval:无
  */
void NRF24L01_Flush_Tx_Fifo ( void )
{
    RF24L01_SET_CS_LOW( );                 //片选

    drv_spi_read_write_byte( FLUSH_TX );   //清TX FIFO命令

    RF24L01_SET_CS_HIGH( );                //取消片选
}

/**
  * @brief :清空RX缓冲区
  * @param :无
  * @note  :无
  * @retval:无
  */
void NRF24L01_Flush_Rx_Fifo( void )
{
    RF24L01_SET_CS_LOW( );                //片选

    drv_spi_read_write_byte( FLUSH_RX );  //清RX FIFO命令

    RF24L01_SET_CS_HIGH( );               //取消片选
}

/**
  * @brief :重新使用上一包数据
  * @param :无
  * @note  :无
  * @retval:无
  */
void NRF24L01_Reuse_Tx_Payload( void )
{
    RF24L01_SET_CS_LOW( );                   //片选

    drv_spi_read_write_byte( REUSE_TX_PL );  //重新使用上一包命令

    RF24L01_SET_CS_HIGH( );                  //取消片选
}

/**
  * @brief :NRF24L01空操作
  * @param :无
  * @note  :无
  * @retval:无
  */
void NRF24L01_Nop( void )
{
    RF24L01_SET_CS_LOW( );                //片选

    drv_spi_read_write_byte( NOP );        //空操作命令

    RF24L01_SET_CS_HIGH( );                //取消片选
}

/**
  * @brief :NRF24L01读状态寄存器
  * @param :无
  * @note  :无
  * @retval:RF24L01状态
  */
uint8_t NRF24L01_Read_Status_Register( void )
{
    uint8_t Status;

    RF24L01_SET_CS_LOW( );                //片选

    Status = drv_spi_read_write_byte( NRF_READ_REG + STATUS );        //读状态寄存器

    RF24L01_SET_CS_HIGH( );                //取消片选

    return Status;
}

/**
  * @brief :NRF24L01清中断
  * @param :
           @IRQ_Source:中断源
  * @note  :无
  * @retval:清除后状态寄存器的值
  */
uint8_t NRF24L01_Clear_IRQ_Flag( uint8_t IRQ_Source )
{
      uint8_t btmp = 0;

      IRQ_Source &= ( 1 << RX_DR ) | ( 1 << TX_DS ) | ( 1 << MAX_RT );        //中断标志处理
      btmp = NRF24L01_Read_Status_Register( );                  //读状态寄存器

      RF24L01_SET_CS_LOW( );                                    //片选
      drv_spi_read_write_byte( NRF_WRITE_REG + STATUS );        //写状态寄存器命令
      drv_spi_read_write_byte( IRQ_Source | btmp );             //清相应中断标志
      RF24L01_SET_CS_HIGH( );                                   //取消片选

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

/**
  * @brief :读RF24L01中断状态
  * @param :无
  * @note  :无
  * @retval:中断状态
  */
uint8_t RF24L01_Read_IRQ_Status( void )
{
      return ( NRF24L01_Read_Status_Register( ) & (( 1 << RX_DR ) | ( 1 << TX_DS ) | ( 1 << MAX_RT )));        //返回中断状态
}

 /**
  * @brief :读FIFO中数据宽度
  * @param :无
  * @note  :无
  * @retval:数据宽度
  */
uint8_t NRF24L01_Read_Top_Fifo_Width( void )
{
      uint8_t btmp;

      RF24L01_SET_CS_LOW( );                         //片选

      drv_spi_read_write_byte( R_RX_PL_WID );        //读FIFO中数据宽度命令
      btmp = drv_spi_read_write_byte( 0xFF );        //读数据

      RF24L01_SET_CS_HIGH( );                        //取消片选

      return btmp;
}

 /**
  * @brief :读接收到的数据
  * @param :无
  * @note  :无
  * @retval:
           @pRxBuf:数据存放地址首地址
  */
uint8_t NRF24L01_Read_Rx_Payload( uint8_t *pRxBuf )
{
      uint8_t Width, PipeNum;

      PipeNum = ( NRF24L01_Read_Reg( STATUS ) >> 1 ) & 0x07;         //读接收状态
      Width = NRF24L01_Read_Top_Fifo_Width( );                       //读接收数据个数

      RF24L01_SET_CS_LOW( );                                         //片选
      drv_spi_read_write_byte( RD_RX_PLOAD );                        //读有效数据命令

      for( PipeNum = 0; PipeNum < Width; PipeNum ++ )
      {
              *( pRxBuf + PipeNum ) = drv_spi_read_write_byte( 0xFF );   //读数据
      }
      RF24L01_SET_CS_HIGH( );                                        //取消片选
      NRF24L01_Flush_Rx_Fifo( );                                     //清空RX FIFO

      return Width;
}

 /**
  * @brief :发送数据(带应答)
  * @param :
  * @pTxBuf:发送数据地址
  * @len:长度
  * @note  :一次不超过32个字节
  * @retval:无
  */
void NRF24L01_Write_Tx_Payload_Ack( uint8_t *pTxBuf, uint8_t len )
{
      uint8_t btmp;
      uint8_t length = ( len > 32 ) ? 32 : len;            //数据长达大约32 则只发送32个

      NRF24L01_Flush_Tx_Fifo( );                           //清TX FIFO

      RF24L01_SET_CS_LOW( );                               //片选
      drv_spi_read_write_byte( WR_TX_PLOAD );              //发送命令

      for( btmp = 0; btmp < length; btmp ++ )
      {
            drv_spi_read_write_byte( *( pTxBuf + btmp ) );  //发送数据
      }
      RF24L01_SET_CS_HIGH( );                               //取消片选
}

 /**
  * @brief :发送数据(不带应答)
  * @param :
  * @pTxBuf:发送数据地址
  * @len:长度
  * @note  :一次不超过32个字节
  * @retval:无
  */
void NRF24L01_Write_Tx_Payload_NoAck( uint8_t *pTxBuf, uint8_t len )
{
      if( len > 32 || len == 0 )
      {
            return ;                                   //数据长度大于32 或者等于0 不执行
      }

      RF24L01_SET_CS_LOW( );                           //片选
      drv_spi_read_write_byte( WR_TX_PLOAD_NACK );     //发送命令
      while( len-- )
      {
          drv_spi_read_write_byte( *pTxBuf );          //发送数据
          pTxBuf++;
      }
      RF24L01_SET_CS_HIGH( );                           //取消片选
}

 /**
  * @brief :在接收模式下向TX FIFO写数据(带ACK)
  * @param :
  *                        @pData:数据地址
  *                        @len:长度
  * @note  :一次不超过32个字节
  * @retval:无
  */
void NRF24L01_Write_Tx_Payload_InAck( uint8_t *pData, uint8_t len )
{
    uint8_t btmp;

    len = ( len > 32 ) ? 32 : len;                      //数据长度大于32个则只写32个字节

    RF24L01_SET_CS_LOW( );                              //片选
    drv_spi_read_write_byte( W_ACK_PLOAD );             //命令
    for( btmp = 0; btmp < len; btmp ++ )
    {
        drv_spi_read_write_byte( *( pData + btmp ) );   //写数据
    }
    RF24L01_SET_CS_HIGH( );                             //取消片选
}

 /**
  * @brief :设置发送地址
  * @param :
  *                        @pAddr:地址存放地址
  *                        @len:长度
  * @note  :无
  * @retval:无
  */
void NRF24L01_Set_TxAddr( uint8_t *pAddr, uint8_t len )
{
        len = ( len > 5 ) ? 5 : len;                  //地址不能大于5个字节
    NRF24L01_Write_Buf( TX_ADDR, pAddr, len );        //写地址
}

 /**
  * @brief :设置接收通道地址
  * @param :
  *                        @PipeNum:通道
  *                        @pAddr:地址存肥着地址
  *                        @Len:长度
  * @note  :通道不大于5 地址长度不大于5个字节
  * @retval:无
  */
void NRF24L01_Set_RxAddr( uint8_t PipeNum, uint8_t *pAddr, uint8_t Len )
{
    Len = ( Len > 5 ) ? 5 : Len;
    PipeNum = ( PipeNum > 5 ) ? 5 : PipeNum;                //通道不大于5 地址长度不大于5个字节

    NRF24L01_Write_Buf( RX_ADDR_P0 + PipeNum, pAddr, Len );        //写入地址
}

 /**
  * @brief :设置通信速度
  * @param :
  *                        @Speed:速度
  * @note  :无
  * @retval:无
  */
void NRF24L01_Set_Speed( nRf24l01SpeedType Speed )
{
        uint8_t btmp = 0;

        btmp = NRF24L01_Read_Reg( RF_SETUP );
        btmp &= ~( ( 1<<5 ) | ( 1<<3 ) );

        if( Speed == SPEED_250K )                //250K
        {
                btmp |= ( 1<<5 );
        }
        else if( Speed == SPEED_1M )   //1M
        {
                   btmp &= ~( ( 1<<5 ) | ( 1<<3 ) );
        }
        else if( Speed == SPEED_2M )   //2M
        {
                btmp |= ( 1<<3 );
        }

        NRF24L01_Write_Reg( RF_SETUP, btmp );
}

 /**
  * @brief :设置功率
  * @param :
  *                        @Speed:速度
  * @note  :无
  * @retval:无
  */
void NRF24L01_Set_Power( nRf24l01PowerType Power )
{
      uint8_t btmp;

      btmp = NRF24L01_Read_Reg( RF_SETUP ) & ~0x07;
      switch( Power )
      {
            case POWER_F18DBM:
                btmp |= PWR_18DB;
                break;
            case POWER_F12DBM:
                btmp |= PWR_12DB;
                break;
            case POWER_F6DBM:
                btmp |= PWR_6DB;
                break;
            case POWER_0DBM:
                btmp |= PWR_0DB;
                break;
            default:
                break;
      }
      NRF24L01_Write_Reg( RF_SETUP, btmp );
}

 /**
  * @brief :设置频率
  * @param :
  *                        @FreqPoint:频率设置参数
  * @note  :值不大于127
  * @retval:无
  */
void RF24LL01_Write_Hopping_Point( uint8_t FreqPoint )
{
      NRF24L01_Write_Reg(  RF_CH, FreqPoint & 0x7F );
}

/**
  * @brief :NRF24L01检测
  * @param :无
  * @note  :无
  * @retval:无
  */
void NRF24L01_check( void )
{
      uint8_t i;
      uint8_t error = 0;
      uint8_t buf[5]={ 0XA5, 0XA5, 0XA5, 0XA5, 0XA5 };
      uint8_t read_buf[ 5 ] = { 0 };

      while( 1 )
      {
            NRF24L01_Write_Buf( TX_ADDR, buf, 5 );        //写入5个字节的地址
            NRF24L01_Read_Buf( TX_ADDR, read_buf, 5 );    //读出写入的地址
            for( i = 0; i < 5; i++ )
            {
                  if( buf[ i ] != read_buf[ i ] )
                  {
                        break;
                  }
            }

            if( 5 == i )
            {
                  break;
            }
            else
            {
                  error++;
                  if( error >= 3 )
                  {
                    break;
                  }
                  //测试错误
                  uart0_send_string("NRF24L01 ERROR  FILE:NRF24L01.C\r\n");
            }
            drv_delay_500Ms( 2 );
      }
      uart0_send_string("Successful configuration\r\n");
}

 /**
  * @brief :设置模式
  * @param :
  * @Mode:模式发送模式或接收模式
  * @note  :无
  * @retval:无
  */
void RF24L01_Set_Mode( nRf24l01ModeType Mode )
{
      uint8_t controlreg = 0;
      controlreg = NRF24L01_Read_Reg( CONFIG );

      if( Mode == MODE_TX )
      {
            controlreg &= ~( 1<< PRIM_RX );
      }
      else
      {
            if( Mode == MODE_RX )
            {
                  controlreg |= ( 1<< PRIM_RX );
            }
      }

      NRF24L01_Write_Reg( CONFIG, controlreg );
}

/**
  * @brief :NRF24L01发送一次数据
  * @param :
  * @txbuf:待发送数据首地址
  * @Length:发送数据长度
  * @note  :无
  * @retval:
  *           MAX_TX:达到最大重发次数
  *           TX_OK:发送完成
  *           0xFF:其他原因
  */
uint8_t NRF24L01_TxPacket( uint8_t *txbuf, uint8_t Length )
{
        uint8_t l_Status = 0;
        uint16_t l_MsTimes = 0;

        RF24L01_SET_CS_LOW( );   //片选
        drv_spi_read_write_byte( FLUSH_TX );
        RF24L01_SET_CS_HIGH( );

        RF24L01_SET_CE_LOW( );
        NRF24L01_Write_Buf( WR_TX_PLOAD, txbuf, Length );   //写数据到TX BUF 32字节  TX_PLOAD_WIDTH
        RF24L01_SET_CE_HIGH( );                             //启动发送
        while( 0 != RF24L01_GET_IRQ_STATUS( ))
        {
                delay_ms( 5 );
//        printf("error-1\r\n");
            if( 500 == l_MsTimes++ )                              //500ms还没有发送成功,重新初始化设备
            {

                NRF24L01_Gpio_Init_transmit( );

                RF24L01_Init( );
                RF24L01_Set_Mode( MODE_TX );
                break;
            }
        }
        l_Status = NRF24L01_Read_Reg(STATUS);            //读状态寄存器
        NRF24L01_Write_Reg( STATUS, l_Status );          //清除TX_DS或MAX_RT中断标志

        if( l_Status & MAX_TX )                          //达到最大重发次数
        {
                NRF24L01_Write_Reg( FLUSH_TX,0xff );      //清除TX FIFO寄存器
                return MAX_TX;
        }
        if( l_Status & TX_OK )        //发送完成
        {
                return TX_OK;
        }

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


void key_gpio_config(void)
{


}

 /**
  * @brief :RF24L01引脚初始化
  * @param :无
  * @note  :无
  * @retval:无
  */
void NRF24L01_Gpio_Init_receive( void )
{
      NVIC_EnableIRQ(GPIO_INT_IRQN);//开启按键引脚的GPIOA端口中断

      RF24L01_SET_CE_LOW( );
      RF24L01_SET_CS_HIGH( );
}



/************************************************
函数名称 : BSP_KEY_EXTI_IRQHandler
功    能 : 中断处理函数
参    数 : 无
返 回 值 : 无
作    者 : LCEDA
*************************************************/
extern uint8_t g_RF24L01RxBuffer[30];

void Buff_Clear(void)
{
      for(int i = 0; i < 30; i++)
      {
            g_RF24L01RxBuffer[i] = 0;
      }
}


void GROUP1_IRQHandler(void)//Group1的中断服务函数
{
    //读取Group1的中断寄存器并清除中断标志位
    switch( DL_Interrupt_getPendingGroup(DL_INTERRUPT_GROUP_1) )
    {

        case GPIO_INT_IIDX:

            if(RF24L01_GET_IRQ_STATUS() == 0)  // IRQ为低电平
            {
                DL_GPIO_togglePins(LED_PORT, LED_BLUE_PIN);
                NRF24L01_RxPacket(g_RF24L01RxBuffer);  //接收数据
                //printf("data = %s",g_RF24L01RxBuffer );//输出数据

                RF24L01_SET_CS_LOW( );                //片选
                drv_spi_read_write_byte( FLUSH_RX );//清除RX FIFO寄存器
                RF24L01_SET_CS_HIGH( );

            }
            else// IRQ为高电平
            {

            }

        break;
    }
}




/**
  * @brief :NRF24L01接收数据
  * @param :
  *                        @rxbuf:接收数据存放地址
  * @note  :无
  * @retval:接收的数据个数
  */
uint8_t NRF24L01_RxPacket( uint8_t *rxbuf )
{
        uint8_t l_Status = 0, l_RxLength = 0;

        l_Status = NRF24L01_Read_Reg( STATUS );               //读状态寄存器
        NRF24L01_Write_Reg( STATUS,l_Status );                //清中断标志
        if( l_Status & RX_OK)        //接收到数据
        {
                l_RxLength = NRF24L01_Read_Reg( R_RX_PL_WID );        //读取接收到的数据个数
                NRF24L01_Read_Buf( RD_RX_PLOAD,rxbuf,l_RxLength );    //接收到数据
                NRF24L01_Write_Reg( FLUSH_RX,0xff );                  //清除RX FIFO
                return l_RxLength;
        }
        return 0;    //没有收到数据
}

 /**
  * @brief :RF24L01引脚初始化
  * @param :无
  * @note  :无
  * @retval:无
  */
void NRF24L01_Gpio_Init_transmit( void )
{
    NVIC_EnableIRQ(GPIO_INT_IRQN);//开启按键引脚的GPIOA端口中断

    RF24L01_SET_CE_LOW( );
    RF24L01_SET_CS_HIGH( );
}


 /**
  * @brief :RF24L01模块初始化
  * @param :无
  * @note  :无
  * @retval:无
  */
void RF24L01_Init( void )
{
    uint8_t addr[5] = {INIT_ADDR};

    RF24L01_SET_CE_HIGH( );
    NRF24L01_Clear_IRQ_Flag( IRQ_ALL );
#if DYNAMIC_PACKET == 1

    NRF24L01_Write_Reg( DYNPD, ( 1 << 0 ) );   //使能通道1动态数据长度
    NRF24L01_Write_Reg( FEATRUE, 0x07 );
    NRF24L01_Read_Reg( DYNPD );
    NRF24L01_Read_Reg( FEATRUE );

#elif DYNAMIC_PACKET == 0

    L01_WriteSingleReg( L01REG_RX_PW_P0, FIXED_PACKET_LEN );        //固定数据长度

#endif        //DYNAMIC_PACKET

    NRF24L01_Write_Reg( CONFIG,     /*( 1<<MASK_RX_DR ) |*/         //接收中断*/
                                      ( 1 << EN_CRC ) |     //使能CRC 1个字节
                                      ( 1 << PWR_UP ) );    //开启设备
    NRF24L01_Write_Reg( EN_AA, ( 1 << ENAA_P0 ) );          //通道0自动应答
    NRF24L01_Write_Reg( EN_RXADDR, ( 1 << ERX_P0 ) );       //通道0接收
    NRF24L01_Write_Reg( SETUP_AW, AW_5BYTES );              //地址宽度 5个字节
    NRF24L01_Write_Reg( SETUP_RETR, ARD_4000US |
                        ( REPEAT_CNT & 0x0F ) );            //重复等待时间 250us
    NRF24L01_Write_Reg( RF_CH, 00 );                        //初始化通道
    NRF24L01_Write_Reg( RF_SETUP, 0x26 );

    NRF24L01_Set_TxAddr( &addr[0], 5 );                      //设置TX地址
    NRF24L01_Set_RxAddr( 0, &addr[0], 5 );                   //设置RX地址
}

         4、NRF24L01.h


#ifndef __NRF24L01_H__
#define __NRF24L01_H__

#include "drv_spi.h"

/** 配置和选项定义 */
#define DYNAMIC_PACKET      1                 //1:动态数据包, 0:固定
#define FIXED_PACKET_LEN    32                //包长度
#define REPEAT_CNT          15                //重复次数
#define INIT_ADDR           0x34,0x43,0x10,0x10,0x01


/** 口线操作函数定义 */

#define RF24L01_SET_CE_HIGH( )        DL_GPIO_setPins(GPIO_PORT, GPIO_CE_PIN)
#define RF24L01_SET_CE_LOW( )         DL_GPIO_clearPins(GPIO_PORT, GPIO_CE_PIN)

#define RF24L01_SET_CS_HIGH( )        spi_set_nss_high( )
#define RF24L01_SET_CS_LOW( )         spi_set_nss_low( )

#define RF24L01_GET_IRQ_STATUS( )     ( ( ( DL_GPIO_readPins(GPIO_PORT,GPIO_IRQ_PIN) & GPIO_IRQ_PIN ) > 0 ) ? 1 : 0 )  //IRQ状态


typedef enum ModeType
{
        MODE_TX = 0,
        MODE_RX
}nRf24l01ModeType;

typedef enum SpeedType
{
        SPEED_250K = 0,
        SPEED_1M,
        SPEED_2M
}nRf24l01SpeedType;

typedef enum PowerType
{
        POWER_F18DBM = 0,
        POWER_F12DBM,
        POWER_F6DBM,
        POWER_0DBM
}nRf24l01PowerType;


/** NRF24L01定义 */
//
//寄存器操作命令
#define NRF_READ_REG    0x00        //读配置寄存器,低5位为寄存器地址
#define NRF_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 R_RX_PL_WID     0x60
#define NOP             0xFF        //空操作,可以用来读状态寄存器
#define W_ACK_PLOAD     0xA8
#define WR_TX_PLOAD_NACK 0xB0
//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        //设置地址宽度(所有数据通道) bit0~1: 00,3字节 01,4字节, 02,5字节
#define SETUP_RETR      0x04        //建立自动重发;bit0~3:自动重发计数器;bit4~7:自动重发延时 250*x+86us
#define RF_CH           0x05        //RF通道,bit0~6工作通道频率
#define RF_SETUP        0x06        //RF寄存器,bit3:传输速率( 0:1M 1:2M);bit1~2:发射功率;bit0:噪声放大器增益
#define STATUS          0x07        //状态寄存器;bit0:TX FIFO满标志;bit1~3:接收数据通道号(最大: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 NRF_FIFO_STATUS 0x17        //FIFO状态寄存器;bit0:RX FIFO寄存器空标志;bit1:RX FIFO满标志;bit2~3保留
                                    //bit4:TX FIFO 空标志;bit5:TX FIFO满标志;bit6:1,循环发送上一数据包.0,不循环
#define DYNPD           0x1C
#define FEATRUE         0x1D
//

//位定义
#define MASK_RX_DR           6
#define MASK_TX_DS           5
#define MASK_MAX_RT          4
#define EN_CRC               3
#define CRCO                 2
#define PWR_UP               1
#define PRIM_RX              0

#define ENAA_P5              5
#define ENAA_P4              4
#define ENAA_P3              3
#define ENAA_P2              2
#define ENAA_P1              1
#define ENAA_P0              0

#define ERX_P5               5
#define ERX_P4               4
#define ERX_P3               3
#define ERX_P2               2
#define ERX_P1               1
#define ERX_P0               0

#define AW_RERSERVED         0x0
#define AW_3BYTES            0x1
#define AW_4BYTES            0x2
#define AW_5BYTES            0x3

#define ARD_250US            (0x00<<4)
#define ARD_500US            (0x01<<4)
#define ARD_750US            (0x02<<4)
#define ARD_1000US           (0x03<<4)
#define ARD_2000US           (0x07<<4)
#define ARD_4000US           (0x0F<<4)
#define ARC_DISABLE           0x00
#define ARC_15                0x0F

#define CONT_WAVE             7
#define RF_DR_LOW             5
#define PLL_LOCK              4
#define RF_DR_HIGH            3
//bit2-bit1:
#define PWR_18DB              (0x00<<1)
#define PWR_12DB              (0x01<<1)
#define PWR_6DB               (0x02<<1)
#define PWR_0DB               (0x03<<1)

#define RX_DR                 6
#define TX_DS                 5
#define MAX_RT                4
//for bit3-bit1,
#define TX_FULL_0             0

#define RPD                   0

#define TX_REUSE              6
#define TX_FULL_1             5
#define TX_EMPTY              4
//bit3-bit2, reserved, only '00'
#define RX_FULL               1
#define RX_EMPTY              0

#define DPL_P5                5
#define DPL_P4                4
#define DPL_P3                3
#define DPL_P2                2
#define DPL_P1                1
#define DPL_P0                0

#define EN_DPL                2
#define EN_ACK_PAY            1
#define EN_DYN_ACK            0
#define IRQ_ALL  ( (1<<RX_DR) | (1<<TX_DS) | (1<<MAX_RT) )

uint8_t NRF24L01_Read_Reg( uint8_t RegAddr );
void NRF24L01_Read_Buf( uint8_t RegAddr, uint8_t *pBuf, uint8_t len );
void NRF24L01_Write_Reg( uint8_t RegAddr, uint8_t Value );
void NRF24L01_Write_Buf( uint8_t RegAddr, uint8_t *pBuf, uint8_t len );
void NRF24L01_Flush_Tx_Fifo ( void );
void NRF24L01_Flush_Rx_Fifo( void );
void NRF24L01_Reuse_Tx_Payload( void );
void NRF24L01_Nop( void );
uint8_t NRF24L01_Read_Status_Register( void );
uint8_t NRF24L01_Clear_IRQ_Flag( uint8_t IRQ_Source );
uint8_t RF24L01_Read_IRQ_Status( void );
uint8_t NRF24L01_Read_Top_Fifo_Width( void );
uint8_t NRF24L01_Read_Rx_Payload( uint8_t *pRxBuf );
void NRF24L01_Write_Tx_Payload_Ack( uint8_t *pTxBuf, uint8_t len );
void NRF24L01_Write_Tx_Payload_NoAck( uint8_t *pTxBuf, uint8_t len );
void NRF24L01_Write_Tx_Payload_InAck( uint8_t *pData, uint8_t len );
void NRF24L01_Set_TxAddr( uint8_t *pAddr, uint8_t len );
void NRF24L01_Set_RxAddr( uint8_t PipeNum, uint8_t *pAddr, uint8_t Len );
void NRF24L01_Set_Speed( nRf24l01SpeedType Speed );
void NRF24L01_Set_Power( nRf24l01PowerType Power );
void RF24LL01_Write_Hopping_Point( uint8_t FreqPoint );
void RF24L01_Set_Mode( nRf24l01ModeType Mode );
void  NRF24L01_check( void );
uint8_t NRF24L01_TxPacket( uint8_t *txbuf, uint8_t Length );
uint8_t NRF24L01_RxPacket( uint8_t *rxbuf );
void NRF24L01_Gpio_Init_transmit( void );
void NRF24L01_Gpio_Init_receive( void );
void RF24L01_Init( void );

void Buff_Clear(void);
void Rocker_Mode(void);
char Get_NRF24L01_ConnectFlag(void);

#endif

        5、drv_spi.c 


#include "drv_spi.h"
#include <stdio.h>


/** 硬件SPI */
#define SPI_WAIT_TIMEOUT       ((uint16_t)0xFFFF)

/**
  * @brief :SPI初始化(硬件)
  * @param :无
  * @note  :无
  * @retval:无
  */
void drv_spi_init( void )
{

}

/**
  * @brief :SPI收发一个字节
  * @param :
  * @TxByte: 发送的数据字节
  * @note  :非堵塞式,一旦等待超时,函数会自动退出
  * @retval:接收到的字节
  */
uint8_t drv_spi_read_write_byte( uint8_t TxByte )
{
      uint8_t l_Data = 0;
      uint16_t timeOut = 1000;

      //发送数据
      DL_SPI_transmitData8(SPI_INST, TxByte);

      //等待SPI总线空闲
      while(DL_SPI_isBusy(SPI_INST))
      {
            if(timeOut <= 0)
            {
                uart0_send_string("TransmitData TIMEOUT!!\r\n");
                  break;
            }

            timeOut--;

            delay_us(2);
      }


      l_Data = DL_SPI_receiveData8(SPI_INST);//读取接收数据

      timeOut = 500;

      //等待SPI总线空闲
      while(DL_SPI_isBusy(SPI_INST))
      {
            if(timeOut <= 0)
            {
                uart0_send_string("ReceiveData TIMEOUT!!\r\n");
                  break;
            }

            timeOut--;

            delay_us(2);
      }

      return l_Data;  //返回
}

/**
  * @brief :SPI收发字符串
  * @param :
  *                        @ReadBuffer: 接收数据缓冲区地址
  *                        @WriteBuffer:发送字节缓冲区地址
  *                        @Length:字节长度
  * @note  :非堵塞式,一旦等待超时,函数会自动退出
  * @retval:无
  */
void drv_spi_read_write_string( uint8_t* ReadBuffer, uint8_t* WriteBuffer, uint16_t Length )
{
    spi_set_nss_low( );//拉低片选
        while( Length-- )
        {
                *ReadBuffer = drv_spi_read_write_byte( *WriteBuffer ); //收发数据
                ReadBuffer++;
                WriteBuffer++;                                //读写地址加1
        }
    spi_set_nss_high( );//拉高片选
}

        6、drv_spi.h 


#ifndef __DRV_SPI_H__
#define __DRV_SPI_H__

#include "board.h"

#define spi_set_nss_high( )     DL_GPIO_setPins(GPIO_PORT, GPIO_CS_PIN)
#define spi_set_nss_low( )      DL_GPIO_clearPins(GPIO_PORT, GPIO_CS_PIN)

void drv_spi_init( void );
uint8_t drv_spi_read_write_byte( uint8_t TxByte );
void drv_spi_read_write_string( uint8_t* ReadBuffer, uint8_t* WriteBuffer, uint16_t Length );

#endif

        7、empty.c(发送端) 


#include "board.h"
#include <stdio.h>
#include "drv_spi.h"
#include "NRF24L01.h"

#define RECEIVING_MODE        1 // 1:接收模式 0:发送模式

uint8_t g_RF24L01RxBuffer[30];



int main(void)
{
    char charArray[] = "222";
    int value = 222;
    SYSCFG_DL_init();
    NVIC_EnableIRQ(GPIO_INT_IRQN);
    drv_spi_init( );

    NRF24L01_Gpio_Init_transmit( );
    //检测nRF24L01
    NRF24L01_check( );
    //NRF初始化
    RF24L01_Init( );
    RF24L01_Set_Mode( MODE_TX );//NRF发送模式        .
    uart0_send_string("MODE_TX\r\n");

    while(1)
    {
        sprintf(charArray, "%d", value++);
        NRF24L01_TxPacket((uint8_t*)charArray,4);//NRF发送数据
        uart0_send_string("Send\r\n");
        delay_ms(1000);
    }
}

//void GROUP1_IRQHandler(void)
//{
//    switch (DL_Interrupt_getPendingGroup(DL_INTERRUPT_GROUP_1)) {
//        case GPIO_INT_IIDX://检测到中断翻转PA0电平
//            DL_GPIO_togglePins(LED_PORT, LED_BLUE_PIN);
//    break;
//}
//}

        8、empty.h(接收端) 


#include "board.h"
#include <stdio.h>
#include "drv_spi.h"
#include "NRF24L01.h"

#define RECEIVING_MODE        1 // 1:接收模式 0:发送模式

uint8_t g_RF24L01RxBuffer[30];



int main(void)
{

    volatile char c,d;
    char a[30] = "main.n0.val=111\xff\xff\xff";
    char b[] = "asd\r\n";
    int value = 222;
    SYSCFG_DL_init();
    drv_spi_init( );

    NRF24L01_Gpio_Init_receive( );
//    检测NRF24L01
    NRF24L01_check( );
    //NRF初始化
    RF24L01_Init( );
    RF24L01_Set_Mode( MODE_RX );//NRF接收模式        .
    uart0_send_string("MODE_RX\r\n");

    while (1) {

        if( 0 != g_RF24L01RxBuffer[0]){
            uart0_send_string(g_RF24L01RxBuffer);
            value = atoi(g_RF24L01RxBuffer);
            sprintf(a, "main.n0.val=%d\xff\xff\xff", value);
            uart1_send_string(a);
            Buff_Clear();
        }

        d = DL_UART_receiveData(UART_0_INST);//接收数据
        if(d  == 'A'){

            sprintf(a, "main.n0.val=%d\xff\xff\xff", value++);
            uart1_send_string(a);

            DL_GPIO_togglePins(LED_PORT,LED_BLUE_PIN);
        }
        delay_cycles(3200000);
    }
}

  3.4 成果展示 

        将蓝色LED放入IRQ的中断中,也就是完成一次接收获发送数据就闪烁一次。同时,发送端每次发送的数据从222开始递增,接收端将数值显示在串口屏上。串口屏上是我室友的照片,所以打码处理了,大家主要看红色箭头指着的数字,是由发送端传输过来的。

2.4G无线传输

四、结语

        本文是在上一篇MSPM0L1306改进的,同样也是主要参考了嘉立创的资料,不过这次用的是MSPM0G3507,但原理都差不多,在下面为大家提供链接,有关串口屏的资料也可以参考下面的连接。

【MSPM0L1306+NRF24L01+CCS】实现2.4G无线传输

淘晶驰资料中心

  • 13
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值